i18next react Trans组件-正确转义字符

时间:2019-10-07 12:19:52

标签: reactjs i18next react-i18next

我有一个基于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&amp;Jerry 的用户已创建。

经过一些研究,我认为问题是i18next和react都转义了它们的输入,因此名称两次转义。我通过添加以下选项

关闭了i18next.init中的i18next转义

interpolation: {escapeValue: false},

这可以解决Tom&Jerry案:

  

名称为 Tom&Jerry 的用户已创建。

,但是有一些输入将其完全破坏,例如,设置name: 'Tom<'的呈现方式如下(名称后的所有内容均为粗体):

  

具有名称 Tom的用户。

设置name: '<Tom>'会给我:

  

已创建名称为的用户。

(完全不显示名称)。我希望它呈现如下:

  

名称为 <Tom> 的用户已创建。

有没有办法使它起作用?

1 个答案:

答案 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>
);

CodeSandbox example