/** * @module i18n/catalogue * Registry of translation files, filled by the application at startup. * * A bundler resolves import paths relative to the file that contains them, so a * library can never discover translation files that live in an application. The * application therefore hands its files to the library instead. * * @example * // Vite * import { registerCatalogue } from '@relax.js/core/i18n'; * registerCatalogue(import.meta.glob('./locales/*\/*.json', { eager: true })); * * @example * // Any bundler, or no bundler at all * import { registerNamespace } from '@relax.js/core/i18n'; * import shellEn from './locales/en/shell.json'; * registerNamespace('en', 'shell', shellEn); */ export type TranslationMap = Record; /** * Loads a namespace the first time it is used, so translations for locales * nobody selects stay out of the initial download. */ export type NamespaceLoader = () => Promise; /** * A namespace given either as ready messages or as a loader that fetches them. */ export type NamespaceSource = TranslationMap | NamespaceLoader; /** * Reduces `en-US` to `en`, so a browser language matches a translation folder. */ export declare function normalizeLocale(locale: string): string; /** * Adds a single namespace to the catalogue. * * Registering the same locale and namespace twice replaces the previous entry, * which lets an application override a built-in namespace such as `r-validation`. * * @param locale - Locale code, normalized the same way as `setLocale()` * @param namespace - Namespace name used in front of the colon in `t('shell:title')` * @param source - The messages, or a function that loads them on first use * * @example * import shellEn from './locales/en/shell.json'; * registerNamespace('en', 'shell', shellEn); * * @example * registerNamespace('sv', 'shell', () => import('./locales/sv/shell.json')); */ export declare function registerNamespace(locale: string, namespace: string, source: NamespaceSource): void; /** * Adds every namespace in a path-keyed record, so a whole `locales/` folder is * registered in one call. * * The locale and namespace are read from the last two segments of each key, so * `./locales/en/shell.json` becomes locale `en` and namespace `shell`. Values may * be the messages, a module with the messages as its default export, or a * function returning either. That covers Vite's eager and lazy `import.meta.glob`, * webpack's `require.context`, and a plain object written by hand. * * @param modules - Record keyed by file path * * @example * // Vite, everything in the first download * registerCatalogue(import.meta.glob('./locales/*\/*.json', { eager: true })); * * @example * // Vite, each locale downloaded when it is first selected * registerCatalogue(import.meta.glob('./locales/*\/*.json')); * * @example * // No bundler * registerCatalogue({ * './locales/en/shell.json': { title: 'Dashboard' }, * './locales/sv/shell.json': { title: 'Instrumentpanel' }, * }); */ export declare function registerCatalogue(modules: Record): void; /** * Returns the messages for a namespace, or `undefined` when it was never registered. * * Rejects when a registered loader fails, so a network error is reported rather * than mistaken for a namespace nobody registered. */ export declare function resolveNamespace(locale: string, namespace: string): Promise;