React Native中如何通过i18n-js将组件作为参数插值渲染
问题原因
i18n-js 原生的i18n.t()方法默认仅返回字符串结果,当你传入 React 组件作为插值变量时,方法内部会自动将组件对象转为字符串,最终就会输出[object Object],该库原生不支持直接插值渲染 React 组件。
可行解决方案
你可以改造自定义的translate hook,让它支持解析组件类型的插值变量,实现思路是先将组件插值替换为唯一标记,待i18n返回翻译结果后,再将标记位替换回对应组件,最终返回React可直接渲染的数组结构,参考实现代码如下:
// 改造后的自定义翻译hook import { useCallback } from 'react'; import i18n from 'i18n-js'; export const useTranslate = () => { const translate = useCallback((key, config = {}) => { // 筛选出所有组件类型的插值变量 const componentInterpolation = Object.entries(config).filter( ([_, value]) => typeof value === 'object' && value.$$typeof != null ); // 生成唯一标记映射,避免和正常文本冲突 const markToComponent = {}; const stringOnlyConfig = {...config}; componentInterpolation.forEach(([key, component]) => { const uniqueMark = `__COMPONENT_${key}__`; markToComponent[uniqueMark] = component; stringOnlyConfig[key] = uniqueMark; }); // 获取i18n返回的纯字符串翻译结果 const translatedText = i18n.t(key, stringOnlyConfig); // 按标记拆分文本,转换为可直接渲染的混合数组 const splitReg = new RegExp(`(${Object.keys(markToComponent).join('|')})`, 'g'); const renderParts = translatedText.split(splitReg).filter(Boolean); return renderParts.map((part, index) => markToComponent[part] ? markToComponent[part] : part ); }, []); return translate; };
使用方式和你原有代码完全一致,不需要做额外修改:
const translate = useTranslate(); // 业务代码保持不变 <Text> {translate( 'tnc_text', { topUpTnC: <Text style={{color: 'blue'}} onPress={() => Linking.openURL('https://google.com')}> Top-Up Terms and Conditions* </Text>, dealsTnC: <Text style={{color: 'blue'}} onPress={() => Linking.openURL('https://example.com')}> Deals Terms and Conditions </Text>, })} </Text>
注意事项
如果你的插值变量中同时包含普通字符串和组件,上述实现也可以正常兼容,不需要额外处理。
内容的提问来源于stack exchange,提问作者Abhishek Sharma
相关产品推荐
相关产品推荐

