Add flutter_localizations + intl, 12 ARB files (en/ru/es/de/fr/it/pt/zh/ja/ko/ar/hi), replace all hardcoded Russian UI strings with AppLocalizations, detect system locale on first launch, localise bottom nav bar labels, document rule in CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.7 KiB
Project Rules
Language
- All code comments must be written in English.
- All git commit messages must be written in English.
What NOT to commit
- The
examples/directory — it contains sample images and fixtures used for manual testing only. It is listed in.gitignoreand must never be staged or committed.
Localisation
Rule: Every table that stores human-readable text must have a companion {table}_translations
table. The base table always contains the English canonical text (used as fallback).
Translations live only in _translations tables — never as extra columns (name_ru, title_de).
SQL pattern
-- Base table — English canonical text always present
CREATE TABLE cuisines (
slug VARCHAR(50) PRIMARY KEY,
name TEXT NOT NULL,
sort_order SMALLINT NOT NULL DEFAULT 0
);
-- Translation companion
CREATE TABLE cuisine_translations (
cuisine_slug VARCHAR(50) REFERENCES cuisines(slug) ON DELETE CASCADE,
lang VARCHAR(10) NOT NULL,
name TEXT NOT NULL,
PRIMARY KEY (cuisine_slug, lang)
);
Query pattern
SELECT COALESCE(ct.name, c.name) AS name
FROM cuisines c
LEFT JOIN cuisine_translations ct ON ct.cuisine_slug = c.slug AND ct.lang = $lang
Already compliant tables
units + unit_translations, ingredient_categories + ingredient_category_translations,
ingredients + ingredient_translations + ingredient_aliases,
recipes + recipe_translations, cuisines + cuisine_translations,
tags + tag_translations, dish_categories + dish_category_translations,
dishes + dish_translations, recipe_ingredients + recipe_ingredient_translations,
recipe_steps + recipe_step_translations.
Rule when adding new entities
When adding a new entity with text fields, always create a {table}_translations
companion table and use LEFT JOIN COALESCE in all read queries.
File and Directory Naming
- File names: snake_case —
token_verifier.go,wire_gen.go,entity.go. - Package directories: lowercase, no separators — follow Go convention
(
savedrecipe/,openai/,infra/). Do not use underscores in package names. - Non-package directories (migrations, docs, scripts): snake_case is acceptable.
Naming
No abbreviated variable names. Variables must use full descriptive names.
Single- or two-letter names are only allowed when the abbreviation is the full description
(e.g., a loop index i, a matrix coordinate x).
Examples
| Avoid | Use instead |
|---|---|
err |
parseError, writeError, dbError, validationError |
ctx |
requestContext, handlerContext, queryContext |
s |
service, server |
r |
request, repository |
w |
writer, responseWriter |
h |
handler |
req |
request |
res |
response, result |
msg |
message |
cfg |
config |
db |
database |
tx |
transaction |
buf |
buffer |
tmp |
temp, or a descriptive name |
This rule applies to all languages in this repo (Go and Dart).
In Go, name variables to avoid shadowing the error built-in and the context package —
use descriptive prefixes: parseError, requestContext, etc.
Flutter Client Localisation
Rule: Every UI string in client/ must go through AppLocalizations.
Never hardcode user-visible text in Dart source files.
Current setup
flutter_localizations(sdk: flutter) +intl: ^0.20.2inclient/pubspec.yamlgenerate: trueunderflutter:inclient/pubspec.yamlclient/l10n.yaml— generator config (arb-dir, template-arb-file, output-class)- Generated class:
package:food_ai/l10n/app_localizations.dart
Supported languages
en, ru, es, de, fr, it, pt, zh, ja, ko, ar, hi
ARB files
All translation files live in client/lib/l10n/:
app_en.arb— English (template / canonical)app_ru.arb,app_es.arb,app_de.arb,app_fr.arb,app_it.arbapp_pt.arb,app_zh.arb,app_ja.arb,app_ko.arb,app_ar.arb,app_hi.arb
Usage pattern
import 'package:food_ai/l10n/app_localizations.dart';
// Inside build():
final l10n = AppLocalizations.of(context)!;
Text(l10n.someKey)
Adding new strings
- Add the key + English value to
client/lib/l10n/app_en.arb(template file). - Add the same key with the correct translation to all other 11 ARB files.
- Run
flutter gen-l10ninsideclient/to regenerateAppLocalizations. - Use
l10n.<newKey>in the widget.
For parameterised strings use the ICU placeholder syntax in ARB files:
"queuePosition": "Position {position}",
"@queuePosition": { "placeholders": { "position": { "type": "int" } } }
Then call l10n.queuePosition(n) in Dart.