Как мне справиться с интернационализацией в библиотеке компонентов React? - PullRequest
1 голос
/ 30 апреля 2019

Я мог найти много примеров того, как сделать интернационализацию в приложении React, но я не смог найти ни одного для библиотеки компонентов.

Я использую фразуapp, и мне хотелось бы знать, есть ли у кого-нибудь предложения о том, как это сделать хорошо.

  1. Все компоненты получают в качестве реквизита язык, который следует использовать
  2. Все переводы в фразеapp
  3. Это библиотека компонентов для компании, в которой я работаю, поэтому в этой библиотеке будут метки по умолчанию, для которых требуется перевод

Варианты, которые я подумал:

  • Загрузить ключ / значения для текущего языка в клиентском хранилище apollo и создать помощника для получения значения, заданного ключом
  • Попробуйте использовать библиотеку следующим образом: https://github.com/phrase/react-intl-phraseapp, но я не знаю, будет ли она работать, потому что это не SPA

1 Ответ

1 голос
/ 21 мая 2019

, поэтому мы наконец-то использовали react-intl, экспортируя каждый компонент, заключенный в IntlProvider, с любым языковым стандартом и сообщениями, которые просто необходимы. Конфигурация для IntlProvider устанавливается в состоянии компонента внутри конструктора:

    this.state = {
       i18nCfg: IntlUtils.init(props.language, 'SignOutMenu')
    }

... и затем установить в компонентах 'render():

    render() {
      const { i18nCfg } = this.state;
      return (
         <IntlProvider locale={i18nCfg.language} messages={i18nCfg.messages}>

...

Локаль может быть предоставлена ​​родительским компонентом, как указано injectIntl HOC

<SignOutMenu language={this.props.intl.locale}/>

или обнаружен из браузера с помощью метода util getUserLanguage() on init(), если язык не определен.

Вы просто должны быть осторожны, чтобы предотвратить повторное появление идентификаторов сообщений в приложении, поэтому я инициализировал компонент строкой пространства имен, представляющей сообщения, относящиеся только к данному компоненту (сделано в getMessages()):


    import {addLocaleData} from 'react-intl';
    import en from 'react-intl/locale-data/en';
    import de from 'react-intl/locale-data/de';
    import messagesEn from '../locales/lang/i18n_en.json';
    import messagesDe from '../locales/lang/i18n_de.json';

    const defaultLanguage = 'en';
    const supportedLanguages = ['en', 'de'];

    export default class IntlUtils {

       static init = (language, namespace) => {
          // add the supported locale data
          addLocaleData([...en, ...de]);

          // get supported language
          const lang = language && supportedLanguages.indexOf(language) > -1 ? language : IntlUtils.getUserLanguage();

          // return back data for IntlProvider
          return {
             language: lang,
             messages: IntlUtils.getMessages(lang, namespace)
          }
       }

       static getMessages = (language, namespace) => {
          let langMsgs;
          switch (language) {
             case 'de': langMsgs = messagesDe; break;

             case 'en':
             default: langMsgs = messagesEn;
          }

          if (langMsgs) {
             const matchNS = namespace + ".";
             const filtered = {};
             for (var key in langMsgs) {
                if (key.startsWith(matchNS)) {
                   filtered[key] = langMsgs[key];
                }
             }
             return filtered;
          }
       }

       static getUserLanguage = () => {
          //if none available, take it from browser
          const browserLanguage = window.navigator.userLanguage || window.navigator.language;
          if (browserLanguage) {
             // get the language code and store it in local prefs for nexttime
             const m = browserLanguage.match(/^([a-z]+)/i);
             if (m) {
                return m[0];
             }
          }
          // nothing found -> return default en
          return defaultLanguage;
       }
    }

Чтобы иметь возможность импортировать файлы json в IntlUtil, мне пришлось установить devDependency "babel-plugin-inline-json-import" и добавить его в файл .babelrc:

   "plugins": [
      ["inline-json-import", {}]
   ]

Также я обнаружил, что использование injectIntl ​​HOC с методом formatMessage() не работало должным образом в том же компоненте, где IntlProvider был инициализирован, поскольку HOC использовал экземпляр IntlProvider с сообщениями из компонента выше).

Обратите внимание, что наш механизм переключения языков включал обновление страницы, поэтому с init() он работал как чудо. Но я не могу сказать, насколько хорошо это будет работать в случае использования контекста или редукса, когда вы переключаете язык без обновления страницы. Но мы собираемся использовать его в одном из таких приложений в ближайшее время, поэтому я могу выложить здесь обновления ...

Надеюсь, это поможет вам и другим, по крайней мере, как-то

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...