feat(i18n): add translations for zh-Hans, de, fr, es, ja, pt-BR

Ships first-pass AI translations for six locales on top of the existing
English base, plus a simple JSON-per-locale contributor workflow so new
languages can land as a single PR.

- 518 keys translated per locale (proper nouns / brand names / format-
  only strings left to fall back to English by design — see the
  "Non-blocking (intentional verbatim)" section of scarf/docs/I18N.md).
- Per-locale source-of-truth lives in tools/translations/<locale>.json;
  tools/merge-translations.py writes them into Localizable.xcstrings
  and is idempotent (re-runnable as translators iterate).
- InfoPlist.xcstrings (macOS microphone permission prompt) translated
  for all six locales.
- knownRegions expanded: zh-Hans, de, fr now join by es, ja, pt-BR.
- CONTRIBUTING.md gains an "Adding a Language" section documenting the
  fork → JSON → merge → PR flow. Native-speaker reviews welcome.

Closes #13 (the original ask: Simplified Chinese support).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-04-20 18:16:41 -07:00
parent de34a80807
commit 1726a613a5
12 changed files with 24008 additions and 1677 deletions
+18 -3
View File
@@ -7,12 +7,27 @@ Scarf uses Apple's modern **String Catalog** workflow. Source strings are auto-e
| Locale | Status |
|---|---|
| `en` (English) | Base / source |
| `zh-Hans` (Simplified Chinese) | Region enabled, translations pending |
| `de` (German) | Region enabled, translations pending |
| `fr` (French) | Region enabled, translations pending |
| `zh-Hans` (Simplified Chinese) | AI-translated, native-speaker review welcome |
| `de` (German) | AI-translated, native-speaker review welcome |
| `fr` (French) | AI-translated, native-speaker review welcome |
| `es` (Spanish) | AI-translated, native-speaker review welcome |
| `ja` (Japanese) | AI-translated, native-speaker review welcome |
| `pt-BR` (Portuguese, Brazil) | AI-translated, native-speaker review welcome |
Canadian French users are served by base `fr`. `fr-CA` will be added only if a concrete Québec-specific bug is reported.
### Translation workflow
Source-of-truth per locale lives in `tools/translations/<locale>.json` — a flat `{ "English": "Translation" }` map. The merge step writes those into `scarf/scarf/Localizable.xcstrings` via:
```bash
python3 tools/merge-translations.py
```
Keys absent from a locale file fall back to English at runtime — this is deliberate for proper nouns (Scarf, Hermes, Anthropic, OAuth, SSH…) and format-only strings (`%lld`, `%@ → %@`, `•`). Re-running the merge is idempotent; iterate on a JSON and re-merge.
Contributor path for new languages is documented in the repo root [CONTRIBUTING.md](../../CONTRIBUTING.md#adding-a-language).
## Adding a new language
1. Xcode → Project → Info → Localizations → `+` (add locale).
+3
View File
@@ -217,6 +217,9 @@
"zh-Hans",
de,
fr,
es,
ja,
"pt-BR",
);
mainGroup = 534959372F7B83B600BD31AD;
minimizedProjectReferenceProxies = 1;
+36
View File
@@ -5,11 +5,47 @@
"comment" : "Shown by macOS when Scarf first requests microphone access for Hermes voice chat.",
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf verwendet das Mikrofon für den Hermes-Sprach-Chat."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf uses the microphone for Hermes voice chat."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf usa el micrófono para el chat de voz de Hermes."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf utilise le microphone pour le chat vocal de Hermes."
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf は Hermes の音声チャットのためにマイクを使用します。"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "O Scarf usa o microfone para o chat de voz do Hermes."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Scarf 使用麦克风进行 Hermes 语音聊天。"
}
}
}
}
File diff suppressed because it is too large Load Diff