react-i18next:在文本中间的HTML标记链接内插

37

我正在使用react,i18nextreact-i18next。我想要在文本中间插入带有HTML链接的可翻译文本,这些文本将在react中进行插值,就像这样:

This is my text with <a href="{{link}}">a beautiful link</a> in the middle of the text

下面的解决方案可行,但问题是我需要在react中插值链接,因此不能在标签文件中硬编码:
"my-label": "This is my text with <a href=\"http://google.com\">a beautiful link</a> in the middle of the text"

[...]

<Interpolate i18nKey="my-label" useDangerouslySetInnerHTML />

看起来这样会更好:

"my-label": "This is my text with {{link}} in the middle of the text",
"link" "a beautiful link"

[...]

const { url } = props;
const link = <a href={url}>{t('link')}</a>

<Interpolate i18nKey="my-label" link={link} />

这可能是一个解决方案,但应用程序已被翻译成许多语言,翻译的质量非常重要,因此我更喜欢将整个文本放在一行中以便于翻译(特别是对于具有格的语言而言)。

是否有任何方法可以使类似这样的内容正常工作(或者是否有完全不同的解决方法)?

"my-label": "This is my text with <a href=\"{{link}}\">a beautiful link</a> in the middle of the text"

[...]

const { url } = props;

<Interpolate i18nKey="my-label" useDangerouslySetInnerHTML link={url} />
5个回答

35

在react-i18next v4.4.0中,我们引入了一个新的组件Trans

<Trans i18nKey="optionalKey">See the <Link to="/more">description</Link> below.</Trans>

JSON格式如下:请查看下面的<1>描述</1>

甚至更复杂的情况:

<Trans i18nKey="userMessagesUnread" count={count}>
Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
</Trans>

新功能的文档在这里:https://react.i18next.com/latest/trans-component

如果您遇到了missingKey错误的问题,那很可能是命名空间的问题。详细信息请参见https://github.com/i18next/react-i18next/issues/867 - Shawn
答案应该更新,以显示将 t 函数作为 prop 传递给 Trans 组件。即 <Trans t={t} i18nKey="optionalKey">。 - Shawn
在 Trans 组件的子组件中,你能否使用条件逻辑? - Paul Razvan Berg
15
谢谢您的回答。我可能有所误解,这是否意味着Trans内部的文本需要与JSON保持同步?如果是,这似乎并不十分方便,因为它不再作为不可变键。 - Danyal Aytekin
看起来这些文本不需要同步。我能够使用X<a href>Y</a>Z(真的是XYZ!)作为Trans的子元素,并且它可以工作!在JSON中,我有实际的字符串(例如This is a text with <1>a link</1> inside)。 - v.nivuahc

7

这是react-intlreact-i18next的共同问题——两个库对翻译中内联组件和富文本格式的支持都非常有限(我已经在这里进行了更详细的描述)。

如果你的项目还处于起步阶段,你可能想考虑使用不同的i18n库——js-lingui(声明:我是作者)。它是第一个(也是迄今为止唯一一个)完全支持内联组件的库。

你只需编写:

<Trans>See the <Link to="/more">description</Link> below.</Trans>

您的翻译人员将使用消息 请参见下面的<0>描述</0> 进行工作。

唯一的代价是您需要使用额外的Babel插件,这样才有可能实现。


3

既然这里没有人讨论如何在仅使用JSON的情况下插入带链接的文本,那我就告诉你怎么做。

JSON:

json_key: "文本 <0>链接</0> 文本"

React:

<Trans
    i18nKey="json_key"
    components={[<Link to="/" />]}
/>

从11.6.0版本开始,您还可以为组件命名:"json_key": "text link text" }} />请注意,您为组件选择的名称不能是已存在的自闭合HTML标签名称(例如link,img,br等)。了解更多信息:https://react.i18next.com/latest/trans-component#alternative-usage-which-lists-the-components-v11.6.0 - undefined

0

您只需要使用t属性将Trans标签链接到语言文件即可。标签之间的内容并不重要。

<Trans i18nKey="cookieConsent.content" t={t}>
    x<Link to="/#privacy-policy">y</Link>z<Link to="/#legal">w</Link>
</Trans>

不错!这是一些新功能吗?它是在哪个版本中添加的? - Knut Holm
@KnutHolm 我不知道,我是刚接触react-i18next。我的版本是11.8.15。 - sepehrgd
7
网络上提供的每个示例都展示了如何编写“Trans”组件的React代码,但没有人会提供翻译文件的样式。这可能是我职业生涯中最令人困惑的API。 - The Muffin Man

-3

<Interpolate i18nKey="my-label" useDangerouslySetInnerHTML link={url} /> 几周前添加了这个功能,可以插入包含HTML片段的翻译 - 但要注意,如果URL来自用户输入并包含恶意代码(XSS攻击),则这很危险

据我所见,这是去年添加的:https://github.com/i18next/react-i18next/pull/195/files

但是,默认情况下,它会在{{link}}之前/之后包装每个部分的span,因此这可能不是您需要的...但解决方案相当简单-不使用interpolate组件,而是在t函数上使用常规插值:

<div dangerouslySetInnerHTML={t('my-label', { link: yourURL }} />


显然,这仅支持将那些部分包装在额外的组件(默认跨度)中。 - jamuhl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接