ahhtree
2023-11-15 09:17:28 +08:00
layout:
<code>
export async function generateStaticParams() {
return Languages.map((lang) => ({ lang }));
}
export default async function RootLayout({
children,
params: { lang },
}: {
children: React.ReactNode;
params: { lang: LanguageType };
}) {
return (
<html lang={lang.includes("zh") ? "zh-CN" : "en-US"}>
<body className={inter.className}>
<main className="relative w-full h-screen flex flex-col">
<Header lang={lang} />
{/* <ContentWrapper childNodes={children} lang={lang} /> */}
<div className="relative grow w-full flex flex-col items-center justify-center">
{children}
</div>
<Toaster />
<Footer lang={lang} />
</main>
<InitRDKit />
</body>
</html>
);
}
</code>
settings:
<code>
export type LanguageType = "en" | "zh";
export const FallbackLng: LanguageType = "en";
export const Languages: LanguageType[] = [FallbackLng, "zh"];
export const CookieLocaleName = "i18next";
export const defaultNS = "home";
export function getOptions(lng: LanguageType = FallbackLng, ns = defaultNS) {
return {
debug: process.env.NODE_ENV === "development",
supportedLngs: Languages,
fallbackLng: FallbackLng,
lng,
fallbackNS: defaultNS,
defaultNS,
ns,
};
}
</code>
i18n 服务端配置:
<code>
const initI18next = async (lng: LanguageType, ns: string) => {
const i18nInstance = createInstance({});
await i18nInstance
.use(initReactI18next)
.use(
resourcesToBackend(
(language: string, namespace: string) =>
import(`./locales/${language}/${namespace}.json`)
)
)
.init({
...getOptions(lng, ns),
detection: {
order: ["path", "htmlTag", "navigator"],
// lookupCookies: "",
cookieOptions: {
sameSite: "lax",
path: `/${lng}`,
},
lookupCookie: CookieLocaleName,
caches: ["localStorage"],
excludeCacheFor: ["cookie"],
},
});
return i18nInstance;
};
export async function serverTranslation(
lng: LanguageType,
ns: string,
options = {}
) {
const i18nextInstance = await initI18next(lng, ns);
return {
t: i18nextInstance.getFixedT(lng, Array.isArray(ns) ? ns[0] : ns),
i18n: i18nextInstance,
};
}
</code>
i18n 客户端 配置:
<code>
const runsOnServerSide = typeof window === "undefined";
const languageDetector = new LanguageDetector();
languageDetector.init({ useCookies: false });
//
i18next
.use(initReactI18next)
.use(languageDetector)
.use(
resourcesToBackend(
(language: string, namespace: string) =>
import(`./locales/${language}/${namespace}.json`)
)
)
.init({
...getOptions(),
lng: undefined, // let detect the language on client side
preload: runsOnServerSide ? Languages : [],
detection: {
order: ["path", "htmlTag", "navigator"],
// lookupCookies: "",
cookieOptions: {
sameSite: "lax",
},
caches: ['localStorage'],
},
});
export function useTranslation(
lng: string,
ns: string,
options?: UseTranslationOptions<any>
) {
const [done, setDone] = useState(false);
const [cookies, setCookie] = useCookies([CookieLocaleName]);
const ret = useTranslationOrg(ns, options);
const { i18n } = ret;
if (runsOnServerSide && lng && i18n.resolvedLanguage !== lng) {
i18n.changeLanguage(lng);
} else {
// debugger
// eslint-disable-next-line react-hooks/rules-of-hooks
const [activeLng, setActiveLng] = useState(i18n.resolvedLanguage);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (activeLng !== lng) {
setActiveLng(lng);
i18n.changeLanguage(lng);
}
}, [activeLng, lng, i18n]);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (cookies[CookieLocaleName] === lng) return;
setCookie(CookieLocaleName, lng, { sameSite: "lax", path: `/${lng}` });
}, [lng, cookies, setCookie]);
useEffect(() => {
setDone(true);
}, []);
}
return ret;
}
</code>