我有一个基于React的应用程序,并使用i18next的Trans组件进行翻译。
假设我们有一个用户注册表格,我们想通过显示以下文本来确认已经创建了一个新帐户:
名称为 NAME 的用户已创建。
其中 NAME 由用户提供,并以粗体显示。
我现在所拥有的是react中的以下代码:
<Trans i18n={i18next} i18nKey="userCreated" values={{name: 'Tom'}}>
User with name <strong>{{name}}</strong> has been created.
</Trans>
和以下翻译字符串
"userCreated": "User with name <1>{{name}}</1> has been created.",
对于带有name: 'Tom'
的简单情况,它可以正常工作并显示
已创建名称为 Tom 的用户。
但是,我想让用户在名称中使用特殊字符。当我将名称更改为Tom&Jerry
时,我会得到
名称为
Tom&Jerry
的用户已创建。
经过一些研究,我认为问题是i18next和react都转义了它们的输入,因此名称两次转义。我通过添加以下选项
关闭了i18next.init
中的i18next转义
interpolation: {escapeValue: false},
这可以解决Tom&Jerry案:
名称为 Tom&Jerry 的用户已创建。
,但是有一些输入将其完全破坏,例如,设置name: 'Tom<'
的呈现方式如下(名称后的所有内容均为粗体):
具有名称 Tom的用户。
设置name: '<Tom>'
会给我:
已创建名称为的用户。
(完全不显示名称)。我希望它呈现如下:
名称为
<Tom>
的用户已创建。
有没有办法使它起作用?
答案 0 :(得分:2)
没有完美的解决方案。问题的根源在Trans
组件的源代码中。您或者需要为此文件创建补丁以更改此行为,或者自己实施欺诈技巧。如果要使用秘籍解决方案,则可以创建一个组件UnescapedTrans
,该组件将使用lodash取消对HTML实体的转义:
import React, { Suspense } from "react";
import { Trans } from "react-i18next";
import { unescape } from "lodash";
const getUnescapeChildrenRef = ref =>
Array.from(ref.childNodes).forEach(node => {
if (!node.innerText) {
return node;
}
node.innerText = unescape(node.innerText);
});
const UnescapedTrans = props => (
<div ref={getUnescapeChildrenRef}>
<Trans {...props} tOptions={{ interpolation: { escapeValue: true } }} />
</div>
);