Skip to content

feat(i18n): added german translation (de-DE)#571

Open
miko007 wants to merge 3 commits intojamiepine:mainfrom
miko007:feature/lang-de
Open

feat(i18n): added german translation (de-DE)#571
miko007 wants to merge 3 commits intojamiepine:mainfrom
miko007:feature/lang-de

Conversation

@miko007
Copy link
Copy Markdown

@miko007 miko007 commented Apr 27, 2026

Added german translation and made the german language selectable in settings.

Summary by CodeRabbit

  • New Features
    • German (Deutsch) UI support added with comprehensive translations across the app.
  • Localization
    • German now appears as an available language in language selection and detection.
  • Bug Fixes
    • Date/locale handling improved to format dates correctly for German users.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 691199a1-eced-45ef-8415-8a47fea69726

📥 Commits

Reviewing files that changed from the base of the PR and between 12e03fb and ca5f89e.

📒 Files selected for processing (2)
  • app/src/i18n/locales/de/translation.json
  • app/src/lib/utils/format.ts
✅ Files skipped from review due to trivial changes (2)
  • app/src/lib/utils/format.ts
  • app/src/i18n/locales/de/translation.json

📝 Walkthrough

Walkthrough

Adds German localization: registers German translations, adds a comprehensive German translation JSON, and updates date-fns locale handling to return the German locale when language is de.

Changes

Cohort / File(s) Summary
i18n Configuration
app/src/i18n/index.ts
Imports German translations, adds { code: 'de', label: 'Deutsch' } to SUPPORTED_LANGUAGES, registers de: { translation: de } in i18next resources, and expands LanguageCode to include 'de'.
German Translation Resources
app/src/i18n/locales/de/translation.json
New comprehensive German translation file covering many UI domains (navigation, audio, profiles, samples, effects, stories, history, generation, settings, GPU/backend, logs, models). Includes pluralization and templated variables.
Date locale utility
app/src/lib/utils/format.ts
Adds import for date-fns/locale/de and extends getDateLocale() to return the German locale when i18n.language === 'de'.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Ich hopple leis' und bring' dir 'Deutsch' heut',

Wörter blühen auf im neuen Kleid.
Menüs und Meldungen nun freundlich und klar,
Ein kleines Hopp — die App spricht wunderbar. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding German translation support. It accurately reflects the primary objective of the changeset across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
app/src/i18n/locales/de/translation.json (1)

734-736: Stray blank line inside the JSON object.

Line 735 is an empty line between "devHint" and the closing brace of settings.logs. It's valid JSON, but inconsistent with the rest of the file and likely to be flagged by the formatter.

       "devHint": "Server-Logs werden nur erfasst, wenn die App den Serverprozess verwaltet (Produktions-Builds)."
