Next.js自动将带有语言代码的遗留URL(如以“-es”结尾的URL)重定向到核心页面,并通过i18next实现自动翻译
我们在Next.js中结合 i18next,对一个带有EN/ES双语的应用进行了重构。它可以工作,但需要支持遗留应用中启用西语的URL,例如 /page1-es、/page2-es,使其能重定向到新应用的 /page1 和 page2,并在组件内实现自动的 i18next 翻译。
由于在重定向时无法传递自定义数据(URL也不显示任何参数),我当前的代码是:在Next.js的 not-found.tsx 中指定对相应新页面的重定向,同时设置一个 sessionStorage 属性,稍后可以从拥有 i18next App基础架构的组件中取到该属性。
export default function Custom404(){ // not-found.tsx
const pathname = usePathname();
const ES_AUTO_REDIRECTS = new Map([
["/page1-es", "/page1"],
["/page2-es", "/page2"]
]);
useEffect(() => {
// sessionStorage requires an Effect as it is only available in the browser
let esRedirectURL = ES_AUTO_REDIRECTS.get(pathname);
if (esRedirectURL) {
// Manually change language to ES via sessionStorage attribute and redirect to the appropriate page
sessionStorage.setItem("init-language", "es");
redirect(esRedirectURL);
} else {
// For any general 404 Not Found errors, always redirect to home page
redirect('/');
}
}, []);
return (
<div></div>
)
常规页面接着会有自己的 TranslationProvider,并调用各自的组件,这些组件会读取此属性并在启动时设定语言,
<TranslationsProvider
namespaces={i18nNamespaces}
locale={params.locale}>
<App page="page1" />
</TranslationsProvider>
在页面所连接的组件内部(页面/组件的链接关系未展示):
export const Page1Component = () => {
const { i18n } = useTranslation(['appTranslations']);
useEffect(() => {
let initLanguage = sessionStorage.getItem("init-language");
if (initLanguage) {
i18n.changeLanguage(initLanguage);
// Remove after use
sessionStorage.removeItem("init-language");
}
}, []);
这可行,但会有闪烁,因为在重定向的Effect生效前,空白的Not Found页面会被快速显示。这个Effect会引入闪烁,但 sessionStorage 需要一个Effect(它需要浏览器环境,不能放在主代码中)。
是否有办法在不让Not Found出现闪烁的情况下完成这次重定向与翻译?404错误页不在应用的i18next基础设施内,也不属于其中。
最终结果应当是把URL改到核心URL,并在需要时完成内联翻译。
解决方案
我发现的唯一办法,是通过 next.config.ts 的 redirects 部分,将重定向到一个临时的 ?lang=.. URL,然后再重定向一次到组件中不带 ?lang=.. 参数的干净URL。与之前类似,但至少没有空白页的闪烁,只有内容的闪烍,稍微好一些。
const nextConfig: NextConfig = {
async redirects() {
return [
{
source: '/page1-es',
destination: '/page1?lang=es',
permanent: true,
},
/* etc. */
然后在组件中,
const pathname = usePathname();
useEffect(() => {
const searchParams = new URLSearchParams(window.location.search);
let langParam = searchParams.get("lang");
if (langParam) {
i18n.changeLanguage(langParam);
redirect(pathname); // Redirect to the respective clean URL without the "?lang=.." URL param after processing
}
}, []);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。