UNPKG

next-i18next

Version:

The easiest way to translate your NextJs apps.

74 lines (73 loc) 3.24 kB
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