Skip to content

feat(bots): add German (de) bundle for the Bot Mode plugin catalog - #101305

Open
Euterer wants to merge 1 commit into
NousResearch:mainfrom
Euterer:bots-de-locale
Open

Euterer wants to merge 1 commit into
NousResearch:mainfrom
Euterer:bots-de-locale

Conversation

@Euterer

@Euterer Euterer commented Sep 2, 2026

Copy link
Copy Markdown

The hermes-bots plugin ships its own message catalog (BOTS_LOCALES) with en, ja, zh and zh-hant. Unlike the main desktop catalog, plugin catalogs have no per-key fallback — a bundle is either complete or absent. So even with a German UI locale selected, the entire Bot Mode surface stays English: the roster, group chats, routines, cron jobs, delete dialogs, all of it.

This adds the de bundle (182 keys, mirroring en exactly) and registers it in BOTS_LOCALES.

Dependency — please read before reviewing

This does not compile on main as it stands, and that is expected. 'de' is not part of the Locale union yet:

src/plugins/hermes-bots/i18n.ts(1223,83): error TS2353:
  Object literal may only specify known properties,
  and 'de' does not exist in type 'Partial<Record<Locale, PluginMessages>>'.

That registration is exactly what the open desktop-locale work provides (#51762, and #92909 materializing it). I deliberately did not bundle the Locale/catalog.ts/languages.ts changes here — that would make this a sixth competing German-locale PR, and there are already five open. This PR is strictly the plugin surface none of them cover.

Merge order: land any of the desktop-locale PRs first, then this one applies cleanly.

Verification

Since the branch cannot be green standalone, I verified it against a locally registered de (Locale union + catalog.ts entry — the same two lines the desktop PR adds, reverted afterwards, not part of this diff):

  • tsc --noEmit -p tsconfig.json: 0 errors in hermes-bots/i18n.ts
  • vitest run src/plugins/hermes-bots: 59 files, 564 tests passed

Without that registration, the single TS2353 above is the only error — nothing else in this file is at issue.

Notes on the translation

  • Informal du, consistent with locales/de.yaml.
  • Product and platform terms stay English: Bot, Gruppenchat is translated but Bot, Skills, Cron, Routine, Gateway, Session, Profile, Workspace are not — they are the terms German-speaking users of this product actually use.
  • Placeholders and function signatures are character-identical to en; every interpolating value was checked to return the same shape.
  • The existing en/ja/zh/zh-hant bundles are untouched.

If the maintainers would rather fold this into whichever desktop-locale PR lands, I'm happy to close this and hand the bundle over instead — it applies as a single file.

@Euterer Euterer mentioned this pull request Sep 2, 2026
13 tasks
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) area/i18n Localization, locales, translations labels Sep 2, 2026
@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference; please use your judgment.

PR 101305 — feat(bots): add German (de) bundle for the Bot Mode plugin. Adds a full de locale object (apps/desktop/src/plugins/hermes-bots/i18n.ts:1023) mirroring the en shape, registered in BOTS_LOCALES. Data-only change; the comment correctly notes catalogs have no per-key fallback so completeness matters.

Non-blocking observations:

  • Completeness against en is asserted by convention, not by test — a type-level check (BotsMessages satisfies, which the annotation provides) catches missing keys at compile time as long as BotsMessages requires every leaf. If the type has optionals, a future en addition could silently leave de behind; a unit test asserting key-parity between en and de would lock it.
  • A couple of strings mix English fragments ("Cron", "Bot antwortet", "Thread") — normal for German UI copy, no action.

The hermes-bots plugin ships its own message catalog with no per-key
fallback, so a German desktop user sees the entire Bot Mode surface in
English even once a `de` UI locale is selected.

Adds the full `de` bundle (183 keys, mirroring `en`) and registers it in
BOTS_LOCALES. The en/ja/zh/zh-hant bundles are untouched.

Two test changes, both prompted by review on the first revision:

