Next.js 14 App Router:服务端与客户端翻译需分方式处理吗?
Next.js App Router 中服务端/客户端组件的国际化处理
核心结论
是的,必须区分服务端组件(Server Components)和客户端组件(Client Components)的翻译处理方式,但这并非是库的设计缺陷,而是由Next.js App Router的架构特性决定的——服务端组件与客户端组件的运行环境、API访问权限存在本质差异。不过你可以通过封装统一的工具函数,避免切换组件类型时重写大量翻译代码。
为什么需要区分?
- 服务端组件的限制:服务端组件运行在Node.js环境,无法访问浏览器API,也不能使用依赖客户端状态的React Hook(比如react-i18next的
useTranslation)。因此只能直接调用国际化库的服务端实例来获取翻译文本,比如直接调用i18n实例的t方法。 - 客户端组件的需求:客户端组件需要响应用户的语言切换交互,必须使用能订阅语言状态变化的Hook(如
useTranslation),这样语言切换时组件能自动更新。
简化实现的方案
你可以封装一套统一的翻译工具,让服务端和客户端组件使用相同的调用方式,只在底层做环境适配:
1. 统一翻译工具封装
// lib/translate.js 'use client'; import { useTranslation } from 'react-i18next'; import i18n from './i18n-config'; // 服务端环境直接返回i18n实例的t方法 export const getTranslator = () => { if (typeof window === 'undefined') { return i18n.t; } // 客户端环境返回useTranslation的t方法 const { t } = useTranslation(); return t; }; // 针对客户端组件的Hook封装 export const useTranslator = () => { const { t } = useTranslation(); return t; };
2. 服务端组件使用示例
// app/page.js(默认服务端组件) import { getTranslator } from '@/lib/translate'; export default async function Home() { const t = getTranslator(); return ( <main> <h1>{t('home.title')}</h1> <p>{t('home.description')}</p> </main> ); }
3. 客户端组件使用示例
// app/components/ClientSwitcher.js(客户端组件) 'use client'; import { useTranslator } from '@/lib/translate'; import { useRouter } from 'next/navigation'; export default function LanguageSwitcher() { const t = useTranslator(); const router = useRouter(); const switchLanguage = (lang) => { router.push(`/${lang}`); }; return ( <div> <button onClick={() => switchLanguage('en')}>{t('lang.en')}</button> <button onClick={() => switchLanguage('zh-CN')}>{t('lang.zh')}</button> </div> ); }
补充说明
这种区分不仅适用于react-i18next,像next-intl等主流国际化库也遵循相同逻辑——本质是适配Next.js App Router的服务端/客户端隔离机制。只要做好底层封装,就能避免重复代码,让组件切换类型时的改动降到最小。
内容的提问来源于stack exchange,提问作者Rowin_nb2
相关产品推荐
相关产品推荐

