mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-10-17 21:20:59 +02:00
feat: german translation
This commit is contained in:
1 parent
d6657eac98
commit
9f7d8d3690
5 files changed
+3554
-4
No files matched your search
@@ -34,7 +34,7 @@ donutbrowser/
|
||||
│ ├── components/ # 50+ React components (dialogs, tables, UI)
|
||||
│ │ └── tips/ # Feature tips: SVG scene primitives and one looping scene per tip
|
||||
│ ├── hooks/ # Event-driven React hooks
|
||||
│ ├── i18n/locales/ # Translations (en, es, fr, ja, ko, pt, ru, tr, vi, zh)
|
||||
│ ├── i18n/locales/ # Translations (de, en, es, fr, ja, ko, pt, ru, tr, vi, zh)
|
||||
│ ├── generated/ # Build-generated third-party license inventory
|
||||
│ ├── lib/ # Utilities (themes, toast, browser-utils)
|
||||
│ └── types.ts # Shared TypeScript interfaces
|
||||
@@ -180,7 +180,7 @@ Linux/Windows swap `~/Library/Logs/com.donutbrowser/` for the platform-appropria
|
||||
|
||||
- Never write user-facing strings as raw English literals in JSX, toast messages, dialog titles/descriptions, button labels, placeholders, table headers, tooltips, or empty-state text. Always go through `t("namespace.key")` from `useTranslation()`.
|
||||
- This applies to every component under `src/`, including new ones. If a component doesn't already import `useTranslation`, add it.
|
||||
- Adding a new string means adding the key to EVERY locale file in `src/i18n/locales/` (currently en, es, fr, ja, ko, pt, ru, tr, vi, zh), not just `en.json`. The English version alone is incomplete work. Don't trust this list: enumerate `src/i18n/locales/*.json` and update every file you find, because a newly added locale is exactly what a hardcoded list silently skips.
|
||||
- Adding a new string means adding the key to EVERY locale file in `src/i18n/locales/` (currently de, en, es, fr, ja, ko, pt, ru, tr, vi, zh), not just `en.json`. The English version alone is incomplete work. Don't trust this list: enumerate `src/i18n/locales/*.json` and update every file you find, because a newly added locale is exactly what a hardcoded list silently skips.
|
||||
- Reuse existing keys (`common.buttons.*`, `common.labels.*`, `createProfile.*`, etc.) before creating new namespaces. Check `en.json` first.
|
||||
- Strings excluded from this rule: `console.log/warn/error`, dev-only debug labels, internal IDs, CSS class names, type names. If unsure whether a string renders to the user, assume it does and translate it.
|
||||
- Never use `t(key, "fallback")` with a default-value second argument. The 2-arg form is forbidden: every key must exist in every locale file before the call site lands. Fallbacks mask missing translations, so a key missing from `ru.json` silently renders the English fallback to Russian users and the bug never surfaces in CI or review. Only call `t("namespace.key")`. If a translation is missing for any locale, that's a bug to fix at the JSON, not a hole to paper over at the call site.
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ codeql database analyze /tmp/codeql-rust --format=sarifv2.1.0 --output=/tmp/rust
|
||||
|
||||
## Key Rules
|
||||
|
||||
- Translations: Any UI text change must be reflected in all 9 locale files (`src/i18n/locales/`)
|
||||
- Translations: Any UI text change must be reflected in all 11 locale files (`src/i18n/locales/`)
|
||||
- Tauri commands: If you modify Tauri commands, the `test_no_unused_tauri_commands` test will catch unused ones
|
||||
- No hardcoded colors: Use theme CSS variables (see `src/lib/themes.ts`), never Tailwind color classes like `text-red-500`
|
||||
- No lock file changes: Don't update `pnpm-lock.yaml` or `Cargo.lock` unless updating dependencies is the purpose of the PR
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
import de from "./locales/de.json";
|
||||
import en from "./locales/en.json";
|
||||
import es from "./locales/es.json";
|
||||
import fr from "./locales/fr.json";
|
||||
@@ -17,6 +18,7 @@ export const SUPPORTED_LANGUAGES = [
|
||||
{ code: "es", name: "Spanish", nativeName: "Español" },
|
||||
{ code: "pt", name: "Portuguese", nativeName: "Português" },
|
||||
{ code: "fr", name: "French", nativeName: "Français" },
|
||||
{ code: "de", name: "German", nativeName: "Deutsch" },
|
||||
{ code: "zh", name: "Chinese", nativeName: "中文" },
|
||||
{ code: "ja", name: "Japanese", nativeName: "日本語" },
|
||||
{ code: "ko", name: "Korean", nativeName: "한국어" },
|
||||
@@ -40,6 +42,11 @@ const LANGUAGE_FALLBACKS: Record<string, string[]> = {
|
||||
"es-ES": ["es", "en"],
|
||||
"fr-CA": ["fr", "en"],
|
||||
"fr-FR": ["fr", "en"],
|
||||
"de-DE": ["de", "en"],
|
||||
"de-AT": ["de", "en"],
|
||||
"de-CH": ["de", "en"],
|
||||
"de-LU": ["de", "en"],
|
||||
"de-LI": ["de", "en"],
|
||||
"vi-VN": ["vi", "en"],
|
||||
};
|
||||
|
||||
@@ -66,6 +73,7 @@ const resources = {
|
||||
es: { translation: es },
|
||||
pt: { translation: pt },
|
||||
fr: { translation: fr },
|
||||
de: { translation: de },
|
||||
zh: { translation: zh },
|
||||
ja: { translation: ja },
|
||||
ko: { translation: ko },
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -149,7 +149,19 @@ test("both keys of every pair have a sentence in every locale", () => {
|
||||
inTheClear,
|
||||
undecided,
|
||||
]);
|
||||
const codes = ["en", "es", "fr", "ja", "ko", "pt", "ru", "tr", "vi", "zh"];
|
||||
const codes = [
|
||||
"de",
|
||||
"en",
|
||||
"es",
|
||||
"fr",
|
||||
"ja",
|
||||
"ko",
|
||||
"pt",
|
||||
"ru",
|
||||
"tr",
|
||||
"vi",
|
||||
"zh",
|
||||
];
|
||||
for (const code of codes) {
|
||||
const bundle = JSON.parse(
|
||||
readFileSync(path.join(LOCALES, `${code}.json`), "utf8"),
|
||||
|
||||
Reference in new issue
Block a user