UNPKG

lr-i18n

Version:

Allows to connect your `Laravel` Framework localization files with `React`.

183 lines (182 loc) 7.12 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = LaravelReactI18nProvider; const react_1 = require("react"); const context_1 = require("./context"); const pluralization_1 = __importDefault(require("./utils/pluralization")); const recognizer_1 = __importDefault(require("./utils/recognizer")); const replacer_1 = __importDefault(require("./utils/replacer")); const resolver_1 = __importDefault(require("./utils/resolver")); /** * */ const isServer = typeof window === 'undefined'; /** * Map object for translations. */ const translation = new Map(); /** * Get document lang meta from HTML. */ const documentLang = typeof document !== 'undefined' ? ((_b = (_a = document === null || document === void 0 ? void 0 : document.documentElement) === null || _a === void 0 ? void 0 : _a.lang) === null || _b === void 0 ? void 0 : _b.replace('-', '_')) || 'en' : 'en'; /** * The default options. */ const defaultOptions = { locale: documentLang, fallbackLocale: documentLang, prevLocale: documentLang, files: {} }; /** * Laravel React I18n Provider: */ function LaravelReactI18nProvider(_a) { var { children, ssr } = _a, currentOptions = __rest(_a, ["children", "ssr"]); const [isFirstRender, setIsFirstRender] = (0, react_1.useState)(true); const [loading, setLoading] = (0, react_1.useState)(!isServer); const [options, setOptions] = (0, react_1.useState)(Object.assign(Object.assign({}, defaultOptions), currentOptions)); const { getLocales, isLocale } = (0, recognizer_1.default)(options.files); // Determine if files are eagerly loaded. const filesAreEagerlyLoaded = Object.values(options.files).every((value) => typeof value === 'object' && value !== null); const { locale, fallbackLocale } = options; if (!translation.get(locale)) { if (filesAreEagerlyLoaded) { fetchLocaleSync(locale); } else if (isServer) { fetchLocaleServer(locale); } } if (locale !== fallbackLocale && !translation.get(fallbackLocale)) { if (filesAreEagerlyLoaded) { fetchLocaleSync(fallbackLocale); } else if (isServer) { fetchLocaleServer(fallbackLocale); } } (0, react_1.useEffect)(() => { if (!filesAreEagerlyLoaded) { if (!translation.get(locale)) fetchLocaleClient(locale); if (locale !== fallbackLocale && !translation.get(fallbackLocale)) fetchLocaleClient(fallbackLocale); } }, [options.locale]); function fetchLocaleSync(locale) { const responses = (0, resolver_1.default)(options.files, locale); for (const response of responses) { translation.set(locale, Object.assign(Object.assign({}, (translation.get(locale) || {})), response.default)); } } /** * Initialise translations for server. */ if (isServer) { const { locale, fallbackLocale } = options; if (!translation.get(locale)) fetchLocaleServer(locale); if (locale !== fallbackLocale && !translation.get(fallbackLocale)) fetchLocaleServer(fallbackLocale); } /** * Fetching locale for client side. */ function fetchLocaleClient(locale) { const promises = (0, resolver_1.default)(options.files, locale); setLoading(true); Promise.all(promises) .then((responses) => { for (const response of responses) { translation.set(locale, Object.assign(Object.assign({}, (translation.get(locale) || {})), response.default)); } }) .then(() => { if (isFirstRender) setIsFirstRender(false); setLoading(false); }); } /** * Fetching locale for server side. */ function fetchLocaleServer(locale) { const responses = (0, resolver_1.default)(options.files, locale); for (const response of responses) { translation.set(locale, Object.assign(Object.assign({}, (translation.get(locale) || {})), response.default)); } } /** * Get the translation for the given key. */ function t(key, replacements = {}) { const { locale, fallbackLocale, prevLocale } = options; function getNestedValue(obj, keyPath) { return keyPath.split('.').reduce((acc, part) => (acc && acc[part] !== undefined ? acc[part] : undefined), obj); } let message = getNestedValue(translation.get(fallbackLocale) || {}, key) || key; if (isLocale(locale)) { if (getNestedValue(translation.get(locale) || {}, key)) { message = getNestedValue(translation.get(locale), key); } else if (getNestedValue(translation.get(prevLocale) || {}, key)) { message = getNestedValue(translation.get(prevLocale), key); } else if (getNestedValue(translation.get(fallbackLocale) || {}, key)) { message = getNestedValue(translation.get(fallbackLocale), key); } } return (0, replacer_1.default)(message, replacements); } /** * Translates the given message based on a count. */ function tChoice(key, number, replacements = {}) { const message = t(key, replacements); const locale = isLocale(options.locale) ? options.locale : options.fallbackLocale; return (0, replacer_1.default)((0, pluralization_1.default)(message, number, locale), Object.assign(Object.assign({}, replacements), { count: number.toString() })); } /** * Set locale. */ function setLocale(locale) { if (!isServer) { // When setting the HTML lang attribute, hyphen must be use instead of underscore. document.documentElement.setAttribute('lang', locale.replace('_', '-')); } setOptions((prevState) => (Object.assign(Object.assign({}, options), { locale, prevLocale: prevState.locale }))); } /** * Current locale. */ function currentLocale() { return options.locale || options.fallbackLocale; } return (0, react_1.createElement)(context_1.Context.Provider, { value: { t, tChoice, loading, isLocale, getLocales, currentLocale, setLocale } }, children); }