i18n(zh-CN): complete and ship Simplified Chinese

- Translate the remaining 910 strings and review the whole catalog (meaning,
  terms, punctuation, label length) against the screens.
- Register zh-CN: any zh tag maps to it except Traditional ones (Hant, TW,
  HK, MO), which keep English until a Traditional catalog ships.
- Hemisphere letters get their own context so the HUD sector line reads
  21.33N, not a compass word; the Bhote Koshi imagery dates follow
  year-first languages (2021年10月16日).
- cjk.css: tight tracking for Chinese text and a 9px floor on the dock voice
  labels and layer buttons; Latin HUD readouts keep their look.
- docs/translations/zh-CN.md: style, plurals and glossary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-21 12:52:34 +04:00
1 parent db16d8ed4c
commit c4cc499d58
16 files changed
+1422 -199

No files matched your search

+10 -3
View File
@@ -8,25 +8,32 @@ export const LOCALE_STORAGE_KEY = 'gev:locale:v1';
export const DEFAULT_LOCALE = 'en';
/** Shipped locales; order does not matter. Adding one: docs/TRANSLATORS.md. */
export const LOCALES = Object.freeze(['en', 'es', 'ru']);
export const LOCALES = Object.freeze(['en', 'es', 'ru', 'zh-CN']);
/** Each locale named in its own language, for the selector. */
export const LOCALE_NAMES = Object.freeze({
en: 'English',
es: 'Español',
ru: 'Русский',
'zh-CN': '简体中文',
});
/** Right-to-left locales. */
const RTL_LOCALES = Object.freeze([]);
/**
* Map any language tag to a shipped locale: 'ru-RU' and 'RU' → 'ru'.
* Map any language tag to a shipped locale: 'ru-RU' and 'RU' → 'ru',
* 'zh', 'zh-CN' and 'zh-Hans-SG' → 'zh-CN'.
* @returns {string|null}
*/
export function normalizeLocale(candidate) {
if (typeof candidate !== 'string') return null;
const primary = candidate.trim().toLowerCase().split(/[-_]/)[0];
const [primary, ...rest] = candidate.trim().toLowerCase().split(/[-_]/);
// Traditional Chinese readers are not given Simplified: no zh-TW yet.
if (primary === 'zh')
return rest.some((part) => ['hant', 'tw', 'hk', 'mo'].includes(part))
? null
: 'zh-CN';
return LOCALES.includes(primary) ? primary : null;
}