laravel-i18n-react
Version:
A Vite plugin to load Laravel localization files and provide them to React applications.
175 lines (174 loc) • 6.56 kB
JavaScript
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 _a, _b;
import { createElement, useEffect, useState } from 'react';
import { Context } from './context';
import pluralization from './utils/pluralization';
import recognizer from './utils/recognizer';
import replacer from './utils/replacer';
import resolver from './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:
*/
export default function LaravelReactI18nProvider(_a) {
var { children, ssr } = _a, currentOptions = __rest(_a, ["children", "ssr"]);
const [isFirstRender, setIsFirstRender] = useState(true);
const [loading, setLoading] = useState(!isServer);
const [options, setOptions] = useState(Object.assign(Object.assign({}, defaultOptions), currentOptions));
const { getLocales, isLocale } = recognizer(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);
}
}
useEffect(() => {
if (!filesAreEagerlyLoaded) {
if (!translation.get(locale))
fetchLocaleClient(locale);
if (locale !== fallbackLocale && !translation.get(fallbackLocale))
fetchLocaleClient(fallbackLocale);
}
}, [options.locale]);
function fetchLocaleSync(locale) {
const responses = resolver(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 = resolver(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 = resolver(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 = {}) {
var _a, _b, _c, _d;
const { locale, fallbackLocale, prevLocale } = options;
let message = ((_a = translation.get(fallbackLocale)) === null || _a === void 0 ? void 0 : _a[key]) ? translation.get(fallbackLocale)[key] : key;
if (isLocale(locale)) {
if ((_b = translation.get(locale)) === null || _b === void 0 ? void 0 : _b[key]) {
message = translation.get(locale)[key];
}
else if ((_c = translation.get(prevLocale)) === null || _c === void 0 ? void 0 : _c[key]) {
message = translation.get(prevLocale)[key];
}
else if ((_d = translation.get(fallbackLocale)) === null || _d === void 0 ? void 0 : _d[key]) {
message = translation.get(fallbackLocale)[key];
}
}
return replacer(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 replacer(pluralization(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 createElement(Context.Provider, {
value: {
t,
tChoice,
loading,
isLocale,
getLocales,
currentLocale,
setLocale
}
}, children);
}