Batch update ARB translation files across all languages when new translation keys are added to English and Chinese files; use when adding new i18n strings to the Flutter app.
This skill helps batch update all language ARB (Application Resource Bundle) files when new translation entries are added to the base languages (English and Chinese). It automates the process of translating and distributing new entries across 60+ language files.
ALWAYS add new translation entries at the very end of each ARB file, just before the closing }.
intl_en.arb and intl_zh.arb) AND automated additions via the update scriptExample:
{
"existingKey1": "...",
"@existingKey1": {},
"existingKey2": "...",
"@existingKey2": {},
// Add new entries HERE ↓
"newKey": "...",
"@newKey": {}
}
ALL ARB files (including non-English languages) must have metadata descriptions written in English.
"@perfectDatabaseChallengeHint": {"description": "Hint to enable perfect database for greater challenge", ...}"@perfectDatabaseChallengeHint": {"description": "启用完美数据库以获得更大挑战的提示", ...} (in intl_zh.arb)This applies to:
description field in @key metadataintl_en.arb, intl_zh.arb, intl_ja.arb, etc.Rationale: Flutter's ARB format specification requires metadata to be in English for tooling compatibility and consistency across all locales.
Before adding new translations, ALWAYS check if the key already exists in the ARB files.
Check before adding:
# Check if key exists in a specific file
grep -c "keyName" intl_en.arb
# Check all files
for file in intl_*.arb; do
count=$(grep -c "keyName" "$file")
echo "$file: $count occurrences"
done
Decision matrix:
If duplicates exist:
Prevention:
ALL ARB files MUST use 4-space indentation, NOT 2-space or tabs.
Indentation levels:
Example with correct 4-space indentation:
{
"myKey": "My value",
"@myKey": {
"description": "My description",
"placeholders": {
"param": {
"description": "Parameter description",
"type": "String"
}
}
}
}
❌ WRONG (2-space indentation):
{
"myKey": "My value",
"@myKey": {
"description": "My description",
"placeholders": {
"param": {
"description": "Parameter description",
"type": "String"
}
}
}
}
Important:
new-items.txt, use 4-space indentationupdate_arb_files.sh script will copy indentation exactly as written1. Use git to identify new entries in intl_en.arb (and intl_zh.arb if available)
2. Generate translations for all 59 other languages
3. Create new-items.txt with all translations
4. Run update_arb_files.sh to apply changes
5. Validate JSON format of updated files
Use git to see what was recently added (most reliable method):
cd src/ui/flutter_app/lib/l10n
# Check recent changes to English ARB file
git log -p --follow -1 intl_en.arb
# Or see diff from last commit
git diff HEAD~1 intl_en.arb
# See what was added (lines starting with +)
git diff HEAD~1 intl_en.arb | grep "^+"
# Check if Chinese file also has new entries
git diff HEAD~1 intl_zh.arb
# If no recent changes in git, check uncommitted changes
git diff intl_en.arb
git diff intl_zh.arb
Extract the new keys:
@)"key": "value" and "@key": {}{} - NO description field in any language file (including English and Chinese)Priority:
intl_en.arb and intl_zh.arb have new entries → use both as translation referenceintl_en.arb has new entries → translate from English onlyCheck if the new keys exist in other language files:
# Check if a specific key exists in all files
grep -l "newKeyName" intl_*.arb
# Count how many files already have the key
grep -l "newKeyName" intl_*.arb | wc -l
# Find which files are missing the key
for file in intl_*.arb; do
if ! grep -q "newKeyName" "$file"; then
echo "Missing in: $file"
fi
done
Create translations for all required languages. Each ARB file needs:
Supported Languages (59+ total excluding en and zh):
The update_arb_files.sh script reads from new-items.txt with this format:
// intl_<locale>.arb
"keyName": "Translated text",
"@keyName": {},
"keyNameDetail": "Detailed translated text",
"@keyNameDetail": {}
// intl_<another_locale>.arb
"keyName": "其他语言的翻译",
"@keyName": {},
...
Format Rules:
// intl_<locale>.arb (indicates which file to update)@key metadata must be empty objects {} - NEVER include description or any other fieldsExample new-items.txt:
// intl_ja.arb
"stopPlacing": "配置を停止",
"@stopPlacing": {},
"stopPlacing_Detail": "ボード上に空きスペースが2つだけ残ったときに配置フェーズが終了します。",
"@stopPlacing_Detail": {}
// intl_fr.arb
"stopPlacing": "Arrêter le placement",
"@stopPlacing": {},
"stopPlacing_Detail": "La phase de placement se termine lorsque le plateau n'a plus que 2 espaces vides.",
"@stopPlacing_Detail": {}
// intl_de.arb
"stopPlacing": "Setzen beenden",
"@stopPlacing": {},
"stopPlacing_Detail": "Die Setzphase endet, wenn das Brett nur noch 2 freie Felder hat.",
"@stopPlacing_Detail": {}
Execute the update script to apply all translations:
cd src/ui/flutter_app/lib/l10n
# Run the update script
./update_arb_files.sh
# The script will:
# - Read new-items.txt
# - Parse each locale section
# - Append entries to corresponding .arb files
# - Maintain proper JSON formatting
Verify that all files were updated correctly:
# Check how many files contain the new key
grep -l "stopPlacing" intl_*.arb | wc -l
# Should return 63 (all language files including en and zh)
# Count total arb files
ls -1 intl_*.arb | wc -l
# Should return 63
# Validate JSON format of all files
for file in intl_*.arb; do
if ! python3 -m json.tool "$file" > /dev/null 2>&1; then
echo "❌ JSON Error in $file"
fi
done
echo "✅ JSON validation complete"
# Spot check a few languages
tail -6 intl_ja.arb # Japanese
tail -6 intl_fr.arb # French
tail -6 intl_ru.arb # Russian
tail -6 intl_ar.arb # Arabic
Location: src/ui/flutter_app/lib/l10n/update_arb_files.sh
What it does:
new-items.txt from the same directory// intl_<locale>.arb)How it works:
} from target file} back# append.sh - Appends content from append.txt to specified ARB file
./append.sh <arb_file>
# append-items.sh - Calls append.sh for all ARB files
./append-items.sh
# replace-locale.sh - Replace locale identifiers
./replace-locale.sh
When translating Mill game terms, consider:
intl_en.arb)intl_zh.arb) - if available and recently updatedRight-to-Left Languages (ar, he, fa, ur):
Asian Languages (zh, ja, ko, th, vi):
European Languages:
Solution:
# Use git to see the actual changes
git log -p --since="1 week ago" -- intl_en.arb
# Compare with current HEAD
git diff HEAD intl_en.arb
# See only added lines
git diff HEAD intl_en.arb | grep "^+[^+]"
Solution:
Solution:
new-items.txt exists in l10n directory//)Cause: Trailing comma or malformed JSON
Solution:
# Find the problematic file
for file in intl_*.arb; do
python3 -m json.tool "$file" > /dev/null 2>&1 || echo "Error: $file"
done
# Manually fix JSON or re-run script
Check:
# Verify all locales are in new-items.txt
grep "^//" new-items.txt | wc -l
# Should be around 59-61 (excluding en and zh base files)
# List which files are included
grep "^//" new-items.txt
Problem: Not properly translated, just English copied
Solution: Regenerate translations ensuring each language gets proper localization
Problem: ARB files have "@key": {"description": "..."} instead of "@key": {}
Solution:
# Fix all ARB files to have empty metadata objects
import json
for locale in ['en', 'zh', 'ja', 'fr', ...]: # all locales
file_path = f'intl_{locale}.arb'
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# Remove description from all @ keys
for key in list(data.keys()):
if key.startswith('@'):
data[key] = {}
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
f.write('\n')
Important:
intl_en.arb and intl_zh.arb) must have empty metadata objects {}description or any other fields to metadataUse git to identify changes
git diff is more reliable than tailEnglish is the primary source
intl_en.arb for new entriesintl_zh.arb) is optional referenceUse consistent terminology
Test after updating
Version control
i18n: Add translations for [feature]Quality over speed
src/ui/flutter_app/lib/l10n/
├── intl_en.arb # English (primary base)
├── intl_zh.arb # Chinese Simplified (optional reference)
├── intl_zh_Hant.arb # Chinese Traditional
├── intl_*.arb # 60 other language files
├── new-items.txt # Temporary: new translations to add
├── update_arb_files.sh # Main update script
├── append.sh # Helper script
├── append-items.sh # Helper script
└── replace-locale.sh # Helper script
After running the update process:
# 1. Navigate to l10n directory
cd src/ui/flutter_app/lib/l10n
# 2. Use git to identify what's new
git diff HEAD~1 intl_en.arb
# OR if uncommitted:
git diff intl_en.arb
# Output shows:
# +"newFeature": "Stop placing when empty",
# +"@newFeature": {},
# +"newFeature_Detail": "Detailed explanation...",
# +"@newFeature_Detail": {}
# 3. Check if Chinese also has these (optional)
git diff HEAD~1 intl_zh.arb
# If not found, proceed with English only
# 4. Extract the new keys
# newFeature
# newFeature_Detail
# 5. Generate translations for all languages
# (Use AI or translation service to create new-items.txt)
# Remember: do NOT include intl_en.arb or intl_zh.arb
# 6. Verify new-items.txt format
head -30 new-items.txt
# Should start with: // intl_af.arb or similar (NOT intl_en.arb)
# 7. Run update script
./update_arb_files.sh
# 8. Validate results
grep -l "newFeature" intl_*.arb | wc -l
# Output: 63 ✓ (all files including en and zh)
# 9. Validate JSON
for file in intl_*.arb; do
python3 -m json.tool "$file" > /dev/null 2>&1 || echo "Error: $file"
done
echo "✅ All files valid"
# 10. Spot check translations
tail -8 intl_ja.arb
tail -8 intl_de.arb
tail -8 intl_ar.arb
# 11. Verify with git
git diff intl_ja.arb
git diff intl_de.arb
# 12. Clean up
rm new-items.txt # Optional: keep for reference
# 13. Commit changes
# Navigate to project root directory
git add src/ui/flutter_app/lib/l10n/intl_*.arb
git commit -m "i18n: Add translations for new feature across all languages"
When using AI to generate all translations:
Important: Translate from English, optionally reference Chinese
# Prompt template for AI translation:
Translate the following Mill game UI strings from English to all these languages:
[List of target languages]
English source:
"newFeature": "Stop placing when only two empty squares remain"
"newFeature_Detail": "When enabled, the placing phase ends and moving phase begins when the board has only 2 empty spaces left, regardless of pieces in hand. This rule only applies to 12-piece games."
Optional Chinese reference (if available):
"newFeature": "棋盘只剩两个空位时停止放子"
"newFeature_Detail": "启用后,当棋盘只剩2个空位时,无论手中是否还有棋子,放子阶段都会结束并进入走子阶段。此规则仅适用于12子棋。"
Context:
- This is for a Mill board game app (Nine Men's Morris)
- "newFeature" is a short settings label
- "newFeature_Detail" is a detailed description shown in settings
Please provide natural, fluent translations for each language.
Format as new-items.txt (do NOT include English or Chinese).
Then format the response into new-items.txt format.
# See what was added to English ARB
git diff HEAD~1 intl_en.arb | grep "^+"
# Check if all files have a key
grep -l "keyName" intl_*.arb | wc -l
# Validate all JSON files
for f in intl_*.arb; do python3 -m json.tool "$f" >/dev/null 2>&1 || echo "Bad: $f"; done
# Count languages in new-items.txt
grep "^//" new-items.txt | wc -l
# Update all ARB files
./update_arb_files.sh
# View recent ARB commits
git log --oneline --follow -10 intl_en.arb
src/ui/flutter_app/lib/l10n/update_arb_files.shgit diff to identify new entries reliably