i18следующий компонент Trans реагирует - экранирование символов корректно - PullRequest
0 голосов
/ 07 октября 2019

У меня есть приложение, основанное на реагировании, и я использую компонент Trans i18next для переводов.

Допустим, у нас есть форма регистрации пользователя, и мы хотим подтвердить, что была создана новая учетная запись, отображая следующий текст:

Пользователь с именем ИМЯ был создан.

где 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' он работает нормально и отображает

Пользователь с именем Том создан.

Однако я бы хотел, чтобы пользователи использовали специальные символы в своих именах. Когда я меняю имя на Tom&Jerry, я получаю

Пользователь с именем Tom&amp;Jerry был создан.

После некоторых исследованийЯ думал, что проблема в том, что и i18next, и response избегают ввода, и поэтому имя экранируется дважды. Я отключил экранирование i18next в i18next.init, добавив следующую опцию

interpolation: {escapeValue: false},

, исправляющую случай Тома и Джерри:

Пользователь с именем Tom & Jerry был создан.

, но есть некоторые входы, которые полностью его нарушают, например, установка name: 'Tom<' рендерится так (все, что после имени выделено жирным шрифтом):

Пользователь с именем Том был создан.

и настройка name: '<Tom>' дает мне:

Пользователь с именем был создан.

(имя не отображается вообще). Я хотел бы, чтобы это выглядело так:

Пользователь с именем <Tom> создан.

Есть ли способ сделать этоработай?

1 Ответ

2 голосов
/ 11 октября 2019

Нет элегантного решения этой проблемы. Корень проблемы находится в исходном коде компонента Trans. Вам нужно либо создать патч для этого файла, изменяя это поведение, либо реализовать хитрый трюк самостоятельно. Если вы собираетесь использовать обманчивое решение, вы должны создать компонент UnescapedTrans, который будет скрывать HTML-сущности с использованием lodash:

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 .

...