ReactJS中i18n如何传入不带前后缀的第二个参数
问题场景
在ReactJS项目中接入i18n国际化能力,基础初始化代码如下:
import i18n from 'i18next'; import detector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; import translationEn from '~/lang/data/translation_en.json'; import translationKo from '~/lang/data/translation_ko.json'; const resources = { en: { translation: translationEn, }, ko: { translation: translationKo, }, }; i18n .use(detector) .use(initReactI18next) .init({ resources, fallbackLng: 'en', debug: true, keySeparator: false, interpolation: { escapeValue: false, }, react: { transEmptyNodeValue: '!null', transSupportBasicHtmlNodes: true, transKeepBasicHtmlNodesFor: ['br', 'strong', 'i'], }, }); export default i18n;
翻译资源配置如下:
{"data_to_transfer": "Saving data to transfer to {{test.data}}"}
业务代码中引入React 16.6.3版本CDN资源,定义常量const test = {data: 'PC'},调用t函数的代码如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> const test = { data: 'PC', }; <p className='para'>{t('data_to_transfer'),'test'}</p>
问题诉求
希望以{t('data_to_transfer'),'test'}的形式传入不带额外前后缀的第二个参数,但目前查阅到的所有官方文档都仅展示了{t('data_to_transfer', {test: test.data})}这类带插值标识包裹的传参方式,需要该场景的实现建议。
实现方案
- 先修正现有代码的基础问题
- 你当前写的
{t('data_to_transfer'),'test'}是JS逗号运算符语法,执行逻辑为从左到右运算所有表达式,最终返回最后一个表达式的值,等价于:
这个写法根本不会把'test'作为参数传给t函数,和传参逻辑完全无关。t('data_to_transfer') // 无参数执行,返回带未替换占位符的原始字符串 return 'test' // 最终p标签里只会渲染test文本 - 你当前初始化配置里设置了
keySeparator: false,会关闭i18next的点分隔嵌套key解析能力,翻译资源里的{{test.data}}占位符无法读取对象嵌套属性,需要把该配置改为keySeparator: '.',或直接删除该配置使用默认值。
- 你当前写的
- 简化插值传参的实现方式
i18next原生的t函数第二个参数固定为插值/配置对象,不支持直接传入裸值作为插值参数,要减少重复传参代码,有两种可落地的方案:- 方案一:封装自定义t方法,自动注入全局/固定插值变量
如果你有大量固定复用的插值变量(比如示例里的test对象),可以封装自定义hook统一注入,业务侧调用时不需要每次手动传参:
业务代码里直接调用即可,不需要额外传test参数:import { useTranslation } from 'react-i18next'; // 可以把全局固定的插值变量放在公共配置、上下文或全局状态里 const baseInterpolateParams = { test: { data: 'PC' } }; export const useAppT = () => { const { t } = useTranslation(); return (translateKey, extraParams = {}) => { return t(translateKey, { ...baseInterpolateParams, ...extraParams }); }; };const t = useAppT(); <p className='para'>{t('data_to_transfer')}</p> - 方案二:自定义i18next插值处理器(不推荐)
你可以重写i18next的插值解析逻辑,支持读取第二个位置传入的裸值作为插值参数,但这种方式会破坏i18next原生的参数规则,后续升级、多人协作时容易出现兼容问题,非特殊场景不建议使用。
- 方案一:封装自定义t方法,自动注入全局/固定插值变量
内容的提问来源于stack exchange,提问作者jjj
相关产品推荐
相关产品推荐