-
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/locales/de/translation.json` around lines 734 - 736, Remove the
stray empty line inside the JSON object for settings.logs: delete the blank line
between the "devHint" entry and the closing brace for the settings.logs object
so the block matches the file's formatting style; ensure the "devHint" line
remains intact and the object closing brace follows it directly, then run the
project's JSON/formatter to verify consistency.
app/src/i18n/index.ts (1)

5-5: Add 'de' case to getDateLocale() for German date formatting.

The function at app/src/lib/utils/format.ts (lines 11–22) only handles ja, zh-CN, and zh-TW. German dates will render in English (the default) instead of German (e.g., "vor 2 Tagen" for relative dates). Import de from date-fns/locale and add a case to match the UI language:

Suggested implementation
// app/src/lib/utils/format.ts
import { de, ja, zhCN, zhTW } from 'date-fns/locale';

function getDateLocale() {
  switch (i18n.language) {
    case 'de':
      return de;
    case 'ja':
      return ja;
    case 'zh-CN':
      return zhCN;
    case 'zh-TW':
      return zhTW;
    default:
      return undefined;
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/index.ts` at line 5, Update getDateLocale in
app/src/lib/utils/format.ts to return the German locale: import de from
'date-fns/locale' (alongside existing ja, zhCN, zhTW imports) and add a case
'de' in the switch inside getDateLocale to return de; ensure the default
behavior remains unchanged if no match is found and reference the function name
getDateLocale so you modify the correct location.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/i18n/index.ts`:
- Line 26: The indentation for the resources entry "de: { translation: de },"
uses a tab character while surrounding entries use spaces; open the resources
object in app/src/i18n/index.ts and replace the leading tab on the line
containing "de: { translation: de }," with the same number of spaces used for
the other locale entries so indentation is consistent.

In `@app/src/i18n/locales/de/translation.json`:
- Around line 415-426: The translations under the keys stories.* and
storyContent.* use the English "Story/Stories" while nav.stories uses
"Unterhaltungen"; choose one term and make it consistent: either change
nav.stories to the English loanword or translate all occurrences of
"Story"/"Stories" in stories.* and storyContent.* to
"Unterhaltung"/"Unterhaltungen" (and related inflections), including keys
referenced like storyContent.itemActions.removeFromStory,
storyContent.empty.title, stories.title, stories.newStory, stories.loading,
stories.empty.hint, stories.row.itemCount_* and aria/actions labels so the UI
displays the same German term everywhere. Ensure plural forms and aria labels
keep correct grammar and placeholders (e.g., "{{count}}", "{{name}}",
"{{updated}}").
- Around line 85-107: Several translation keys use informal "du/dein" while the
file predominantly uses formal "Sie/Ihr"; change the informal strings to formal
phrasing to be consistent: update audioChannels.createDialog.description and
action,
profileForm.createTitle/createDescription/editTitle/editDescription/draftRestored/discard
and nested keys profileForm.source.clone and profileForm.builtin.hint/badge/note
(and the similar informal strings referenced around the section flagged at the
end) to use "Sie/Ihr" forms (e.g., "Erstellen Sie …", "Aktualisieren Sie …",
"Ihr Stimmprofil") and adjust phrasing where necessary so grammar and
possessives are correct for formal address across these keys.
- Line 417: Replace the ASCII ellipsis in the translation value for the
"loading" key so it uses the single-character Unicode ellipsis (…); locate the
"loading" entry ("loading": "Lade Stories...") and update the string to "Lade
Stories…" to match the rest of the file's ellipsis usage.
- Around line 396-411: The preset name values for the keys "Robotic", "Radio",
"Echo Chamber", and "Deep Voice" are still in English; update the value of each
"name" property under these keys so they are localized to German (e.g., set
"Robotic" -> name: "Roboterhaft" (or similar), "Radio" -> name: "Radio" (if
appropriate), "Echo Chamber" -> name: "Echokammer", and "Deep Voice" -> name:
"Tiefe Stimme") so the translation path effects.builtinPresets.${p.name}.name
returns a German label for each preset.

---

Nitpick comments:
In `@app/src/i18n/index.ts`:
- Line 5: Update getDateLocale in app/src/lib/utils/format.ts to return the
German locale: import de from 'date-fns/locale' (alongside existing ja, zhCN,
zhTW imports) and add a case 'de' in the switch inside getDateLocale to return
de; ensure the default behavior remains unchanged if no match is found and
reference the function name getDateLocale so you modify the correct location.

In `@app/src/i18n/locales/de/translation.json`:
- Around line 734-736: Remove the stray empty line inside the JSON object for
settings.logs: delete the blank line between the "devHint" entry and the closing
brace for the settings.logs object so the block matches the file's formatting
style; ensure the "devHint" line remains intact and the object closing brace
follows it directly, then run the project's JSON/formatter to verify
consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ebbd8179-a85e-4a28-b954-8d1ca363582f

📥 Commits

Reviewing files that changed from the base of the PR and between b35b909 and 214c621.

📒 Files selected for processing (2)
  • app/src/i18n/index.ts
  • app/src/i18n/locales/de/translation.json

Comment thread app/src/i18n/index.ts
.init({
resources: {
en: { translation: en },
de: { translation: de },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Mixed indentation: tab character on this line.

Line 26 starts with a literal tab while the surrounding resources entries are indented with spaces. This will likely show up as a formatting/lint diff and looks misaligned in editors with non-default tab widths.

🔧 Proposed fix
       en: { translation: en },
-	  de: { translation: de },
+      de: { translation: de },
       ja: { translation: ja },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
de: { translation: de },
en: { translation: en },
de: { translation: de },
ja: { translation: ja },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/index.ts` at line 26, The indentation for the resources entry
"de: { translation: de }," uses a tab character while surrounding entries use
spaces; open the resources object in app/src/i18n/index.ts and replace the
leading tab on the line containing "de: { translation: de }," with the same
number of spaces used for the other locale entries so indentation is consistent.

