NextJS 13多语言站点:如何用Cookie记住用户上次选择的语言
- Cookie是最优解:服务端组件能直接读取,页面初始渲染就能加载用户偏好的语言,完全适配NextJS13的服务端渲染逻辑,不会出现客户端二次切换的闪烁问题。
- LocalStorage仅作兜底:只能在客户端访问,服务端渲染时拿不到值,第一次加载还是默认语言,客户端读取后再切换会有视觉跳动,适合Cookie被禁用的场景。
具体实现步骤
1. 存储用户选择的语言到Cookie
在语言切换的客户端组件里,用户点击切换按钮时,除了跳转对应URL,同时设置Cookie(有效期可设为30天):
// 客户端组件中的语言切换逻辑 const handleLanguageChange = (lang) => { // 设置全站有效Cookie,有效期30天 document.cookie = `preferred_lang=${lang}; path=/; maxAge=${30*24*60*60}; SameSite=Lax`; // 跳转到对应语言路径 window.location.href = `/${lang}`; };
2. 服务端读取Cookie,设置默认语言
在服务端组件(比如layout.js)中,通过headers()获取Cookie,解析出用户偏好语言,存在且合法就用该语言,否则用默认英语:
// app/layout.js(服务端组件) import { headers } from 'next/headers'; import getDictionary from './dictionaries'; export default async function RootLayout({ children }) { const headersList = headers(); const cookie = headersList.get('cookie'); let preferredLang = 'en'; // 默认英语 if (cookie) { // 解析Cookie提取语言值 const langMatch = cookie.match(/preferred_lang=([a-z-]+)/); // 替换成你实际支持的语言列表 if (langMatch && ['en', 'zh', 'es'].includes(langMatch[1])) { preferredLang = langMatch[1]; } } const dict = await getDictionary(preferredLang); return ( <html lang={preferredLang}> <body> {/* 将字典传递给子组件或通过Context分发 */} {children} </body> </html> ); }
3. 根路径重定向(可选)
如果用户访问根路径example.com/,可以在服务端组件中读取Cookie,直接重定向到用户偏好的语言页面:
// app/page.js(服务端组件) import { redirect } from 'next/navigation'; import { headers } from 'next/headers'; export default async function HomePage() { const headersList = headers(); const cookie = headersList.get('cookie'); let preferredLang = 'en'; if (cookie) { const langMatch = cookie.match(/preferred_lang=([a-z-]+)/); if (langMatch && ['en', 'zh', 'es'].includes(langMatch[1])) { preferredLang = langMatch[1]; } } redirect(`/${preferredLang}`); }
4. LocalStorage兜底逻辑(可选)
担心Cookie被禁用的话,在客户端组件中添加LocalStorage的读取和存储逻辑:
// 客户端组件 import { useEffect } from 'react'; import { usePathname } from 'next/navigation'; export default function LanguageSwitcher() { const pathname = usePathname(); const currentLang = pathname.split('/')[1] || 'en'; useEffect(() => { // 页面加载时读取LocalStorage,若Cookie未生效则切换 const savedLang = localStorage.getItem('preferred_lang'); if (savedLang && savedLang !== currentLang && ['en', 'zh', 'es'].includes(savedLang)) { document.cookie = `preferred_lang=${savedLang}; path=/; maxAge=${30*24*60*60}; SameSite=Lax`; window.location.href = `/${savedLang}`; } }, []); const handleChange = (lang) => { // 切换时同时存到LocalStorage和Cookie localStorage.setItem('preferred_lang', lang); document.cookie = `preferred_lang=${lang}; path=/; maxAge=${30*24*60*60}; SameSite=Lax`; window.location.href = `/${lang}`; }; return ( <div> <button onClick={() => handleChange('en')}>English</button> <button onClick={() => handleChange('zh')}>中文</button> </div> ); }
注意事项
- 维护一个合法语言列表,避免非法语言值导致逻辑错误。
- Cookie的
SameSite属性设为Lax或Strict,符合浏览器安全规范。
内容的提问来源于stack exchange,提问作者IdoBa
相关产品推荐
相关产品推荐

