next-i18next
Version:
The easiest way to translate your NextJs apps.
165 lines (164 loc) • 6.21 kB
JavaScript
'use client';
"use client";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let react = require("react");
react = __toESM(react);
let i18next = require("i18next");
let react_i18next = require("react-i18next");
let react_i18next_initReactI18next = require("react-i18next/initReactI18next");
let i18next_resources_to_backend = require("i18next-resources-to-backend");
i18next_resources_to_backend = __toESM(i18next_resources_to_backend);
let next_navigation = require("next/navigation");
let react_jsx_runtime = require("react/jsx-runtime");
//#region src/appRouter/client.tsx
/**
* Client-side i18next provider for App Router.
* Creates an i18next instance hydrated with server-loaded resources,
* with fallback dynamic loading for additional namespaces.
*
* Supports custom backends via the `use` prop — pass i18next-http-backend,
* i18next-locize-backend, or i18next-chained-backend to load translations
* from external sources.
*
* @example
* ```tsx
* // In app/[lng]/layout.tsx (Server Component)
* import { I18nProvider } from 'next-i18next/client'
* import { getT, getResources } from 'next-i18next/server'
*
* export default async function Layout({ children, params }) {
* const { lng } = await params
* const { i18n } = await getT()
* const resources = getResources(i18n, ['common'])
* return (
* <I18nProvider language={lng} resources={resources}>
* {children}
* </I18nProvider>
* )
* }
* ```
*/
function I18nProvider({ children, language, resources, supportedLngs, defaultNS = "common", fallbackLng, localePath = "/locales", localeStructure = "{{lng}}/{{ns}}", localeExtension = "json", use = [], i18nextOptions = {} }) {
const [instance] = (0, react.useState)(() => {
const inst = (0, i18next.createInstance)();
inst.use(react_i18next_initReactI18next.initReactI18next);
const userHasBackend = use.some((b) => b.type === "backend");
const bundledNsSet = resources ? new Set(Object.values(resources).flatMap((r) => Object.keys(r))) : /* @__PURE__ */ new Set();
const bundledNs = bundledNsSet.size > 0 ? [...bundledNsSet] : [defaultNS];
if (!userHasBackend) inst.use((0, i18next_resources_to_backend.default)((lng, ns) => {
if (bundledNsSet.has(ns)) return {};
const path = `${localePath}/${localeStructure.replace("{{lng}}", lng).replace("{{ns}}", ns)}.${localeExtension}`;
return fetch(path).then((r) => r.ok ? r.json() : {});
}));
use.forEach((plugin) => inst.use(plugin));
const hasAnyBackend = userHasBackend || !resources;
inst.init({
lng: language,
resources,
ns: bundledNs,
partialBundledLanguages: hasAnyBackend,
defaultNS,
fallbackLng: fallbackLng ?? language,
supportedLngs: supportedLngs ?? (resources ? Object.keys(resources) : [language]),
fallbackNS: defaultNS,
interpolation: { escapeValue: false },
react: { useSuspense: false },
...i18nextOptions
});
return inst;
});
(0, react.useEffect)(() => {
if (instance.language !== language) instance.changeLanguage(language);
}, [instance, language]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_i18next.I18nextProvider, {
i18n: instance,
children
});
}
/**
* Translation hook for Client Components in App Router.
* Works in both locale-in-path and no-locale-path modes:
* - Locale-in-path: reads language from URL params (`[lng]` or `[locale]`) and syncs
* - No-locale-path: uses the language set by I18nProvider (from server detection)
*
* @example
* ```tsx
* 'use client'
* import { useT } from 'next-i18next/client'
*
* export default function Counter() {
* const { t } = useT('home')
* return <p>{t('greeting')}</p>
* }
* ```
*/
function useT(ns, options) {
const params = (0, next_navigation.useParams)();
const lngFromParams = typeof params?.lng === "string" ? params.lng : typeof params?.locale === "string" ? params.locale : void 0;
const ret = (0, react_i18next.useTranslation)(ns, options);
(0, react.useEffect)(() => {
if (lngFromParams && ret.i18n.resolvedLanguage !== lngFromParams) ret.i18n.changeLanguage(lngFromParams);
}, [lngFromParams, ret.i18n]);
return ret;
}
/**
* Hook for changing the language without URL navigation (no-locale-path mode).
* Updates cookie + i18next instance + triggers server re-render via router.refresh().
*
* @example
* ```tsx
* 'use client'
* import { useChangeLanguage } from 'next-i18next/client'
*
* export default function LanguageSwitcher() {
* const changeLanguage = useChangeLanguage()
* return <button onClick={() => changeLanguage('de')}>Deutsch</button>
* }
* ```
*/
function useChangeLanguage(cookieName = "i18next") {
const { i18n } = (0, react_i18next.useTranslation)();
const router = (0, next_navigation.useRouter)();
return (0, react.useCallback)(async (newLng) => {
document.cookie = `${cookieName}=${newLng};path=/;max-age=${365 * 24 * 60 * 60};SameSite=Lax`;
await i18n.changeLanguage(newLng);
router.refresh();
}, [
i18n,
router,
cookieName
]);
}
//#endregion
exports.I18nProvider = I18nProvider;
Object.defineProperty(exports, "Trans", {
enumerable: true,
get: function() {
return react_i18next.Trans;
}
});
exports.useChangeLanguage = useChangeLanguage;
exports.useT = useT;
//# sourceMappingURL=client.cjs.map