From 93c3ca35fd3de6a4f12b349f4ed9c4a5d90cfe5f Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Wed, 20 May 2026 23:21:31 +0200 Subject: [PATCH] chore(locales): normalize Korean to ko, keep kr as back-compat alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Korean locale shipped under the wrong code `kr` (that's ISO 3166-1 country, not language). Canonical ISO 639-1 is `ko`. The shipped file was `kr.json` and `localeLoaders` mapped both `ko` and `kr` to it, which `SUPPORTED_LANGUAGES` exposed under `ko` — a dual-code setup that confused every new contributor and was flagged in code review. - Rename `src/i18n/locales/kr.json` -> `ko.json` (via `git mv` so the history follows). - Drop the duplicate `kr` entry from `localeLoaders`; the alias map already redirects `kr` -> `ko` at detection time. - Migrate persisted `localStorage["waveflow-language"] === "kr"` to `"ko"` once at startup so DevTools / future migrations see the canonical value. `convertDetectedLanguage` already normalised on read, so this is purely about cleaning up the stored token. - Keep `kr` in `supportedLngs` so any direct `i18n.changeLanguage("kr")` still resolves (belt-and-suspenders alongside the alias map). - Update `CLAUDE.md` to reflect the new canonical code. --- CLAUDE.md | 2 +- src/i18n/index.ts | 23 ++++++++++++++++++++--- src/i18n/locales/{kr.json => ko.json} | 0 3 files changed, 21 insertions(+), 4 deletions(-) rename src/i18n/locales/{kr.json => ko.json} (100%) diff --git a/CLAUDE.md b/CLAUDE.md index 6829595..9c1ac04 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -116,6 +116,6 @@ Autostart + close-to-tray + scan-on-start ([`commands/preferences.rs`](src-tauri ## Language -The README is in English. The app ships UI copy in **17 locales** via i18next — `fr` (source of truth), `en`, `es`, `de`, `it`, `nl`, `pt`, `pt-BR`, `ru`, `tr`, `id`, `ja`, `kr` (registered as `ko` + `kr` alias), `zh-CN`, `zh-TW`, `ar`, `hi`. Strings in `src/i18n/locales/.json`. `index.ts` sets `document.documentElement.dir` per language so Arabic renders RTL automatically. +The README is in English. The app ships UI copy in **17 locales** via i18next — `fr` (source of truth), `en`, `es`, `de`, `it`, `nl`, `pt`, `pt-BR`, `ru`, `tr`, `id`, `ja`, `ko`, `zh-CN`, `zh-TW`, `ar`, `hi`. Strings in `src/i18n/locales/.json`. `index.ts` sets `document.documentElement.dir` per language so Arabic renders RTL automatically. The legacy `kr` code is still accepted as an alias for back-compat (early builds shipped `kr` instead of the ISO 639-1 `ko`); a one-time migration rewrites stored `kr` preferences to `ko` at startup. `fallbackLng: "en"` is set, but the project convention is **every locale carries every key** so the experience stays coherent without language-mixing. When you add a new key, propagate it to all 17 locales (a small Python script using `json.load`/`dump` with `ensure_ascii=False, indent=2` keeps the existing formatting intact). Brand tokens (`WaveFlow`, `Last.fm`, `Deezer`, `ReplayGain`, `LRCLIB`, `BPM`) stay verbatim across locales. Preserve i18next `{{placeholder}}` interpolation tokens unchanged. diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 7c9b241..ebdea19 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -47,6 +47,21 @@ export const SUPPORTED_LANGUAGES: readonly SupportedLanguage[] = [ const LOCAL_STORAGE_KEY = "waveflow-language"; const SUPPORTED_LANGUAGE_CODES = SUPPORTED_LANGUAGES.map((lang) => lang.code); + +// Rewrite the historical "kr" preference to "ko" once, before i18next +// reads localStorage. `convertDetectedLanguage` already normalises at +// read time, but persisting the canonical value keeps DevTools / future +// migrations honest. +try { + if (typeof localStorage !== "undefined") { + if (localStorage.getItem(LOCAL_STORAGE_KEY) === "kr") { + localStorage.setItem(LOCAL_STORAGE_KEY, "ko"); + } + } +} catch { + // Storage unavailable (private browsing, embed sandbox) — non-fatal, + // the in-memory alias still maps "kr" → "ko" for the session. +} const localeLoaders: Record< string, () => Promise<{ default: ResourceLanguage }> @@ -61,8 +76,7 @@ const localeLoaders: Record< pt: () => import("./locales/pt.json"), "pt-BR": () => import("./locales/pt-BR.json"), ja: () => import("./locales/ja.json"), - ko: () => import("./locales/kr.json"), - kr: () => import("./locales/kr.json"), + ko: () => import("./locales/ko.json"), nl: () => import("./locales/nl.json"), ar: () => import("./locales/ar.json"), hi: () => import("./locales/hi.json"), @@ -76,7 +90,10 @@ const localeLoaders: Record< // OS reporting `fr-FR` or `en-US` lands on `fr` / `en` instead of // falling all the way to the fallback language. const LANGUAGE_ALIASES: Record = { - // Korean — historical "kr" code (the file is still kr.json) + // Korean — historical "kr" code that shipped before we normalised to + // the correct ISO 639-1 "ko". Old profiles may still have "kr" in + // localStorage; the alias keeps them working until they pick a + // language explicitly. kr: "ko", "ko-KR": "ko", // Chinese — pick simplified by default for ambiguous codes; preserve diff --git a/src/i18n/locales/kr.json b/src/i18n/locales/ko.json similarity index 100% rename from src/i18n/locales/kr.json rename to src/i18n/locales/ko.json