next-i18next
Version:
The easiest way to translate your NextJs apps.
74 lines (73 loc) • 3.24 kB
JavaScript
import { useIsomorphicLayoutEffect } from "./utils.mjs";
import { createConfig } from "./config/createConfig.mjs";
import browser_default from "./createClient/browser.mjs";
import React, { useMemo, useRef } from "react";
import hoistNonReactStatics from "hoist-non-react-statics";
import { I18nextProvider, Trans, useTranslation, withTranslation } from "react-i18next";
//#region src/pagesRouter/appWithTranslation.tsx
let globalI18n = null;
const addResourcesToI18next = (instance, resources) => {
if (resources && instance.isInitialized) {
for (const locale of Object.keys(resources)) for (const ns of Object.keys(resources[locale])) if (!instance?.store?.data || !instance.store.data[locale] || !instance.store.data[locale][ns]) instance.addResourceBundle(locale, ns, resources[locale][ns], true, true);
}
};
const appWithTranslation = (WrappedComponent, configOverride = null) => {
const AppWithTranslation = (props) => {
const { _nextI18Next } = props.pageProps || {};
let locale = _nextI18Next?.initialLocale ?? props?.router?.locale;
const ns = _nextI18Next?.ns;
const instanceRef = useRef(null);
/**
* Memoize i18n instance and reuse it rather than creating new instance.
* When the locale or resources are changed after instance was created,
* we will update the instance by calling addResourceBundle method on it.
*/
const i18n = useMemo(() => {
if (!_nextI18Next && !configOverride) return null;
const userConfig = configOverride ?? _nextI18Next?.userConfig;
if (!userConfig) throw new Error("appWithTranslation was called without a next-i18next config");
if (!userConfig?.i18n) throw new Error("appWithTranslation was called without config.i18n");
if (!userConfig?.i18n?.defaultLocale) throw new Error("config.i18n does not include a defaultLocale property");
const { initialI18nStore } = _nextI18Next || {};
const resources = configOverride?.resources ?? initialI18nStore;
if (!locale) locale = userConfig.i18n.defaultLocale;
let instance = instanceRef.current;
if (instance) addResourcesToI18next(instance, resources);
else {
instance = browser_default({
...createConfig({
...userConfig,
lng: locale
}),
lng: locale,
...ns && { ns },
resources
}).i18n;
addResourcesToI18next(instance, resources);
globalI18n = instance;
instanceRef.current = instance;
}
return instance;
}, [
_nextI18Next,
locale,
ns
]);
/**
* Since calling changeLanguage method on existing i18n instance cause state update in react,
* we need to call the method in `useLayoutEffect` to prevent state update in render phase.
*/
useIsomorphicLayoutEffect(() => {
if (!i18n || !locale) return;
i18n.changeLanguage(locale);
}, [i18n, locale]);
return i18n !== null ? /* @__PURE__ */ React.createElement(I18nextProvider, { i18n }, /* @__PURE__ */ React.createElement(WrappedComponent, props)) : /* @__PURE__ */ React.createElement(WrappedComponent, {
key: locale,
...props
});
};
return hoistNonReactStatics(AppWithTranslation, WrappedComponent);
};
//#endregion
export { Trans, appWithTranslation, globalI18n, useTranslation, withTranslation };
//# sourceMappingURL=appWithTranslation.mjs.map