webentwicklung-frage-antwort-db.com.de

React-Intl, wie Sie das Gebietsschema und die Nachrichten von Variablen wechseln

Ich versuche herauszufinden, wie man mit React-Intl die Sprache ändert. Dies ist meine erste React App und wurde mit Create-React-App erstellt. Ich verwende weder Redux noch Flux.

In meiner index.js habe ich den folgenden Code:

import React from 'react';
import ReactDOM from 'react-dom';
import TodoApp from './components/TodoApp';
import registerServiceWorker from './registerServiceWorker';
import './index.css';

// Bootstrap CSS libraries
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';

import { IntlProvider, addLocaleData } from 'react-intl';
import intlEN from 'react-intl/locale-data/en';
import intlES from 'react-intl/locale-data/es';
import intlMessagesES from './i18n/locales/es.json';
import intlMessagesEN from './i18n/locales/en.json';

addLocaleData([...intlEN, ...intlES]);

/* Define your translations */
let i18nConfig = {
    locale: 'es',
    messages: intlMessagesES
};

let changeLanguage = (lang) => {
    i18nConfig = { locale: lang, messages: intlMessagesEN };
    return i18nConfig;
}

ReactDOM.render(
    <IntlProvider locale={ i18nConfig.locale } key={ i18nConfig.locale } messages={ i18nConfig.messages }>
        <TodoApp onChangeLanguage={changeLanguage} />
    </IntlProvider>,
    document.getElementById('root'));
registerServiceWorker();

TodoApp sendet einen String auf 'lang' -Parameter per Requisiten (d. H .: 'es' oder 'en'), wenn ich i18nConfig ändere, ändert sich nichts mit IntlProvider. Mein Gedanke war, meine i18nConfig Variable zu ändern, dann würde auch meine gesamte App die Sprache ändern.

Ich habe FormattedMessages in TodoApp und meine zwei JSON-Nachrichten werden folgendermaßen gefüllt: 

// i18n/locales/en.json
{
  "footer.add.placeholder": "Enter a name ...",
  "footer.add.priority0.text": "No priority",
  "footer.add.priority1.text": "Priority 1",
   ...
}

Wissen Sie, was ich auf meinem Code vermisse? Vielleicht habe ich etwas nicht richtig verstanden über React-Intl. Jeder Rat wird hilfreich sein, danke.

Es funktioniert, wenn Sie alle aus root entfernen:

ReactDOM.render(<TodoApp />, document.getElementById('root'));

Jetzt ändern wir die TodoApp-Komponente folgendermaßen:

1) Wir fügen 'locale' als Komponentenstatus hinzu und importieren React-Intl:

import { IntlProvider, addLocaleData } from 'react-intl';
import intlEN from 'react-intl/locale-data/en';
import intlES from 'react-intl/locale-data/es';
import intlMessagesES from './../i18n/locales/es.json';
import intlMessagesEN from './../i18n/locales/en.json';

addLocaleData([...intlEN, ...intlES]);

/* Define your default translations */
let i18nConfig = {
    locale: 'en',
    messages: intlMessagesEN
};

2) Ändern Sie unsere changeLanguage-Funktion (dieses Mal 'onChangeLanguage'). Diese Funktion empfängt 'lang' von einem SubComponent-Sprachselektor:

onChangeLanguage(lang) {
        switch (lang) {
            case 'ES': i18nConfig.messages = intlMessagesES; break;
            case 'EN': i18nConfig.messages = intlMessagesEN; break;
            default: i18nConfig.messages = intlMessagesEN; break;
        }
        this.setState({ locale: lang });
        i18nConfig.locale = lang;
}

Und endlich rendern:

render() {
        return (
            <IntlProvider key={ i18nConfig.locale } locale={ i18nConfig.locale }  messages={ i18nConfig.messages }>
                <div>
                    <Header onChangeLanguage={this.onChangeLanguage} />
                    // Other components ...
                </div>
            </IntlProvider>
        );
    }

Wenn jemand überhaupt nichts versteht, bitte in Kommentaren! Vielen Dank an @ TomásEhrich

Mit einer neuen React Context API ist das ganz einfach. Erstellen Sie einen Wrapper:

import React from "react";
import Types from "prop-types";
import { IntlProvider, addLocaleData } from "react-intl";
import en from "react-intl/locale-data/en";
import de from "react-intl/locale-data/de";
import deTranslation from "../../lang/de";
import enTranslation from "../../lang/en";

addLocaleData([...en, ...de]);

const { Provider, Consumer } = React.createContext();

class IntlProviderWrapper extends React.Component {
  constructor(...args) {
    super(...args);

    this.switchToEnglish = () =>
      this.setState({ locale: "en", messages: enTranslation });

    this.switchToDeutsch = () =>
      this.setState({ locale: "de", messages: deTranslation });

    // pass everything in state to avoid creating object inside render method (like explained in the documentation)
    this.state = {
      locale: "en",
      messages: enTranslation,
      switchToEnglish: this.switchToEnglish, 
      switchToDeutsch: this.switchToDeutsch 
    };
  }

  render() {
    const { children } = this.props;
    const { locale, messages } = this.state;
    return (
      <Provider value={this.state}>
        <IntlProvider
          key={locale}
          locale={locale}
          messages={messages}
          defaultLocale="en"
        >
          {children}
        </IntlProvider>
      </Provider>
    );
  }
}

export { IntlProviderWrapper as IntlProvider, Consumer as IntlConsumer };

Und dann nutzen Sie diesen Provider und Consumer:

import { Provider } from "react-redux";
import {  IntlProvider } from "./IntlContext";

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <IntlProvider>
          ...
        </IntlProvider>
      </Provider>
    );
  }
}

irgendwo in der App:

import React from "react";
import { Text, Button } from "native-base";
import { IntlConsumer } from "../IntlContext";

const LanguageSwitch = () => (
  <IntlConsumer>
    {({ switchToEnglish, switchToDeutsch }) => (
      <React.Fragment>
        <button onClick={switchToEnglish}>
          English
        </button>
        <button onClick={switchToDeutsch}>
          Deutsch
        </button>
      </React.Fragment>
    )}
  </IntlConsumer>
);

export default LanguageSwitch;

Hier ist das relevante Repository mit allgemeinerer Lösung.

Hinweis: Derzeit verwendet einsatzberechnungsbedingt noch eine alte Kontext-API, in der Zukunft kann diese Lösung jedoch sofort funktionieren.

5

sie können redux verwenden, um Ihre Locale und LocaleMessage zu verwalten. Fügen Sie einfach einen Schlüssel in IntlProvider hinzu.

import React, { Component } from 'react';
import { IntlProvider } from 'react-intl';

class Inter extends Component {
    render() {
      let { locale, localeMessage, children } = this.props;
      return (
          <IntlProvider key={locale} locale={locale} messages={localeMessage}>
              {children}
          </IntlProvider>
      )
    }
};

export default Inter;

0
carroll cai