UNPKG

use-l10n

Version:

A type-safe localization hook for React

77 lines (72 loc) 2.85 kB
import { jsx, Fragment } from 'react/jsx-runtime'; import { createContext, useContext } from 'react'; class LocalizationTable { table; aliases; constructor(table, aliases) { this.table = table; this.aliases = aliases; } getString(language, key) { if (!(language in this.table)) { throw new Error(`Language ${language} not found in localization table. Please use getLanguage to get available languages.`); } if (!(key in this.table[language])) { throw new Error(`Key ${key} not found in localization table for language ${language}.`); } return this.table[language][key]; } getLanguage(language) { for (const [alias, lang] of this.aliases) { if (alias.test(language)) { return lang; } } if (language in this.table) { return language; } return null; } } function getBrowserLanguage() { // Use URL parameter ?lang=ja or navigator.language const navigatorLanguage = navigator.language; const langParam = new URL(location.href).searchParams.get("lang"); return langParam ?? navigatorLanguage; } const createLocalizationContext = () => createContext({ language: null, }); const createUseCurrentLanguage = (LocalizationContext, localizationTable, primaryLanguage) => { return () => { const context = useContext(LocalizationContext); if (!context) { throw new Error("useLocalized must be used within a LocalizationContext"); } const language = context.language ?? getBrowserLanguage(); return localizationTable.getLanguage(language) ?? primaryLanguage; }; }; const createUseLocalization = (localizationTable, useCurrentLanguage) => { return () => { const language = useCurrentLanguage(); return new Proxy({}, { get: (_, key) => localizationTable.getString(language, key), }); }; }; const createComponent = (useLocalization) => ({ name }) => { const localized = useLocalization(); return jsx(Fragment, { children: localized[name] }); }; const createLocalization = (table, primaryLanguage, aliases = []) => { const LocalizationContext = createLocalizationContext(); const localizationTable = new LocalizationTable(table, aliases); const firstLanguage = primaryLanguage ?? Object.keys(table)[0]; const useCurrentLanguage = createUseCurrentLanguage(LocalizationContext, localizationTable, firstLanguage); const useLocalization = createUseLocalization(localizationTable, useCurrentLanguage); const Localized = createComponent(useLocalization); return { LocalizationContext, useCurrentLanguage, useLocalization, Localized }; }; export { createLocalization }; //# sourceMappingURL=index.js.map