Web: eight more UI languages behind a single language registry
Adds Swiss German, French, Italian, Dutch, Danish, Norwegian, Swedish and Finnish — ten selectable languages, each complete at 418/418 keys with matching placeholders and date arrays. A language used to be registered in four unrelated places (dictionary, settings dropdown, date-picker locale ternary, resolver fallback), so adding one meant touching all of them. LANGUAGES in i18n.js is now the single source of truth: adding a language is one entry plus one dictionary, and the dropdown derives from it. The registry also separates the stored code from the BCP-47 tag used for formatting. That distinction is what makes 'ch' safe — "ch" is a country, not a language, and would throw if handed to Intl; it maps to de-CH. Fixes locale handling along the way: fmtTime/fmtDatetime in calendar.js, month.js and week.js hardcoded 'de', so English users saw German-formatted times, and two toLocaleDateString() calls silently used the browser locale instead of the app language. All formatting now goes through getLocale(). Missing keys fall back language → English → German rather than straight to German, and the dead per-dictionary `locale` key is gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
// syncable value so that "not synced" works per browser, plus the declarative
|
||||
// table definition the settings UI renders from. See backend/SETTINGS_SYNC.md.
|
||||
|
||||
import { LANGUAGES } from './i18n.js';
|
||||
|
||||
// Canonical default colours — the single source for the web. Reset writes these.
|
||||
export const DEFAULT_COLORS = {
|
||||
primary_color: '#58B900',
|
||||
@@ -59,9 +61,11 @@ export const SETTING_GROUPS = [
|
||||
{
|
||||
titleKey: 'settings_language',
|
||||
rows: [
|
||||
{ key: 'language', labelKey: 'settings_language', type: 'select', opts: [
|
||||
{ v: 'de', label: 'Deutsch' }, { v: 'en', label: 'English' },
|
||||
] },
|
||||
// Derived from the i18n registry: adding a language there adds it here.
|
||||
// Each language is listed under its own endonym, so the labels are never
|
||||
// translated — a Finn looks for "Suomi", not "Finnisch".
|
||||
{ key: 'language', labelKey: 'settings_language', type: 'select',
|
||||
opts: LANGUAGES.map(l => ({ v: l.code, label: l.label })) },
|
||||
{ key: 'share_calendar_icon', labelKey: 'settings_share_icon', type: 'icon' },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user