| name | joycai-l10n |
| description | Guides the complete localization (l10n) workflow for the Joycai Image AI Toolkits Flutter project. Use proactively whenever adding, editing, or removing any user-visible string in the app — including new UI text in widgets, screen labels, button labels, dialog messages, or error strings. Trigger on: "add a localization key", "translate", "update l10n", "add l10n string", "add UI text", "new string key", "internationalize". Also trigger automatically when you notice new hard-coded string literals appearing in Dart files that should be localized. This skill enforces the 4-language requirement (en, zh, zh_Hant, ja) and the mandatory merge step that is easy to forget.
|
Joycai L10n Workflow
This project uses a modular ARB source system. Strings are maintained in per-module
files under lib/l10n/src/<lang>/, merged into top-level app_*.arb files, then
compiled by Flutter's codegen into AppLocalizations. Skipping any step produces
silent failures or broken builds.
Golden Rule
Never edit lib/l10n/app_*.arb directly. These files are auto-generated by
dart tool/merge_l10n.dart and will be overwritten on the next run.
Module Map
Match the string to the right category file. When in doubt, use common.arb.
| Module | Screen / Purpose |
|---|
browser.arb | File Browser screen |
common.arb | Shared labels — buttons, status words, generic messages |
downloader.arb | Image Downloader screen |
metrics.arb | Token Usage / cost metrics screen |
models.arb | Models & Channels management screen |
prompts.arb | Prompt Library screen |
settings.arb | Settings screen |
tasks.arb | Task Queue screen |
wizard.arb | Setup Wizard |
workbench.arb | Workbench / gallery screen |
Each module exists for all 4 languages:
lib/l10n/src/
en/<module>.arb
zh/<module>.arb
zh_Hant/<module>.arb
ja/<module>.arb
Checklist
Work through these in order — every step is required:
ARB Format
Simple key — no metadata needed:
{
"cancelTask": "Cancel Task"
}
Parameterized key — the @keyName metadata block is mandatory whenever a {placeholder} appears in the string. Without it, flutter gen-l10n will fail or produce incorrect code:
{
"taskId": "Task ID: {id}",
"@taskId": {
"placeholders": {
"id": {
"type": "String"
}
}
},
"filesCount": "{count} files",
"@filesCount": {
"placeholders": {
"count": {
"type": "int"
}
}
}
}
Common placeholder types: String, int, double, DateTime.
Using Keys in Dart
// Inside a build() method with an AppLocalizations variable:
final l10n = AppLocalizations.of(context)!;
Text(l10n.cancelTask)
Text(l10n.filesCount(42)) // parameterized
// Or inline:
Text(AppLocalizations.of(context)!.cancelTask)
Common Pitfalls
Missing a language — All 4 languages must have identical key sets. A missing key
causes merge_l10n.dart to fail silently or leaves untranslated strings at runtime.
After editing, always verify all 4 files have the new key before running the merge.
Skipping the merge — New keys added to src/ are invisible to Flutter until
dart tool/merge_l10n.dart runs. flutter gen-l10n alone is not enough.
Missing @keyName metadata — If a string contains {placeholder} syntax but
lacks the corresponding @keyName block, Flutter codegen will either fail or generate
a method with the wrong signature.
Wrong module — Keys placed in the wrong category file are hard to discover later.
Check the Module Map when uncertain; common.arb is the safe fallback.
Editing generated files — Any change to lib/l10n/app_*.arb is lost on the next
dart tool/merge_l10n.dart run. Always edit the source files in lib/l10n/src/.