feat(i18n): added german translation (de-DE)#571
feat(i18n): added german translation (de-DE)#571miko007 wants to merge 3 commits intojamiepine:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (2)
📝 WalkthroughWalkthroughAdds 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 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 ofsettings.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 togetDateLocale()for German date formatting.The function at
app/src/lib/utils/format.ts(lines 11–22) only handlesja,zh-CN, andzh-TW. German dates will render in English (the default) instead of German (e.g., "vor 2 Tagen" for relative dates). Importdefromdate-fns/localeand 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
📒 Files selected for processing (2)
app/src/i18n/index.tsapp/src/i18n/locales/de/translation.json
| .init({ | ||
| resources: { | ||
| en: { translation: en }, | ||
| de: { translation: de }, |
There was a problem hiding this comment.
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.
| 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.
| "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." |
There was a problem hiding this comment.
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.
| "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" | ||
| } |
There was a problem hiding this comment.
🧩 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.
There was a problem hiding this comment.
i assumed the "names" of the voices as actual names, hence translating them did not make sense.
There was a problem hiding this comment.
Only users with a collaborator, contributor, member, or owner role can interact with CodeRabbit.
| "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}}" |
There was a problem hiding this comment.
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}}").
There was a problem hiding this comment.
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
📒 Files selected for processing (1)
app/src/lib/utils/format.ts
Added german translation and made the german language selectable in settings.
Summary by CodeRabbit