Python toolkit to automate iOS/macOS localization with Xcode String Catalogs (.xcstrings)
Update translations in seconds instead of hours. Automate your Xcode String Catalog (.xcstrings) workflows with simple CSV files.
Manually updating translations across multiple languages in Xcode String Catalogs is:
- β±οΈ Time-consuming (hours per update)
- π Error-prone (copy-paste mistakes)
- π« Tedious for translators (need Xcode access)
Automate with CSV workflows:
- β‘ Update 10+ languages in 30 seconds
- β Zero copy-paste errors
- π Translators work with familiar CSV/Excel files
Automate your iOS/macOS localization workflow. Update Xcode .xcstrings files from CSV files in seconds instead of hours.
- β Automatic key mapping - Matches English strings to xcstrings keys
- β Smart quote handling - Handles Unicode smart quotes vs straight quotes
- β Special character preservation - Correctly handles %lld, %@, etc.
- β Dry run mode - Preview changes before applying
- β Batch processing - Update multiple languages at once
- β Export to CSV - Send translations to translators
- β No dependencies - Pure Python 3 (standard library only)
python3 update-translations.py -l de -c German.csvpython3 export-translations.py -l de -o German.csv./update-all-languages.sh Languages/-
Copy scripts to your project:
mkdir Scripts cd Scripts # Copy update-translations.py, export-translations.py, update-all-languages.sh chmod +x update-all-languages.sh
-
No other dependencies needed! Uses Python 3 standard library only.
Your CSV must have exactly 2 columns:
English,Translation
"Hello World","Hallo Welt"
"Welcome to %@","Willkommen bei %@"
Important:
- First row is header (will be skipped)
- Column 1: English text (must match exactly)
- Column 2: Translation
- Preserve placeholders like %@, %lld
python3 update-translations.py --language de --csv German.csvOptions:
-l, --language- Language code (de, es-419, fr-CA, etc.)-c, --csv- Path to CSV file-x, --xcstrings- Path to xcstrings file (auto-detected by default)-d, --dry-run- Preview without applying-v, --verbose- Show detailed progress
python3 export-translations.py --language de --output German.csvOptions:
-l, --language- Language code-o, --output- Output CSV path-k, --include-keys- Include key column (useful for reference)
Edit update-all-languages.sh to add your language mappings:
get_lang_code() {
case "$1" in
"German.csv") echo "de" ;;
"Spanish.csv") echo "es-419" ;;
"French.csv") echo "fr-CA" ;;
# Add your languages here
*) echo "" ;;
esac
}Then run:
./update-all-languages.sh path/to/csvs/| Language | Code | Language | Code |
|---|---|---|---|
| German | de |
Spanish (Latin America) | es-419 |
| French (Canada) | fr-CA |
Portuguese (Brazil) | pt-BR |
| Chinese (Simplified) | zh-Hans |
Chinese (Traditional) | zh-Hant |
| Japanese | ja |
Korean | ko |
| Italian | it |
Dutch | nl |
| Russian | ru |
Thai | th |
| Vietnamese | vi |
Indonesian | id |
| Filipino | fil |
# 1. Export current translations for translator
python3 export-translations.py -l de -o German-for-review.csv
# 2. Send to translator, receive German-updated.csv
# 3. Preview changes
python3 update-translations.py -l de -c German-updated.csv --dry-run
# 4. Apply updates
python3 update-translations.py -l de -c German-updated.csv
# 5. Verify and commit
git diff path/to/Localizable.xcstrings
git add path/to/Localizable.xcstrings
git commit -m "Update German translations"# Export all languages
for lang in de es-419 fr-CA ja; do
python3 export-translations.py -l $lang -o "${lang}.csv"
done
# After receiving updates, batch import
./update-all-languages.sh .The scripts provide color-coded feedback:
- Green β - Already matching (no change needed)
- Yellow β» - Will be updated
- Blue + - New translation being added
- Red β - English text not found in xcstrings
The English text in your CSV doesn't match the xcstrings file.
Solution: Export fresh translations and update from there:
python3 export-translations.py -l de -o German-fresh.csvSolution: Specify the path explicitly:
python3 update-translations.py -l de -c German.csv -x path/to/Localizable.xcstringsYour xcstrings has Unicode smart quotes (') but CSV has straight quotes ('). This is handled automatically with fuzzy matching.
- Python 3.6 or later
- Xcode String Catalog (.xcstrings) format
- No external dependencies
- Handles 50+ strings in < 1 second
- Scales to hundreds of strings
- Batch updates 10+ languages in seconds
| Task | Manual | Automated |
|---|---|---|
| Single language update | 30 min | 10 sec |
| 10+ languages | 4+ hours | 30 sec |
| Export for translator | Manual | 5 sec |
MIT License - Feel free to use in your projects!
Found a bug or have a feature request? Please open an issue!
- Always dry-run first - Use
--dry-runto preview - Keep CSV files versioned - Track translation history
- Test in simulator - Verify translations in UI
- Use include-keys for context - Export with
-kflag for translator reference
Built to simplify iOS/macOS localization workflows. Works with Xcode 15+ String Catalogs.
Star this repo if it helps your workflow! π
Xcode localization, iOS internationalization, macOS i18n, String Catalog automation, xcstrings tool, translation workflow, localization automation, Swift localization, CSV translation import, Xcode 15 String Catalogs, iOS l10n, macOS localization tool