feat(desktop): add German (de) locale - #51762
oliverhees wants to merge 7 commits into
Conversation
9fd78df to
aaa014b
Compare
|
Re: the Demand signal: The originating issue (#51217) cites ~80M+ German speakers across Germany/Austria/Switzerland, with zero existing German locale option today. For a desktop product aiming at broader reach, "the UI doesn't render in my language" is often the actual adoption blocker for non-English-first users — not cosmetic polish, but the reason someone quietly bounces off an install. Re: #38846 — I see that PR also proposes German (among 15 locales) via a JSON + sync-script architecture, still open/unmerged since June. This PR is intentionally narrower: one locale, using the existing per-file |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused use of the existing defineLocale() path. German is still absent from current main (apps/desktop/src/i18n/types.ts:8, catalog.ts:7-12), so this remains a useful, narrow contribution.
Problems
apps/desktop/src/i18n/de.ts:84suppliesremoteSignInHintas a string. Current main requires(signInLabel: string) => string(apps/desktop/src/i18n/types.ts:140) and calls it atapps/desktop/src/components/boot-failure-overlay.tsx:248; the salvaged German locale would fail on remote reauthentication.
Suggested changes
- Preserve the current contract when resolving the conflict: make the German hint a callback, and add
signOutAndSignIn,gatewaySettings,back, andremoteFailureHintcopy alongside it. - Add a regression assertion for the German remote-reauth path.
Automated hermes-sweeper review.
| openLogs: 'Logs öffnen', | ||
| repairHint: | ||
| 'Die Reparatur führt den Installer erneut aus und kann auf einem frischen Rechner einige Minuten dauern.', | ||
| remoteSignInHint: |
There was a problem hiding this comment.
Current main changed this contract to (signInLabel: string) => string (types.ts:140) and calls it at boot-failure-overlay.tsx:248. Please preserve that callback shape when this locale is salvaged; a string here would fail during remote reauthentication.
aaa014b to
ce55225
Compare
|
@teknium1 Good catch, thanks — you were right, I was checking against a stale local checkout. Rebased onto current main (was 625 commits behind) and fixed:
Re-verified: |
|
Just want to add a voice of support for this PR — I went looking for a German locale in Hermes Desktop today and was surprised to find it missing, given that the CLI/backend layer ( I tested this PR branch locally on Debian and it works flawlessly. The translation reads naturally, uses the informal "du" consistently, and the The number of duplicate PRs this has spawned (#62592, #67077, #71161, #81775, #82411 and counting) is a pretty clear demand signal — ~80M+ German speakers and zero UI locale. Every new duplicate wastes contributor time that could go into other features. @teknium1's review feedback on the Thanks @oliverhees for the thorough implementation! |
|
Quick heads-up: this branch now has merge conflicts with main. I pulled both and checked — the conflicts are all trivial, same root cause: The i18n conflicts (4 files):
The 4 non-i18n conflicts ( Happy to help with a PR to your branch if you'd prefer, but it's a straightforward fix. The translations themselves are solid. |
|
@oliverhees I took the liberty of rebasing your branch onto current main and filling in all the missing translations that landed in en.ts since June. Opened as a PR to your branch: oliverhees#1 If you merge that, your #51762 will be current and merge-ready. |
fe9073c to
ee336fd
Compare
|
Rebased onto current What changed since the last push
Two small fixes that aren't strictly the feature
Verification against current On the duplicates There are several other open German locale PRs (#82411, #81775, #79085, #71161, #67077, #62592). Happy to defer if any of them is preferred — I care more about German shipping than about whose branch it lands from. If this one is the canonical path per the earlier triage, it's ready now. Thanks @Luna161 for flagging the missing keys and the |
|
@teknium1 — this one is ready whenever someone has a slot for it. Current state:
It stays deliberately narrow: no new build tooling, no sync step, no renderer changes — just Why I keep pushing on this one: we're building Hermes plugins for the German-speaking community and the desktop UI locale is the piece they sit on top of. Right now that's the blocker for shipping them. Beyond this PR, we'd like to support Hermes properly in the DACH region — translation upkeep as Also happy to take on more of the load here if it helps: reviewing the other open German locale PRs (#85236, #82411, #81775, #79085, #71161, #67077, #62592) and consolidating them into whichever branch you consider canonical, or acting as a reviewer for If a different branch is preferred over this one, that's fine too — I care more about German shipping than about whose PR it lands from. |
babd989 to
68bfe6b
Compare
|
Rebased onto What changed
Coverage against
Verified against that base: prettier clean · One ask, and it isn't a review slot. No CI job has ever run on this branch. Every workflow run it has ever Nine runs, nine times I can't see your Actions settings, so I won't guess at the exact policy. From Separately, an offer: there are eight open German locale PRs. This is the |
68bfe6b to
c470f9e
Compare
One-shot current-main workflow that applies the exact two-key locale contract migration to the NousResearch#51762 materializer and removes itself.
c470f9e to
fcc3631
Compare
|
Hi! Flagging that there's now a parallel PR adding the same German desktop locale: #81775. Quick comparison (both add
Both were verified with strict
so neither contributor's work is lost. Happy to rebase/extract whatever helps maintainers decide. (Also noting #81775 currently carries a |
|
Thanks for flagging it, and for doing the comparison properly instead of just asserting overlap. I checked your numbers rather than taking them on trust. Something you'll want to know, because it isn't visible from this thread: review has moved to #92909. This PR has sat behind the fork workflow-approval gate since June, which is why it reads as dormant. @andrexibiza rebased the same implementation onto current main so CI could actually run. I verified the On the line delta, I'd rather not let it stand as a quality claim. #81775 branches off Aug 8 and this one off Aug 23, and Your proposal is the right shape and I'll go one step further than splitting it down the middle. The Kanban bundle is yours. It's the one piece that neither this PR nor #92909 covers, and it should land under your name. I'm not going to reimplement it just to close a gap you already filled. |
|
Independent verification, from someone who built a German locale separately before finding this PR. I had translated The On Numbers from my parallel implementation, verified on a clean clone of
Two things I hit that are worth knowing for whoever reviews:
I have opened two PRs that deliberately do not overlap with this one, covering surfaces none of the five German PRs touch:
Happy to help however is useful — rebasing, filling in keys that landed since, or reviewing. The thing that would help German-speaking users most is one of these five landing, not a sixth. |
Adds German as a desktop UI locale using the existing per-file defineLocale() pattern already shipped for ja/zh/zh-hant/ar. No new build tooling, no sync step. - New apps/desktop/src/i18n/de.ts covering every Translations section, including the surfaces that landed since June (starmap, webhooks, zones) and the settings field labels. - Register `de` in the Locale union (types.ts), the picker and alias table (languages.ts: de, de-DE, de-AT, de-CH, de-LI, de-LU, german, deutsch), and the catalog (catalog.ts). - languages.test.ts extends the existing `ar` assertions rather than replacing them; both locales are covered side by side. - context.test.tsx used 'de' as its example of an *unsupported* language, which this change would silently invert. Switched to 'xx' so the assertion stays meaningful as more locales land. - DESIGN.md's i18n contract now lists all six locales (it still said four after `ar` shipped). UI chrome is translated; established product/tech terms stay English (Gateway, Skill, Toolset, Agent, Cron, Token, MCP, Provider, Worktree). Informal "du" throughout. Callback-valued strings keep their signatures so remote-reauth, webhook toggles and the sidebar toggle format correctly. Verified against current main: tsc -p . --noEmit clean for this locale, eslint src/i18n reports no errors (one fewer warning than baseline), vitest run src/i18n 28/28 pass. Co-authored-by: Luna <luna161@users.noreply.github.com>
The Contributor Attribution Check fails on any commit whose author email is neither a GitHub id+login noreply address nor mapped under contributors/emails/. This branch's commit is authored from oliverhees@gmail.com, which is neither, so the job would exit 1. Adds the mapping file per contributors/README.md: one file per email, no AUTHOR_MAP edit.
Rebased onto current main and filled in every string that landed in
`en.ts` since the branch was last refreshed on 2026-08-10.
- 1080 missing entries translated (902 plain strings, 178 callback-valued),
covering the surfaces that shipped since: Hermes Cloud sign-in and agent
discovery (`settings.gateway.cloud*`), registered gateways
(`settings.connections.*`), desktop and agent plugins
(`settings.plugins.*`), the SSH connection mode, cron blueprints, the
skill hub, projects and worktrees in the sidebar, the working-tree
status stack, quick entry, and the per-tool assistant labels.
- 6 stale keys dropped. `settings.gateway.{appliesTo,allProfiles,
defaultConnection,profileConnection}` moved to `settings.profileScope`
upstream, `onboarding.flowSubtitles.loopback` and
`keybinds.actions.'view.closePreviewTab'` were removed.
- `titlebar.layoutEditorTitle` became `(modifier: string) => string`
upstream; the German entry is now a callback and interpolates the
modifier instead of hardcoding ⌘.
- Fixed two pre-existing defects this pass surfaced: `skills.toggleToolset`
dropped its `enabled` argument, so the accessibility label said
"umschalten" without naming the target state (every other locale
interpolates it); `rightSidebar.folderTip` appended an invented
"click to change folder" hint, while `en`, `ja`, `zh`, `zh-hant`, and
`ar` all return the bare path.
`de.ts` now covers 2920 of 2920 leaf keys: no missing entries, and no keys
that no longer exist in `en.ts`.
Verified against current main: prettier clean, `tsc -p . --noEmit` reports
0 errors, `eslint src/i18n` reports 0 errors (4 pre-existing warnings in
context.test.tsx, unchanged from baseline), `vitest run src/i18n` 28/28
pass. Every callback entry was checked against its English counterpart for
matching arity and interpolation variables.
Co-authored-by: Luna <luna161@users.noreply.github.com>
…int/fade, intro splash, voice controls, update dialog)
upstream renamed zones.showHeader/hideHeader to showTabStrip/hideTabStrip when tab-strip hiding got its own command. de.ts still carried the old names, which fails the desktop typecheck (TS2353) on current main. Verified locally against upstream/main bdf1047: tsc -p . --noEmit clean tsc -p tsconfig.electron.json clean tsc -p tsconfig.e2e.json clean npm run lint 0 errors vitest src/i18n/ 4 files, 28 tests, all pass
defineLocale() merges every locale onto the English base, so a key that was
never translated silently renders in English and nothing reports it. A value
comparison against en.ts found 230 German leaves still holding the English
string, including the whole sendDiagnostics block, the cloud-down boot
failure copy, and a long tail of settings labels.
This translates every one of them that has a German form. What remains
identical to English is only words that are identical in German (Repository,
System, Auto, Updates, Navigation), proper nouns (GitHub Issues, Hermes
Desktop) and format-only helpers (`Version ${value}`).
Additions only, no existing translation touched: 102 insertions, 0 deletions.
Verified locally against upstream/main bdf1047:
tsc -p . --noEmit clean
tsc -p tsconfig.electron.json clean
tsc -p tsconfig.e2e.json clean
npm run lint 0 errors
vitest src/i18n/ 4 files, 28 tests pass
value-comparison coverage 92.7% -> 95.3%
Carry forward the later German locale refresh from NousResearch#106287 while retaining NousResearch#51762 as the canonical PR line. Remove only keys no longer present in the current locale contract. Co-authored-by: gustl-clawbot <gustl-clawbot@gmx.at>
39b2683 to
9644e4a
Compare
Rebased onto current
|
|
Superseded by #120829, now merged. French, German and Spanish now ship as full Desktop catalogs and appear in Settings → Appearance → Language. The strings that still matched current keys were reused from the contributor PRs, and their authors are credited with |
What does this PR do?
Adds a complete German (
de) locale for the Hermes Desktop UI, taking the desktop app from four to five shipped languages.The translation reaches full parity with the existing
ja/zh/zh-hantlocales — every section ofen.tsis covered, including the settingsfieldLabels/fieldDescriptions(viadefineFieldCopy). It uses the existingdefineLocale()merge helper, so any future English-only string still falls back cleanly to English.Translation approach: UI chrome is in German; established product/tech terms stay English where that reads natural to German-speaking developers (Gateway, Skill, Toolset, Agent, Cron, Token, MCP, Provider, YOLO, Pet).
Related Issue
N/A — new locale contribution. Happy to open a tracking issue if preferred.
Type of Change
Changes Made
apps/desktop/src/i18n/de.ts— new: full German translation viadefineLocale()(incl.settings.fieldLabels/fieldDescriptionsviadefineFieldCopy)apps/desktop/src/i18n/types.ts— add'de'to theLocaleunionapps/desktop/src/i18n/languages.ts— add the Deutsch picker option + aliases (de,de-de,de-at,de-ch,de-li,de-lu)apps/desktop/src/i18n/catalog.ts— registerdeinTRANSLATIONSapps/desktop/src/i18n/languages.test.ts— coverdenormalization / support / config valueapps/desktop/DESIGN.md— update the i18n contract + checklist to five localesHow to Test
npm run devinapps/desktopde*locale)Checklist
Code
pytest tests/ -q— N/A (desktop / TypeScript-only change). Verified instead withtsc -p . --noEmit(0 errors),eslint src/ electron/(clean),prettier --check(clean) andvitest run src/i18n(i18n unit tests pass).languages.test.tscovers the new locale)Documentation & Housekeeping
apps/desktop/DESIGN.mdi18n section)cli-config.yaml.example— N/A (no config keys changed)Screenshots / Logs
Verified locally on Pop!_OS 24.04 — the full UI renders in German. Happy to add in-app screenshots if useful.