简体   繁体   English

react-i18next:在文本中间插入 HTML 标签中的链接

[英]react-i18next: interpolation of link in HTML tag in the middle of the text

I am using react, i18next and react-i18next .我正在使用 react, i18nextreact-i18next I would like to have some translatable text with HTML link in the middle of the text which is interpolated in react, something like this:我想在文本中间插入一些带有 HTML 链接的可翻译文本,该文本在 react 中插入,如下所示:

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

The solution below works, but the problem is that I need to interpolate the link in react so it can't be hard-coded in label files:下面的解决方案有效,但问题是我需要在 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 />

It seems like this is much better:这似乎要好得多:

"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} />

Could be the solution, however the app is translated into many languages and a quality of translations really matters so I prefer to have the whole text in one line for translators (this is important especially for languages which have cases).可能是解决方案,但是应用程序被翻译成多种语言,翻译质量真的很重要,所以我更喜欢将整个文本放在一行中供翻译人员使用(这对于有案例的语言尤其重要)。

Is there any way how to get working something like this (or is there any way how to solve it completely differently)?有什么方法可以让这样的事情工作(或者有什么方法可以完全不同地解决它)?

"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} />

With react-i18next v4.4.0 we introduced a new component Trans : 在react-i18next v4.4.0中,我们引入了一个新组件Trans

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

The json would be: See the <1>description</1> below. json为: See the <1>description</1> below.

or even more complex: 甚至更复杂:

<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>

The new feature is documented here: https://react.i18next.com/latest/trans-component 此处记录了新功能: https : //react.i18next.com/latest/trans-component

This is the common problem of react-intl and react-i18next - both libs have very limited support of inline components and rich-text formatting inside translations (I've already described it here with more details). 这是react-intlreact-i18next的常见问题-两个库对内联组件和翻译中的RTF格式的支持都非常有限(我已经在这里进行了详细介绍)。

If you're still at the beginning of your project, you might want to consider different i18n library - js-lingui (disclaimer: I'm the author). 如果您仍处于项目的开始,则可能需要考虑使用其他i18n库-js-lingui (免责声明:我是作者)。 It's the first (and so far the only) library with full support for inline components. 它是第一个(也是迄今为止唯一的)完全支持嵌入式组件的库。

You simply write: 您只需写:

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

and your translators will work with message See the <0>description</0> below. 并且您的翻译将处理以下消息, See the <0>description</0> below.

The only price is you need to use extra babel plugin, which makes it possible. 唯一的价格是您需要使用额外的babel插件,这才有可能。

You only need to use t attribute to link the Trans tag to the language file, what you have between the tags is not important您只需要使用 t 属性将 Trans 标签链接到语言文件,标签之间的内容并不重要

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

<Interpolate i18nKey="my-label" useDangerouslySetInnerHTML link={url} /> was added a few weeks ago and does allow inserting such translations containing html fragments - just be aware this is dangerous if url comes from userinput and contains malicious code (xss attack) <Interpolate i18nKey="my-label" useDangerouslySetInnerHTML link={url} />是在几周前添加的,它确实允许插入包含html片段的翻译-请注意,如果url来自用户输入并包含恶意代码(xss攻击)

As i see this was added last year: https://github.com/i18next/react-i18next/pull/195/files 如我所见,这是去年添加的: https : //github.com/i18next/react-i18next/pull/195/files

But this will wrap per default a span around every part before/after {{link}} so that might not be what you need...but the solution is rather simple - do not use interpolate component but regular interpolation on the t function: 但这默认情况下会在{{link}}之前/之后的每个部分周围包裹一个跨度,因此这可能不是您所需要的...但是解决方案非常简单-不要在t函数上使用插值组件,而是使用常规插值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM