Использование реакции i18next на все вложенные компоненты

У меня вопрос относительно многоязычной поддержки сложного приложения React. Все примеры и документация основаны на плоском приложении без вложенных/дочерних компонентов.

Как обращаться с данными, вложенными следующим образом:

<i18n>
    <App>
        translate('base')(
          <Base>
              <Child1 />
              <Child2 />
              {t('Hello')}
          </Base>
        )
    </App>
</i18n>

Должен ли я обернуть каждый дочерний компонент translate HOC?
Есть ли другой способ передать функцию translation дочерним компонентам?


person J33nn    schedule 01.08.2018    source источник


Ответы (4)


У меня была такая же проблема не так давно. Для этого я нашел 4 решения.

  1. Передача t каждому компоненту. Это очень раздражает и приводит к множеству ошибок, потому что я все время забывал передать его.

  2. Используя контекст NamespacesConsumer, предоставленный react-i18next. Это также очень раздражает, а синтаксис иногда слишком странный и повторяющийся. Это также может отрицательно сказаться на производительности, поскольку компоненты могут часто повторно рендериться.

  3. Используя withNamespaces HOC, предоставленный react-i18next, это отличный вариант, он легко читается и не загрязняет ваш код синтаксисом перевода. Это также более эффективно, чем два предыдущих варианта.

  4. Это мое любимое решение, я в конечном итоге использую i18next напрямую, потому что у вас есть доступ к t() везде из коробки, без дополнительного кода.

Если вы хотите сохранить react-i18next, я бы порекомендовал вам использовать HOC, его намного проще отлаживать, тестировать и разрабатывать. Но, честно говоря, на мой взгляд, i18next работает лучше. Первоначально я использовал react-i18next, потому что я думал, что это способ реагирования, но использовать его просто больно, в react-i18next много ошибок, и для написания гораздо больше кода. Использование i18next очень просто

import i18next from 'i18next';

i18next.t('parentKey.childKey');
person Vincent D'amour    schedule 18.01.2019
comment
Я думаю, что одна проблема с использованием i18next напрямую заключается в том, что ваши компоненты не будут перерисовываться при изменении языка. - person Hendy Irawan; 18.01.2019
comment
Это правда, но обычно я перезагружаю страницу с новым языком. Это не так уж плохо, и приложение без react-i18next намного быстрее, его легко тестировать, легко отлаживать, а код чище. Большинство людей меняют язык только один раз, поэтому использование сложной библиотеки только для поддержки этой функции, на мой взгляд, немного излишне. Попробуйте, это лучший совет, который я могу вам дать. - person Vincent D'amour; 19.01.2019
comment
имеет смысл. Я предлагаю вам упомянуть withNamespaces HOC, предоставленный react-i18next, вместо HOC. - person Hendy Irawan; 19.01.2019
comment
Меня тоже это поразило: в form-redux validate() мне нужно показать локализованные ошибки. Проблема в том, что validate() не имеет доступа к Component.props (CMIIW). Так что мне все равно пришлось import i18n from "i18next" и пользователю i18n.t() прямо внутри validate(). ;-) - person Hendy Irawan; 19.01.2019

Вы также можете передать его через обычные реквизиты из внешнего компонента.

Например, если у вас есть контейнерные компоненты, которые обертываются с помощью translate hoc, а внутренние компоненты вы просто передаете функции t через реквизиты.

person jamuhl    schedule 02.08.2018
comment
Ну, я знаю об этом :) Вопрос в том, как лучше всего это сделать ;) - person J33nn; 03.08.2018
comment
Это худшее, что можно сделать; вручную передача реквизита на бесконечные уровни. Я бы не рекомендовал это для чего-либо более чем на 2 уровня, и ни одно приложение не находится всего на 2 уровня ниже. особенно с переводом - person vsync; 20.08.2019

Лучшим подходом было бы обернуть ваш основной компонент React.Context и передать реквизит t в качестве контекста и сделать его доступным в каждом из ваших вложенных дочерних компонентов.

Я также использую локализацию в своем приложении.

Плюсы:

  • Не разрушает дочернюю иерархию, когда каждый компонент обернут hOC
  • В будущем, если вы решите выбрать другую библиотеку для локализации, вы можете просто изменить основной компонент Provider этого контекста, и он обновит реализацию во всем вашем приложении.
  • Поскольку переводы загружаются изначально, ваш контекст не будет обновляться, и проблема с повторным рендерингом не будет возникать снова и снова.
person Adeel Imran    schedule 23.01.2019
comment
Даже если значение t не изменится, контекст повторно отобразит компоненты внутри. Это действительно раздражает от реакции. Вам нужно указать shouldComponentUpdate или использовать PureComponent, но иногда вы визуализируете только функциональный компонент без состояния или компонент из библиотеки, которую вы можете изменить. Меня раздражает повторный рендеринг многих компонентов только для перевода строк. Но это прекрасное решение для большинства проектов, важно отметить, что проблемы с производительностью или ошибки рендеринга могут быть вызваны контекстом. - person Vincent D'amour; 23.01.2019
comment
Неправильно, сэр, Context не будет постоянно обновлять ваше дерево, если не будет изменено иное. react-router и redux с самого начала использовали контекст в своей библиотеке. - person Adeel Imran; 24.01.2019
comment
Да, правда, но я говорил о том, как с этим справляется react-i18next. почему-вы-обновление срабатывало все время, когда я использовал react-i18next, потому что контекст, который вы получаете из библиотеки, использует несвязанные функции. Чтобы избежать этого, вам нужно создать свой собственный контекст, который раздражает. - person Vincent D'amour; 24.01.2019
comment
Он будет обновляться только тогда, когда мы используем метод react-i18next changeLanguage и меняем всю локализацию в приложении. Я думаю, что это правильное поведение, потому что мы хотим, чтобы все наши дочерние элементы отображались с использованием локализаций (которые, как я думаю, являются почти всеми компонентами). Остальные могут быть memo или Pure.Component - person Adeel Imran; 25.01.2019
comment
Я не уверен, что мы здесь друг друга понимаем. Но это в основном то, что я говорю. Способ, которым react-i18next обрабатывает реквизиты контекста, глючит. Это приводит к повторному рендерингу, даже если язык не изменился. Как вы сказали, чтобы избежать повторного рендеринга, вам нужно использовать функцию memoize или преобразовать компоненты в PureComponent, что раздражает, когда у вас есть SFC. Для меня необходимость конвертировать компонент без состояния в чистый компонент только для того, чтобы избежать повторного рендеринга, является большой проблемой. - person Vincent D'amour; 25.01.2019

Если вы используете хуки, а не классы (как я) при кодировании компонентов React , то вы можете использовать хук useTranslation:

import React from 'react';
import { useTranslation } from 'react-i18next';

export function MyComponent() {
  const { t, i18n } = useTranslation();
  // or const [t, i18n] = useTranslation();

  return <p>{t('my translated text')}</p>
}

Это, как и оболочка withTranslation, требует импорта (хука) в каждый файл, который использует переводы.

person vsync    schedule 20.08.2019