mirror of
https://github.com/Donkie/Spoolman.git
synced 2026-10-23 02:22:20 -05:00
Introduce full i18n for the Svelte client_v2 using svelte-i18n (ICU/formatjs),
mirroring the old client's language support.
- i18n setup in src/lib/i18n/ (lazy per-language loaders, init + waitLocale boot
guard, setLocale persisted to localStorage, Intl locale helper); 26-language
registry ported from the old client.
- Language picker on the Settings page.
- scripts/convert-locales.mjs seeds static/locales/<lang>/common.json from the
old client's Weblate files: {{var}} -> {var}, escapes literal braces, merges
i18next plural suffixes into ICU plurals. Existing translations are reused via
the same keys; new v2-only strings are added to en/common.json only and fall
back to English until Weblate fills them.
- Extracted all hardcoded UI strings across routes and components to $_ lookups;
DateTimeField derives month/weekday names from Intl in the active locale.
- static/locales is prettier-ignored (mirrors the old client's public/locales).
Follow-up (maintainer): add a Weblate component pointing at
client_v2/static/locales (nested JSON, ICU MessageFormat, English source).
Claude-Session: https://claude.ai/code/session_01Ne7RsfHejKZX97uAq3aVMn
132 lines
5.1 KiB
JavaScript
132 lines
5.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// One-shot seed tool: convert the old React client's i18next locale files into
|
|
// the ICU (svelte-i18n / formatjs) format used by client_v2.
|
|
//
|
|
// node scripts/convert-locales.mjs
|
|
//
|
|
// Reads ../client/public/locales/<lang>/common.json (i18next format)
|
|
// Writes ./static/locales/<lang>/common.json (ICU/formatjs format)
|
|
//
|
|
// The transform is intentionally minimal so existing community translations are
|
|
// preserved as faithfully as possible — see the localization plan. Three
|
|
// transforms are applied to every translatable string leaf:
|
|
// 1. {{var}} -> {var} (i18next interpolation -> ICU placeholder)
|
|
// 2. lone { or } -> '{' '}' (ICU literal-brace escaping)
|
|
// 3. i18next plural-suffix siblings (key_one / key_other / _zero / _two /
|
|
// _few / _many) are merged into a single ICU `{count, plural, ...}` key.
|
|
//
|
|
// After running once, client_v2/static/locales is owned by Weblate. Re-running
|
|
// regenerates from the old files, so only do that for an intentional re-seed.
|
|
|
|
import { readdirSync, readFileSync, mkdirSync, writeFileSync, statSync } from 'fs';
|
|
import { dirname, join } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const SRC_DIR = join(__dirname, '../../client/public/locales');
|
|
const OUT_DIR = join(__dirname, '../static/locales');
|
|
|
|
const PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'];
|
|
|
|
// Sentinels used to protect real interpolations while literal braces are
|
|
// escaped. They are wrapped in NUL/US control chars, which never occur in the
|
|
// translation text, so there is no risk of colliding with real content.
|
|
const OPEN = ' |