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

i18next react Trans component - escaping characters correctly

我有一个基于 React 的应用程序并使用 i18next 的 Trans 组件进行翻译。

假设我们有一个用户注册表单,我们想通过显示以下文本来确认已经创建了一个新帐户:

User with name NAME has been created.

其中 NAME 由用户提供并以粗体显示。

我现在有以下反应代码:

<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' 的简单案例,它工作正常并显示

User with name Tom has been created.

但是我想让用户在他们的名字中使用特殊字符。当我将名称更改为 Tom&Jerry 时,我得到

User with name Tom&amp;Jerry has been created.

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

i18next.init 中关闭了 i18next 转义

interpolation: {escapeValue: false},

解决了猫和老鼠的问题:

User with name Tom&Jerry has been created.

但有些输入会完全破坏它,例如设置 name: 'Tom<' 呈现如下(名称后的所有内容都是粗体):

User with name Tom has been created.

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

User with name has been created.

(完全没有显示名称)。我希望它像这样呈现:

User with name <Tom> has been created.

有没有办法让它发挥作用?

这个问题没有优雅的解决方案。问题的根源在于 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.