/** * Language selection and string lookup. * * Every locale is a real page at a real URL (/, /de/, ...), generated at build time, * because the app is client-rendered: a language that exists only as a runtime string * swap has no URL for a crawler to index. This module is the runtime half — it decides * which locale the current page is, and hands components their strings. * * The rule that matters: the URL wins over everything. Someone who opens /de/ gets * German even if they once chose English here, or a shared link would open in whatever * language the recipient happened to pick last, which makes links unshareable. */ import { DEFAULT_LOCALE, SUPPORTED_LOCALES, LOCALE_META, CROSS_LOCALE_STRINGS } from './generated.js'; // Side-effect import: loading the default locale's dictionary registers the strings // t() falls back to when a translation is missing a key. It is the one dictionary that // has to be present on every page, so it is the one that gets bundled. import './dict/default.js'; export { DEFAULT_LOCALE, SUPPORTED_LOCALES, LOCALE_META }; /** * Loaded dictionaries, by locale code. * * On a global rather than in module scope, and that is the point. index.js exists twice * on a page: once bundled inside dist/app.js, and once as raw source, because the PWA * install prompt, the PWA manager and the update checker import it directly. Two module * instances mean two module-scoped registries, and the /ru/ dictionary loaded by the * page would have been invisible to the half of the app that needed it. * * A page loads its own dictionary through a