Comment on lines +85 to +107
"description": "Erstelle einen neuen Audiokanal (Bus), um Stimmen an bestimmte Ausgabegeräte zu leiten.",
"action": "Erstellen"
},
"editDialog": {
"title": "Kanal bearbeiten",
"description": "Aktualisiere die Kanaleinstellungen und die Zuweisung von Stimmen."
}
},
"profileForm": {
"createTitle": "Stimme erstellen",
"editTitle": "Stimme bearbeiten",
"createDescription": "Erstelle ein neues Stimmprofil aus einer Audioaufnahme oder einer integrierten Stimme.",
"editDescription": "Aktualisiere die Details deines Stimmprofils und verwalte die Aufnahmen.",
"draftRestored": "Entwurf wiederhergestellt",
"discard": "Verwerfen",
"source": {
"clone": "Von Audio klonen",
"builtin": "Integrierte Stimme"
},
"builtin": {
"hint": "Wähle eine vorgefertigte Stimme. Diese erfordert keine Audioaufnahme.",
"badge": "Integrierte Stimme",
"note": "Dieses Profil verwendet eine integrierte Stimme. Die Stimme kann nach der Erstellung nicht geändert werden."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent address style: mix of formal "Sie/Ihr" and informal "du/dein".

The translations switch between formal Sie-Anrede and informal Du-Anrede, sometimes within the same screen. Pick one consistently — German UIs are typically all formal or all informal, and mixing reads unprofessionally.

Examples of the inconsistency (non-exhaustive):

  • Informal: line 85 "Erstelle einen neuen Audiokanal …", line 96 "Erstelle ein neues Stimmprofil …", line 97 "Aktualisiere die Details deines Stimmprofils …", line 105 "Wähle eine vorgefertigte Stimme.", line 534 "Wähle ein Sprachprofil oben…", line 545 "Intonationsanweisungen — z.B. langsam und warm sprechen …".
  • Formal in adjacent strings: line 64 "Erstellen Sie Ihren ersten Kanal …", line 156 "Bitte wählen Sie zuerst eine Audiodatei …", line 420 "Erstellen Sie Ihre erste Story …", line 430 "Erstellen Sie eine neue Story …", line 463 "Wählen Sie eine Story …", line 539 "Wählen Sie zuerst ein Sprachprofil", line 581 "Wählen Sie die Anzeigesprache …".

Note in particular audioChannels.createDialog (line 85, "Erstelle…") vs stories.createDialog (line 430, "Erstellen Sie…") — same component shape, opposite style. The bulk of the file uses Sie, so converting the small number of informal strings to formal is probably the smaller diff.

Also applies to: 534-545

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/locales/de/translation.json` around lines 85 - 107, Several
translation keys use informal "du/dein" while the file predominantly uses formal
"Sie/Ihr"; change the informal strings to formal phrasing to be consistent:
update audioChannels.createDialog.description and action,
profileForm.createTitle/createDescription/editTitle/editDescription/draftRestored/discard
and nested keys profileForm.source.clone and profileForm.builtin.hint/badge/note
(and the similar informal strings referenced around the section flagged at the
end) to use "Sie/Ihr" forms (e.g., "Erstellen Sie …", "Aktualisieren Sie …",
"Ihr Stimmprofil") and adjust phrasing where necessary so grammar and
possessives are correct for formal address across these keys.

Comment on lines +396 to +411
"Robotic": {
"name": "Robotic",
"description": "Metallische Roboterstimme (Flanger mit langsamen LFO und hohem Feedback)"
},
"Radio": {
"name": "Radio",
"description": "Dünne AM-Radio-Stimme mit Bandpassfilterung und leichter Kompression"
},
"Echo Chamber": {
"name": "Echo Chamber",
"description": "Weitläufiger Reverb mit nachklingendem Echo"
},
"Deep Voice": {
"name": "Deep Voice",
"description": "Tiefere Stimme mit zusätzlicher Wärme"
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect how built-in preset names/keys are consumed.
fd -t f 'translation.json' --exec sh -c 'echo "=== {} ==="; jq ".effects.builtinPresets // empty" {}'
echo "--- references to builtinPresets ---"
rg -nP --type=ts -C2 'builtinPresets|BUILTIN_PRESETS|"Robotic"|"Echo Chamber"'

Repository: jamiepine/voicebox

Length of output: 4788


The German translation is incomplete—translate the preset name fields to match other languages.

The name fields must be localized. The code constructs translation paths as effects.builtinPresets.${p.name}.name (where p.name is the backend identifier), and other locales already provide translations for the displayed names:

  • Japanese: "name": "ロボット", "ラジオ", "エコーチェンバー", "ディープボイス"
  • Chinese (both variants): Similar translated names

The keys in the translation file ("Robotic", "Radio", "Echo Chamber", "Deep Voice") correctly remain in English to match backend identifiers, but the name values should be translated to German:

  • "Robotic""name": "Roboterhaft" or similar
  • "Radio""name": "Radio" (may be acceptable as-is if appropriate)
  • "Echo Chamber""name": "Echokammer"
  • "Deep Voice""name": "Tiefe Stimme"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/locales/de/translation.json` around lines 396 - 411, The preset
name values for the keys "Robotic", "Radio", "Echo Chamber", and "Deep Voice"
are still in English; update the value of each "name" property under these keys
so they are localized to German (e.g., set "Robotic" -> name: "Roboterhaft" (or
similar), "Radio" -> name: "Radio" (if appropriate), "Echo Chamber" -> name:
"Echokammer", and "Deep Voice" -> name: "Tiefe Stimme") so the translation path
effects.builtinPresets.${p.name}.name returns a German label for each preset.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i assumed the "names" of the voices as actual names, hence translating them did not make sense.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only users with a collaborator, contributor, member, or owner role can interact with CodeRabbit.

Comment on lines +415 to +426
"title": "Stories",
"newStory": "Neue Story",
"loading": "Lade Stories...",
"empty": {
"title": "Noch keine Stories",
"hint": "Erstellen Sie Ihre erste Story, um zu beginnen"
},
"row": {
"itemCount_one": "{{count}} Element",
"itemCount_other": "{{count}} Elemente",
"ariaLabel": "Story {{name}}, {{count}} Elemente, {{updated}}",
"actionsLabel": "Aktionen für {{name}}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

stories.* leaves "Story/Stories" untranslated, conflicting with nav.stories: "Unterhaltungen".

nav.stories is rendered as "Unterhaltungen" (line 16), but the screen those nav items lead to keeps "Stories" / "Story" literally throughout stories.* and storyContent.* (lines 415–489). Users will navigate to Unterhaltungen and land on a screen titled Stories, with copy like "Noch keine Stories" and "Erstellen Sie Ihre erste Story".

Pick a single term and apply it everywhere (either keep the English loanword "Story/Stories" in nav too, or translate consistently — e.g., "Unterhaltung/Unterhaltungen" or "Geschichte/Geschichten"). Same applies to storyContent.itemActions.removeFromStory, storyContent.empty.title, etc.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/i18n/locales/de/translation.json` around lines 415 - 426, The
translations under the keys stories.* and storyContent.* use the English
"Story/Stories" while nav.stories uses "Unterhaltungen"; choose one term and
make it consistent: either change nav.stories to the English loanword or
translate all occurrences of "Story"/"Stories" in stories.* and storyContent.*
to "Unterhaltung"/"Unterhaltungen" (and related inflections), including keys
referenced like storyContent.itemActions.removeFromStory,
storyContent.empty.title, stories.title, stories.newStory, stories.loading,
stories.empty.hint, stories.row.itemCount_* and aria/actions labels so the UI
displays the same German term everywhere. Ensure plural forms and aria labels
keep correct grammar and placeholders (e.g., "{{count}}", "{{name}}",
"{{updated}}").

Comment thread app/src/i18n/locales/de/translation.json Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/lib/utils/format.ts`:
- Around line 19-20: The switch case for German is using the wrong label and
missing a return: change the case from 'de-DE' to 'de' and add "return de;"
inside that case so the imported de locale is actually returned (this fixes the
switch in format.ts where the case for 'de' currently falls through to default
and returns undefined).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f486733-5c23-4cb9-bad4-7f29b0a299b1

📥 Commits

Reviewing files that changed from the base of the PR and between 214c621 and 12e03fb.

📒 Files selected for processing (1)
  • app/src/lib/utils/format.ts

Comment thread app/src/lib/utils/format.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant