在Next.js中无需外部库实现i18n locale全局化调用
在Next.js中全局获取翻译变量
t(无需外部库) 问题背景
我希望在应用的任意组件中获取locale作为全局变量,且不使用任何外部库。目前已完成以下配置:
- 翻译文件
es.js:
export default { home: 'Inicio', signin: 'Iniciar Sesion', welcome: 'Bienvenido', };
(en.js为对应英文翻译,结构一致)
next.config.js的i18n配置:
i18n: { locales: ['en', 'es'], defaultLocale: 'es', },
现在可以通过router.locale在组件中手动判断加载对应翻译,但每个组件都要重复这段逻辑,希望能简化成直接调用t变量的形式,比如:
import t from "../lib/i18n/t"; const HomePage = () => { return ( <div>{t.home}</div> ) }
解决方案
方案一:用React Context全局共享(推荐)
通过React Context把翻译对象全局注入,所有组件都能直接获取,适合大型应用。
1. 创建Context和Provider
新建lib/i18n/TranslationContext.js:
import { createContext, useContext, useMemo } from 'react'; import { useRouter } from 'next/router'; import en from './en'; import es from './es'; // 创建翻译上下文 const TranslationContext = createContext(); // 全局Provider组件,包裹整个应用 export const TranslationProvider = ({ children }) => { const router = useRouter(); const { locale } = router; // 根据当前语言缓存翻译对象 const t = useMemo(() => { switch(locale) { case 'en': return en; case 'es': return es; default: return es; // 兜底用默认语言 } }, [locale]); return ( <TranslationContext.Provider value={t}> {children} </TranslationContext.Provider> ); }; // 自定义Hook,简化上下文调用 export const useTranslation = () => { return useContext(TranslationContext); };
2. 在_app.js中全局注入
修改pages/_app.js,让所有页面都能访问上下文:
import { TranslationProvider } from '../lib/i18n/TranslationContext'; function MyApp({ Component, pageProps }) { return ( <TranslationProvider> <Component {...pageProps} /> </TranslationProvider> ); } export default MyApp;
3. 组件中使用
现在任何组件都能通过自定义Hook快速获取t:
import { useTranslation } from "../lib/i18n/TranslationContext"; const HomePage = () => { const t = useTranslation(); return ( <div>{t.home}</div> ); }; export default HomePage;
方案二:自定义Hook(轻量版)
如果不想用Context,直接写一个Hook封装逻辑,每次调用自动获取当前语言的翻译:
新建lib/i18n/useTranslation.js:
import { useRouter } from 'next/router'; import { useMemo } from 'react'; import en from './en'; import es from './es'; export default function useTranslation() { const router = useRouter(); const { locale } = router; // 缓存翻译对象,避免重复计算 const t = useMemo(() => { return locale === 'en' ? en : es; }, [locale]); return t; }
组件中使用:
import useTranslation from "../lib/i18n/useTranslation"; const HomePage = () => { const t = useTranslation(); return ( <div>{t.home}</div> ); }; export default HomePage;
关于直接import t的说明
如果一定要实现直接import t的形式,由于Next.js的服务端渲染特性,全局变量无法动态匹配每个请求的locale,会导致服务端和客户端渲染内容不一致(出现闪烁),因此不推荐。如果是纯客户端渲染场景,可以尝试,但存在局限性,建议优先选择上面两种方案。
内容的提问来源于stack exchange,提问作者Jesus Aguas
相关产品推荐
相关产品推荐

