react-i18next中如何使用<Trans>组件结合接收children的自定义TextHighlight组件处理翻译内联高亮
react-i18next中如何使用组件结合接收children的自定义TextHighlight组件处理翻译内联高亮
我之前正好碰到过几乎一模一样的需求,别担心,用<Trans>组件完全能搞定,只是之前的写法有几个小细节没踩对~
首先直接上能跑通的正确写法,再给你拆解为什么之前的尝试没成功:
正确写法1:直接传递TextHighlight组件
import Trans from 'react-i18next/Trans'; import TextHighlight from './TextHighlight'; // 注意i18nKey要和你翻译文件里的key对应!你翻译里是text1,之前试的时候写成introText会找不到文本哦 <Trans i18nKey="text1" components={{ highlight: TextHighlight }} />
正确写法2:用箭头函数显式接收children(TS友好版)
如果TypeScript报类型提示错误,你可以用箭头函数显式把children传给TextHighlight,这样类型会更清晰:
<Trans i18nKey="text1" components={{ highlight: (children: React.ReactNode) => <TextHighlight>{children}</TextHighlight> }} />
为什么之前的写法没生效?
你之前试的几种写法里,问题主要出在这两点:
- 传了已渲染的元素而非组件本身:比如
<Trans components={{ highlight: <TextHighlight /> }} />,这种写法是把TextHighlight已经渲染好的元素传进去,它没法再接收<highlight>标签里的文本作为children,自然就不会显示高亮内容了。 - i18nKey不匹配:你翻译文件里的key是
text1,但尝试代码里写的是introText,这会导致Trans找不到对应的翻译文本,自然也没法渲染。
关于TypeScript类型的小提示
如果你的项目用TypeScript,可能会遇到components的类型不匹配警告,这时候可以给Trans组件加上类型注解,或者确保TextHighlight的Props类型是正确的:
你的TextHighlight组件的Props已经是对的:
type Props = { children: React.ReactNode }; export default function TextHighlight({ children }: Props) { return <span className="text-[var(--primary)] font-bold">{children}</span>; }
它完全符合react-i18next对替换组件的要求——只要组件能接收children作为参数,Trans就会自动把<highlight>标签内的内容传给它。
如果Trans组件实在有问题,还有什么替代方案?
如果因为某些原因Trans组件没法满足需求,你可以用useTranslation钩子结合dangerouslySetInnerHTML,但非常不推荐这种方式,因为它有XSS攻击的风险,只适合完全信任翻译内容的场景:
import { useTranslation } from 'react-i18next'; const { t } = useTranslation(); const htmlContent = t('text1', { interpolation: { escapeValue: false } }).replace(/<highlight>/g, '<span class="text-[var(--primary)] font-bold">').replace(/<\/highlight>/g, '</span>'); return <div dangerouslySetInnerHTML={{ __html: htmlContent }} />;
但还是优先用Trans组件的方案,既安全又符合React的组件化思想。
内容来源于stack exchange
相关产品推荐
相关产品推荐

