use-l10n
Version:
A type-safe localization hook for React
77 lines (72 loc) • 2.85 kB
JavaScript
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