fast-react-i18n
Version:
Minimalist i18n library for React and Next.js
171 lines (164 loc) • 5.41 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
I18nProvider: () => I18nProvider,
clearTranslationsCache: () => clearTranslationsCache,
detectUserLocale: () => detectUserLocale,
loadAvailableLocales: () => loadAvailableLocales,
useForceReloadTranslations: () => useForceReloadTranslations,
useTranslation: () => useTranslation
});
module.exports = __toCommonJS(index_exports);
// src/I18nProvider.tsx
var import_react = require("react");
// src/loadTranslations.ts
var loadTranslations = async (path, locale) => {
try {
const res = await fetch(`${path}/${locale}.json`);
if (!res.ok) throw new Error(`No se pudo cargar: ${path}/${locale}.json`);
return await res.json();
} catch {
console.warn(`[i18n] No se pudo cargar: ${path}/${locale}.json`);
return {};
}
};
// src/utils/load.ts
async function load(path, locale, fallbackLocale) {
try {
return await loadTranslations(path, locale);
} catch (error) {
console.warn(`[i18n] No se pudo cargar ${locale}, intentando fallback...`);
if (fallbackLocale && fallbackLocale !== locale) {
try {
return await loadTranslations(path, fallbackLocale);
} catch (fallbackError) {
console.error(
`[i18n] Tampoco se pudo cargar el fallback: ${fallbackLocale}`,
fallbackError
);
}
}
return {};
}
}
// src/I18nProvider.tsx
var import_jsx_runtime = require("react/jsx-runtime");
var I18nContext = (0, import_react.createContext)({
locale: "en",
translations: {},
setLocale: () => {
},
setTranslations: () => {
}
});
var useI18nContext = () => (0, import_react.useContext)(I18nContext);
var I18nProvider = ({
initialLocale,
fallbackLocale,
translationsPath,
persist = false,
children
}) => {
const [locale, setLocale] = (0, import_react.useState)(initialLocale || "auto");
const [translations, setTranslations] = (0, import_react.useState)({});
const cacheRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
(0, import_react.useEffect)(() => {
const resolvedLocale = locale === "auto" ? typeof navigator !== "undefined" ? navigator.language.split("-")[0] : "en" : locale;
if (locale === "auto") {
setLocale(resolvedLocale);
}
async function fetchTranslations() {
if (persist) {
const cached = localStorage.getItem(`i18n_${resolvedLocale}`);
if (cached) {
setTranslations(JSON.parse(cached));
return;
}
}
const cachedInMemory = cacheRef.current.get(resolvedLocale);
if (cachedInMemory) {
setTranslations(cachedInMemory);
return;
}
const res = await load(translationsPath, resolvedLocale, fallbackLocale);
setTranslations(res);
cacheRef.current.set(resolvedLocale, res);
if (persist) {
localStorage.setItem(`i18n_${resolvedLocale}`, JSON.stringify(res));
}
}
fetchTranslations();
}, [locale, translationsPath, fallbackLocale, persist]);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
I18nContext.Provider,
{
value: { locale, translations, setLocale, setTranslations },
children
}
);
};
// src/utils/functions.ts
var clearTranslationsCache = () => {
Object.keys(localStorage).forEach((key) => {
if (key.startsWith("i18n_")) {
localStorage.removeItem(key);
}
});
};
var useTranslation = () => {
const { translations } = useI18nContext();
return { translations };
};
var detectUserLocale = () => {
if (typeof window === "undefined") return "en";
const urlParams = new URLSearchParams(window.location.search);
const langQuery = urlParams.get("lang");
if (langQuery) return langQuery.split("-")[0];
const match = document.cookie.match(/(^| )lang=([^;]+)/);
if (match) return match[2].split("-")[0];
if (navigator.language) return navigator.language.split("-")[0];
return "en";
};
var useForceReloadTranslations = () => {
const { locale, setTranslations } = useI18nContext();
return async (path, fallbackLocale) => {
const data = await load(path, locale, fallbackLocale);
setTranslations(data);
};
};
var loadAvailableLocales = async (path) => {
try {
const res = await fetch(`${path}/locales.json`);
if (!res.ok) throw new Error("Failed to load locales");
return await res.json();
} catch {
return [];
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
I18nProvider,
clearTranslationsCache,
detectUserLocale,
loadAvailableLocales,
useForceReloadTranslations,
useTranslation
});