在Remix中使用Clerk实现本地化:App函数内如何配置localization?
在Remix的root.tsx中根据内部locale动态配置ClerkApp的localization参数
以下是当前的示例代码:
import { ClerkApp } from "@clerk/remix"; import { useLoaderData } from "@remix-run/react"; import { enUS, jaJP } from "@clerk/localizations"; interface LoaderData { locale: string; } function App() { const { locale } = useLoaderData<LoaderData>(); // 该值可由客户端修改 return ( <html lang={locale}> <head> <Meta /> <Links /> </head> <body> <Outlet /> <ScrollRestoration /> <Scripts /> <LiveReload /> </body> </html> ); } const enLocalization = { ...enUS, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; const jaLocalization = { ...jaJP, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; // 如何根据用户浏览器语言设置本地化? export default ClerkApp(App, { localization: enLocalization });
官方文档中ClerkApp的配置是在App函数外部完成的,但如果locale的校验逻辑位于App函数内部,该如何为ClerkApp设置localization参数?
解决方案
核心思路是将locale的确定逻辑移至root的loader中,并利用ClerkApp支持动态配置函数的特性,根据loader返回的locale数据自动切换本地化配置。
方法1:基于服务端loader动态配置(推荐)
这种方式能保证服务端渲染和客户端渲染的locale一致,适合从请求头、路由参数或用户会话中获取locale的场景:
import { ClerkApp } from "@clerk/remix"; import { useLoaderData } from "@remix-run/react"; import { enUS, jaJP } from "@clerk/localizations"; import type { LoaderFunctionArgs } from "@remix-run/node"; interface LoaderData { locale: string; } // 在loader中确定locale,支持从请求头、路由参数等来源获取 export async function loader({ request }: LoaderFunctionArgs) { // 示例:从请求头提取浏览器主语言 const acceptLanguage = request.headers.get("Accept-Language"); const rawLocale = acceptLanguage?.split(",")[0].split("-")[0] || "en"; // 校验locale是否在支持列表中 const supportedLocales = ["en", "ja"]; return { locale: supportedLocales.includes(rawLocale) ? rawLocale : "en" }; } function App() { const { locale } = useLoaderData<LoaderData>(); return ( <html lang={locale}> <head> <Meta /> <Links /> </head> <body> <Outlet /> <ScrollRestoration /> <Scripts /> <LiveReload /> </body> </html> ); } const enLocalization = { ...enUS, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; const jaLocalization = { ...jaJP, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; // 使用函数形式的配置,根据loader数据动态选择本地化 export default ClerkApp(App, (data: LoaderData) => ({ localization: data.locale === "ja" ? jaLocalization : enLocalization, }));
方法2:客户端动态更新(适合用户手动切换场景)
如果locale需要在客户端通过交互切换(比如用户点击语言按钮),可以结合useClerk钩子动态更新本地化配置:
import { ClerkApp, useClerk } from "@clerk/remix"; import { useLoaderData, useEffect } from "@remix-run/react"; import { enUS, jaJP } from "@clerk/localizations"; interface LoaderData { locale: string; } function App() { const { locale } = useLoaderData<LoaderData>(); const clerk = useClerk(); // 当locale变化时,更新Clerk的本地化配置 useEffect(() => { const targetLocalization = locale === "ja" ? jaLocalization : enLocalization; clerk.setLocalization(targetLocalization); }, [locale, clerk]); return ( <html lang={locale}> <head> <Meta /> <Links /> </head> <body> <Outlet /> <ScrollRestoration /> <Scripts /> <LiveReload /> </body> </html> ); } const enLocalization = { ...enUS, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; const jaLocalization = { ...jaJP, ...{ signUp: { start: { subtitle: "{{applicationName}}" } }, }, }; // 先设置默认本地化配置 export default ClerkApp(App, { localization: enLocalization });
内容的提问来源于stack exchange,提问作者Alpin Cleopatra
相关产品推荐
相关产品推荐

