i18next 反应 Trans 组件 - 正确转义字符

Paw*_*żyk 4 i18next reactjs react-i18next

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

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

名为NAME的用户已创建。

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

我现在的反应代码如下:

<Trans i18n={i18next} i18nKey="userCreated" values={{name: 'Tom'}}>
   User with name <strong>{{name}}</strong> has been created.
</Trans>
Run Code Online (Sandbox Code Playgroud)

和以下翻译字符串

"userCreated": "User with name <1>{{name}}</1> has been created.",
Run Code Online (Sandbox Code Playgroud)

对于一个简单的情况,name: 'Tom'它工作正常并显示

名为Tom的用户已创建。

不过我想让用户在他们的名字中使用特殊字符。当我改名时Tom&Jerry我得到

Tom&amp;Jerry已创建具有名称的用户。

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

interpolation: {escapeValue: false},

这解决了汤姆和杰瑞的情况:

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

但有一些输入完全破坏了它,例如设置name: 'Tom<'像这样的渲染(名称后面的所有内容都是粗体):

名为Tom 的用户已创建。

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

已创建具有名称的用户。

(根本没有显示名字)。我希望它像这样渲染:

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

有办法让它发挥作用吗?

tei*_*jan 5

这个问题没有优雅的解决方案。问题的根源在于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>
);
Run Code Online (Sandbox Code Playgroud)

CodeSandbox 示例