如何在i18n-js译文字符串中插入React Native组件或自定义样式?
问题原因
i18n-js默认返回纯字符串,所有自定义标签都会被当做普通文本做转义处理,不会被识别为React组件,因此你会得到转义后的标签文本而不是渲染后的加粗效果。
解决方案
下面提供两种可直接落地的实现方式:
方案1:占位符插值映射组件(最推荐)
该方案翻译内容和样式完全解耦,翻译人员不需要处理任何标签逻辑,维护成本最低。
- 修改翻译文件,将需要自定义样式的部分替换为插值占位符:
// en.js export default { "bold": "A word will be {{boldText}} inside this string." }
- 渲染时直接将自定义组件作为插值参数传入,外层包裹Text组件即可:
import { Text } from 'react-native'; import I18n from 'i18n-js'; // 自定义加粗组件 const B = (props) => <Text style={{fontWeight: 'bold'}}>{props.children}</Text> // 业务组件内使用 const TranslatedTip = () => { return ( <Text> {I18n.t('bold', { boldText: <B>bold</B> })} </Text> ) }
方案2:自定义标签解析组件
如果需要在翻译文本中保留标签结构方便翻译人员判断上下文,可以自己实现轻量的标签解析逻辑:
- 翻译文件保留原有标签写法:
// en.js export default { "bold": "A word will be <B>bold</B> inside this string." }
- 封装通用的翻译解析组件:
import { Text } from 'react-native'; import I18n from 'i18n-js'; const B = (props) => <Text style={{fontWeight: 'bold'}}>{props.children}</Text> // 通用翻译组件,支持自定义标签映射 const I18nText = ({ tKey, components = {} }) => { const rawText = I18n.t(tKey); const tagReg = /<(\w+)>([^<]+)<\/\1>/g; const renderParts = []; let lastCursor = 0; let matchResult; while ((matchResult = tagReg.exec(rawText)) !== null) { // 插入标签前的纯文本内容 if (matchResult.index > lastCursor) { renderParts.push(rawText.slice(lastCursor, matchResult.index)); } const tagName = matchResult[1]; const tagContent = matchResult[2]; // 匹配到注册组件就渲染组件,否则渲染原始文本 const TargetComponent = components[tagName]; renderParts.push(TargetComponent ? <TargetComponent>{tagContent}</TargetComponent> : matchResult[0]); lastCursor = tagReg.lastIndex; } // 插入剩余的末尾文本 if (lastCursor < rawText.length) { renderParts.push(rawText.slice(lastCursor)); } return <Text>{renderParts}</Text>; }; // 业务组件内使用 const App = () => { return <I18nText tKey="bold" components={{ B }} /> }
该方案可支持任意数量的自定义标签,只需要在components参数里传入标签名和对应组件的映射关系即可,可同时适配加粗、斜体、彩色文本、跳转链接等不同样式需求。
内容的提问来源于stack exchange,提问作者jorge
相关产品推荐
相关产品推荐