i18n.test.ts named its locales one by one, so a new bundle was covered by
nothing until someone remembered to edit the test -- which is why `ru` has
no entry there today. It now derives the translated bundles from
BOTS_LOCALES and covers `de`, `ru` and anything added later untouched.
That assertion immediately caught a real gap: `group.slashCommandsUnsupported`
landed upstream after this branch was first written and was missing here.

'tools.skillsHub' leaves the echo-check samples. 'Hermes Skills Hub' is a
product name and is identical in German; asserting it differs from English
tests the brand, not the translation. It stays valid for ja/zh/zh-hant via
the remaining three samples.

Depends on `de` being present in the desktop Locale union, which the open
desktop-locale PRs provide; on its own this does not compile.
@Euterer

Euterer commented Sep 14, 2026

Copy link
Copy Markdown
Author

Thanks — both observations acted on. Pushed a revision; the branch is now on current main (d3e2ace).

Key-parity is now a test, not a convention. You were right that the type annotation alone does not hold the line, and the moment I wrote the assertion it caught a real defect in my own branch.

The existing i18n.test.ts already checked parity, but it named its locales one by one:

const ja = BOTS_LOCALES.ja
const zh = BOTS_LOCALES.zh
const zhHant = BOTS_LOCALES['zh-hant']

So a new bundle is covered by nothing until someone remembers to edit the test — which is why there is no ru row there today either. It now derives the translated bundles from BOTS_LOCALES itself:

const translated = Object.entries(BOTS_LOCALES).filter(([id]) => id !== 'en')

de, ru, and anything added later are covered without touching the test again. A toBeGreaterThanOrEqual(3) guard keeps the filter from silently matching nothing, and failures name the locale (`${id} key tree`) instead of just printing two arrays.

What that immediately caught: group.slashCommandsUnsupported landed upstream after this branch was first written, and my de bundle was missing it. My first fix attempt made it worse — I had copied my whole file over the upstream one, which reverted the key in all five bundles. The branch is rebuilt the right way round: the de block is inserted into the current upstream file, so only de is added. Verified 6 occurrences (type + 5 bundles).

One test change beyond the fix, flagged explicitly: I removed 'tools.skillsHub' from the echo-check samples. 'Hermes Skills Hub' is a product name and is identical in German, so asserting it differs from English tests the brand, not the translation. The other three samples keep the assertion meaningful for ja/zh/zh-hant. Happy to revert if you would rather see a per-locale sample list.

On the mixed-English fragments — Cron, Thread, Skills Hub, Bot are deliberate. They are the terms German-speaking users of this product actually use; translating them ("Fadengespräch") would read worse, not better.

Verification (with de registered locally in the Locale union + catalog.ts — the two lines the desktop-locale PRs add, reverted afterwards and not part of this diff):

  • tsc --noEmit: 0 errors in hermes-bots
  • vitest run src/plugins/hermes-bots: 64 files, 597 tests passed
  • negative control: deleting one de key turns the parity test red, as it should

The dependency on the Locale union is unchanged — see the PR description.

OutThisLife added a commit that referenced this pull request Sep 23, 2026
Preserve the existing draft, routing, credential-sharing and avatar behavior. Extend the landed Bot Mode catalogs from #96726/#96878 and #113430; addresses the dialog report in #88798 by NealZhouPanda. Broader #90810 and #101305 remain independent.
OutThisLife added a commit that referenced this pull request Sep 23, 2026
Extend the existing Bot Mode catalogs, preserving schedule syntax, profile routes, capability IDs and user content. Cover locale switches through the real scheduling and editor components. Builds on the landed infrastructure by OutThisLife (#96726/#96878) and teknium1/Vadim Comanescu (#113430); report by NealZhouPanda (#88798). No wholesale supersede of #90810 or #101305.
OutThisLife added a commit that referenced this pull request Sep 23, 2026
Keep the stock selector and English JSONL authoritative. Add zh, zh-hant and ja display copy at each personality rotation position; preserve custom personality names. Reuse core skills-hub translations for advanced settings. Reported by NealZhouPanda in #88798; related broader work #90810 by Oliver Hees and #101305 by Euterer remains independent and is not superseded.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/i18n Localization, locales, translations comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants