Next.js中i18next构建时未注入翻译文本,运行时才解析问题
解决Next.js + next-i18next静态构建时无法替换翻译键为实际文本的问题
问题场景
我在项目中使用next-i18next实现国际化,但静态构建(SSG)阶段生成的内容里保留了翻译键,直到运行时才解析成实际文本。当前构建输出的内容类似:
<div style="display:absolute">components.atoms.characteristicsPost.averageReadingLast</div>
期望构建时直接输出翻译后的内容:
<div style="display:absolute">12 mins</div>
我的配置与代码如下:
next-18next.config.js
module.exports = { i18n: { defaultLocale: 'es', locales: ['es', 'en'], ns: ['common'] }, };
next.config.js
const { i18n } = require('./next-i18next.config'); const nextConfig = { i18n }; module.exports = nextConfig;
[..uri]页面的getStaticProps
export async function getStaticProps({ locale, params }) { const ruta = `/${params.uri?.join('/')}`; const { page, posts, configuraciones, CabeceraES, PieES, CabeceraEN, PieEN } = await getPage(ruta); const traductionProps = await serverSideTranslations(locale, ['common']); return { props: { page, posts, configuraciones, CabeceraES, PieES, CabeceraEN, PieEN, ...traduccionProps, }, revalidate: 500, notFound: !page, }; }
解决方案
核心思路
要在静态构建阶段完成翻译,需要在getStaticProps中主动加载对应语言的翻译资源,提前将数据中的翻译键替换为实际翻译文本,而不是依赖客户端的t函数在运行时解析。
具体步骤
- 加载对应语言的翻译文件
在getStaticProps中,根据当前locale加载对应的翻译资源文件(假设翻译文件存放在public/locales/{locale}/common.json):
export async function getStaticProps({ locale, params }) { const ruta = `/${params.uri?.join('/')}`; const { page, posts, configuraciones, CabeceraES, PieES, CabeceraEN, PieEN } = await getPage(ruta); // 加载当前locale的common翻译文件 const translations = require(`../public/locales/${locale}/common.json`); // ...后续处理 }
- 编写翻译替换函数
实现一个递归函数,遍历需要翻译的数据(比如page、posts),将其中的翻译键替换为实际文本:
// 递归替换对象中的翻译键 const translateKeys = (data, translations) => { if (typeof data === 'string') { // 如果是字符串,检查是否是翻译键,存在则替换 return translations[data] || data; } if (Array.isArray(data)) { return data.map(item => translateKeys(item, translations)); } if (typeof data === 'object' && data !== null) { const translatedObj = {}; for (const key in data) { translatedObj[key] = translateKeys(data[key], translations); } return translatedObj; } return data; };
- 处理数据并返回
在返回props之前,对需要翻译的数据进行替换:
export async function getStaticProps({ locale, params }) { const ruta = `/${params.uri?.join('/')}`; const { page, posts, configuraciones, CabeceraES, PieES, CabeceraEN, PieEN } = await getPage(ruta); const translations = require(`../public/locales/${locale}/common.json`); // 翻译需要静态渲染的数据 const translatedPage = translateKeys(page, translations); const translatedPosts = translateKeys(posts, translations); const translatedConfiguraciones = translateKeys(configuraciones, translations); const traductionProps = await serverSideTranslations(locale, ['common']); return { props: { page: translatedPage, posts: translatedPosts, configuraciones: translatedConfiguraciones, CabeceraES, PieES, CabeceraEN, PieEN, ...traduccionProps, }, revalidate: 500, notFound: !page, }; }
- 修改组件渲染逻辑
组件中不再使用t(key),而是直接使用props中已经翻译好的文本:
// 错误写法(运行时解析) <div style="display:absolute">{t('components.atoms.characteristicsPost.averageReadingLast')}</div> // 正确写法(构建时已翻译) <div style="display:absolute">{page.averageReadingLast}</div>
注意事项
- 确保翻译文件路径正确,根据你的项目结构调整
../public/locales/${locale}/common.json的路径。 - 如果你的翻译键包含命名空间(ns),需要对应加载对应的命名空间文件。
- 保留
serverSideTranslations,以支持客户端路由切换时的翻译需求。
内容的提问来源于stack exchange,提问作者Eduardo Gil Calvo
相关产品推荐
相关产品推荐

