Reager internationalisering – Sådan

Hvordan kan vi bygge en internationaliseret React-frontend-applikation? Ved hjælp af denne artikel kan du lære, hvordan du registrerer brugerens lokalitet, gemmer den i cookien, lader brugeren ændre deres lokalitet, oversætter brugergrænsefladen og gengiver valutaer i deres passende formater. Yury har også forberedt dig med en liste over nogle fælder og problemer, du kan komme ud for undervejs.

Først og fremmest, lad os definere noget ordforråd. "Internationalisering" er et langt ord, og der er mindst to meget brugte forkortelser:"intl", "i18n". "Lokalisering" kan forkortes til "l10n".

Internationalisering kan generelt opdeles i tre hovedudfordringer:Opdagelse af brugerens lokalitet, oversættelse af UI-elementer, titler samt hints og sidst, men ikke mindst, servering af lokalitetsspecifikt indhold såsom datoer, valutaer og tal. I denne artikel vil jeg kun fokusere på front-end-delen. Vi udvikler en simpel universel React-applikation med fuld internationaliseringssupport.

Internationalisering kan generelt opdeles i følgende udfordringer:

  • registrering af brugerens landestandard;
  • oversætte UI-elementer, titler og tip;
  • viser lokalitetsspecifikt indhold såsom datoer, valutaer og tal.

>Bemærk :I denne artikel vil jeg kun fokusere på frontend-delen. Vi udvikler en simpel universel React-applikation med fuld internationaliseringssupport.

Lad os bruge mit kedellager som udgangspunkt. Her har vi Express-webserveren til server-side rendering, webpack til at bygge JavaScript på klientsiden, Babel til at oversætte moderne JavaScript til ES5 og React til UI-implementeringen. Vi bruger better-npm-run til at skrive OS-agnostiske scripts, nodemon til at køre en webserver i udviklingsmiljøet og webpack-dev-server til at betjene aktiver.

Vores indgangspunkt til serverapplikationen er server.js . Her indlæser vi Babel og babel-polyfill for at skrive resten af ​​serverkoden i moderne JavaScript. Forretningslogik på serversiden er implementeret i src/server.jsx . Her er vi ved at opsætte en Express-webserver, som lytter til port 3001 . Til gengivelse bruger vi en meget simpel komponent fra components/App.jsx , som også er et universelt applikationsdel-indgangspunkt.

Vores indgangspunkt til JavaScript på klientsiden er src/client.jsx . Her monterer vi rodkomponenten component/App.jsx til pladsholderen react-view i HTML-markeringen leveret af Express-webserveren.

Så klon depotet, kør npm install og eksekver nodemon og webpack-dev-server på to konsolfaner samtidigt.

I den første konsolfane:

git clone https://github.com/yury-dymov/smashing-react-i18n.git cd smashing-react-i18n  npm install npm run nodemon

Og i den anden konsolfane:

cd smashing-react-i18n  npm run webpack-devserver

Et websted skulle blive tilgængeligt på localhost:3001 . Åbn din yndlingsbrowser og prøv den.

Vi er klar til at rulle!

1. Registrering af brugerens lokalitet

Der er to mulige løsninger på dette krav. Af en eller anden grund bruger de fleste populære websteder, inklusive Skype's og NBA's, Geo IP til at finde brugerens placering og, baseret på det, til at gætte brugerens sprog. Denne tilgang er ikke kun dyr med hensyn til implementering, men heller ikke rigtig præcis. I dag rejser folk meget, hvilket betyder, at en lokation ikke nødvendigvis repræsenterer brugerens ønskede lokalitet. I stedet bruger vi den anden løsning og behandler HTTP-headeren Accept-Language på serversiden og udtræk brugerens sprogpræferencer baseret på deres systems sprogindstillinger. Denne header sendes af enhver moderne browser inden for en sideanmodning.

Accept-sprog-anmodningshoved

Accept-Language request header giver det sæt naturlige sprog, der foretrækkes som svar på anmodningen. Hvert sprogområde kan tildeles en tilknyttet "kvalitetsværdi", som repræsenterer et estimat af brugerens præference for de sprog, der er specificeret af det pågældende område. Kvalitetsværdien er som standard q=1 . For eksempel Accept-Language: da, en-gb;q=0.8, en;q=0.7 ville betyde, "Jeg foretrækker dansk, men vil acceptere britisk engelsk og andre typer engelsk." Et sprogområde matcher et sprogtag, hvis det nøjagtigt svarer til tagget, eller hvis det nøjagtigt svarer til et præfiks for tagget, således at det første tagtegn efter præfikset er - .

(Det er værd at nævne, at denne metode stadig er ufuldkommen. For eksempel kan en bruger besøge dit websted fra en internetcafé eller en offentlig computer. For at løse dette skal du altid implementere en widget, hvormed brugeren intuitivt kan ændre sproget, og at de kan nemt finde inden for få sekunder.)

Implementering af registrering af brugerens lokalitet

Her er et kodeeksempel for en Node.js Express-webserver. Vi bruger accept-language pakke, som udtrækker lokaliteter fra HTTP-headere og finder de mest relevante blandt dem, der understøttes af dit websted. Hvis ingen findes, vil du falde tilbage til webstedets standardlokalitet. For tilbagevendende brugere kontrollerer vi i stedet cookiens værdi.

Lad os starte med at installere pakkerne:

npm install --save accept-language  npm install --save cookie-parser js-cookie

Og i src/server.jsx , ville vi have dette:

import cookieParser from 'cookie-parser';
import acceptLanguage from 'accept-language';

acceptLanguage.languages(['en', 'ru']);

const app = express();

app.use(cookieParser());

function detectLocale(req) {
  const cookieLocale = req.cookies.locale;

  return acceptLanguage.get(cookieLocale || req.headers['accept-language']) || 'en';
}
…

app.use((req, res) => {
  const locale = detectLocale(req);
  const componentHTML = ReactDom.renderToString(<App />);

  res.cookie('locale', locale, { maxAge: (new Date() * 0.001) + (365 * 24 * 3600) });
  return res.end(renderHTML(componentHTML));
});

Her importerer vi accept-language pakke og opsætte engelske og russiske lokaliteter som understøttet. Vi implementerer også detectLocale funktion, som henter en lokalværdi fra en cookie; hvis ingen findes, så HTTP Accept-Language header behandles. Endelig falder vi tilbage til standardlokaliteten (en i vores eksempel). Når anmodningen er behandlet, tilføjer vi HTTP-headeren Set-Cookie for det sted, der er fundet i svaret. Denne værdi vil blive brugt til alle efterfølgende anmodninger.

2. Oversættelse af brugerfladeelementer, titler og tip

Jeg vil bruge React Intl-pakken til denne opgave. Det er den mest populære og kamptestede i18n-implementering af React-apps. Men alle biblioteker bruger den samme tilgang:De leverer "højere ordens komponenter" (fra det funktionelle programmeringsdesignmønster, der er meget brugt i React), som tilfører internationaliseringsfunktioner til håndtering af beskeder, datoer, tal og valutaer via Reacts kontekstfunktioner.

Først skal vi oprette internationaliseringsudbyderen. For at gøre det vil vi ændre src/server.jsx en smule og src/client.jsx filer.

npm install --save react-intl

Her er src/server.jsx :

import { IntlProvider } from 'react-intl';

…
--- const componentHTML = ReactDom.renderToString(<App />);
const componentHTML = ReactDom.renderToString(
  <IntlProvider locale={locale}>
    <App />
  </IntlProvider>
);
…

Og her er src/client.jsx :

import { IntlProvider } from 'react-intl';
import Cookie from 'js-cookie';

const locale = Cookie.get('locale') || 'en';
…
---  ReactDOM.render(<App />, document.getElementById('react-view'));
ReactDOM.render(
  <IntlProvider locale={locale}>
    <App />
  </IntlProvider>,
  document.getElementById('react-view')
);

Så nu alle IntlProvider underordnede komponenter vil have adgang til internationaliseringsfunktioner. Lad os tilføje noget oversat tekst til vores applikation og en knap for at ændre lokaliteten (til testformål). Vi har to muligheder:enten FormattedMessage komponent eller formatMessage fungere. Forskellen er, at komponenten vil blive pakket ind i en span tag, som er fint til tekst, men ikke egnet til HTML-attributværdier såsom alt og title . Lad os prøve dem begge!

Her er vores src/components/App.jsx fil:

import { FormattedMessage } from 'react-intl';
…
--- <h1>Hello World!</h1>
<h1><FormattedMessage id="app.hello_world" defaultMessage="Hello World!" description="Hello world header greeting" /></h1>

Bemærk venligst, at id attributten skal være unik for hele applikationen, så det giver mening at udvikle nogle regler for navngivning af dine beskeder. Jeg foretrækker at følge formatet componentName.someUniqueIdWithInComponent . defaultMessage værdi vil blive brugt til din applikations standardlokalitet og description attribut giver en vis kontekst til oversætteren.

Genstart nodemon og opdater siden i din browser. Du bør stadig se meddelelsen "Hello World". Men hvis du åbner siden i udviklerværktøjerne, vil du se, at teksten nu er inde i span tags. I dette tilfælde er det ikke et problem, men nogle gange foretrækker vi kun at få teksten uden yderligere tags. For at gøre det har vi brug for direkte adgang til internationaliseringsobjektet leveret af React Intl.

Lad os gå tilbage til src/components/App.jsx :


--- import { FormattedMessage } from 'react-intl';
import { FormattedMessage, intlShape, injectIntl, defineMessages } from 'react-intl';

const propTypes = {
  intl: intlShape.isRequired,
};

const messages = defineMessages({
  helloWorld2: {
    id: 'app.hello_world2',
    defaultMessage: 'Hello World 2!',
  },
});

--- export default class extends Component {
class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>
          <FormattedMessage
            id="app.hello_world"
            defaultMessage="Hello World!"
            description="Hello world header greeting"
          />
        </h1>
        <h1>{this.props.intl.formatMessage(messages.helloWorld2)}</h1>
      </div>
    );
  }
}

App.propTypes = propTypes;

export default injectIntl(App);

Vi har været nødt til at skrive meget mere kode. Først skulle vi bruge injectIntl , som omslutter vores app-komponent og injicerer intl objekt. For at få den oversatte besked var vi nødt til at ringe til formatMessage metode og videregive en message objekt som parameter. Denne message objekt skal have entydigt id og defaultValue egenskaber. Vi bruger defineMessages fra React Intl for at definere sådanne objekter.

Det bedste ved React Intl er dets økosystem. Lad os tilføje babel-plugin-react-intl til vores projekt, som vil udtrække FormattedMessages fra vores komponenter og opbyg en oversættelsesordbog. Vi vil videregive denne ordbog til oversætterne, som ikke behøver nogen programmeringsevner for at udføre deres arbejde.

npm install --save-dev babel-plugin-react-intl

Her er .babelrc :

{
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ],
  "env": {
    "development": {
      "plugins":[
        ["react-intl", {
          "messagesDir": "./build/messages/"
        }]
      ]
    }
  }
}

Genstart nodemon, og du skulle se, at en build/messages mappe er blevet oprettet i projektets rod, med nogle mapper og filer inde, der afspejler dit JavaScript-projekts mappestruktur. Vi skal flette alle disse filer til én JSON. Brug gerne mit script. Gem det som scripts/translate.js .

Nu skal vi tilføje et nyt script til package.json :

"scripts": {
  …
  "build:langs": "babel scripts/translate.js | node",
  …
}

Lad os prøve det!

npm run build:langs

Du bør se en en.json fil i build/lang mappe med følgende indhold:

{
  "app.hello_world": "Hello World!",
  "app.hello_world2": "Hello World 2!"
}

Det virker! Nu kommer en interessant del. På serversiden kan vi indlæse alle oversættelser i hukommelsen og betjene hver anmodning i overensstemmelse hermed. Men for klientsiden er denne tilgang ikke anvendelig. I stedet sender vi JSON-filen med oversættelser én gang, og en klient vil automatisk anvende den angivne tekst for alle vores komponenter, så klienten kun får det, den har brug for.

Lad os kopiere outputtet til public/assets mappe og også give nogle oversættelser.

ln -s ../../build/lang/en.json public/assets/en.json

Bemærk: Hvis du er en Windows-bruger, er symbolske links ikke tilgængelige for dig, hvilket betyder, at du manuelt skal kopiere kommandoen nedenfor, hver gang du genopbygger dine oversættelser:

cp ../../build/lang/en.json public/assets/en.json

I public/assets/ru.json , vi har brug for følgende:

{
  "app.hello_world": "Привет мир!",
  "app.hello_world2": "Привет мир 2!"
}

Nu skal vi justere server- og klientkoden.

Til serversiden er vores src/server.jsx filen skal se sådan ud:

--- import { IntlProvider } from 'react-intl';
import { addLocaleData, IntlProvider } from 'react-intl';
import fs from 'fs';
import path from 'path';

import en from 'react-intl/locale-data/en';
import ru from 'react-intl/locale-data/ru';

addLocaleData([…ru, …en]);

const messages = {};
const localeData = {};

['en', 'ru'].forEach((locale) => {
  localeData[locale] = fs.readFileSync(path.join(__dirname, '../node_modules/react-intl/locale-data/${locale}.js')).toString();
  messages[locale] = require('../public/assets/${locale}.json');
});

--- function renderHTML(componentHTML) {
function renderHTML(componentHTML, locale) {
…
      <script type="application/javascript" src="${assetUrl}/public/assets/bundle.js"></script>
      <script type="application/javascript">${localeData[locale]}</script>

…

--- <IntlProvider locale={locale}>
<IntlProvider locale={locale} messages={messages[locale]}>
…
---  return res.end(renderHTML(componentHTML));
return res.end(renderHTML(componentHTML, locale));

Her gør vi følgende:

  • cachemeddelelser og lokalitetsspecifik JavaScript for valutaen DateTime og Number formatering under opstart (for at sikre god ydeevne);
  • udvidelse af renderHTML metode, så vi kan indsætte lokalitetsspecifik JavaScript i den genererede HTML-markup;
  • leverer de oversatte beskeder til IntlProvider (alle disse meddelelser er nu tilgængelige for underordnede komponenter).

For klientsiden skal vi først installere et bibliotek for at udføre AJAX-anmodninger. Jeg foretrækker at bruge isomorphic-fetch, fordi vi højst sandsynligt også skal anmode om data fra tredjeparts API'er, og isomorphic-fetch kan gøre det meget godt i både klient- og servermiljøer.

npm install --save isomorphic-fetch

Her er src/client.jsx :

--- import { IntlProvider } from 'react-intl';
import { addLocaleData, IntlProvider } from 'react-intl';
import fetch from 'isomorphic-fetch';

const locale = Cookie.get('locale') || 'en';

fetch(`/public/assets/${locale}.json`)
  .then((res) => {
    if (res.status >= 400) {
      throw new Error('Bad response from server');
    }

    return res.json();
  })
  .then((localeData) => {
    addLocaleData(window.ReactIntlLocaleData[locale]);

    ReactDOM.render(
---        <IntlProvider locale={locale}>
      <IntlProvider locale={locale} messages={localeData}>
…
    );
}).catch((error) => {
  console.error(error);
});

Vi skal også justere src/server.jsx , så Express serverer oversættelses-JSON-filerne for os. Bemærk, at du i produktionen ville bruge noget som nginx i stedet.

app.use(cookieParser());
app.use('/public/assets', express.static('public/assets'));

Efter at JavaScript er initialiseret, client.jsx vil gribe lokaliteten fra cookien og anmode om JSON-filen med oversættelserne. Bagefter vil vores enkeltsidede applikation fungere som før.

Tid til at tjekke, at alt fungerer fint i browseren. Åbn fanen "Netværk" i udviklerværktøjerne, og kontroller, at JSON er blevet hentet af vores klient.

For at afslutte denne del, lad os tilføje en simpel widget for at ændre lokaliteten i src/components/LocaleButton.jsx :

import React, { Component, PropTypes } from 'react';
import Cookie from 'js-cookie';

const propTypes = {
  locale: PropTypes.string.isRequired,
};

class LocaleButton extends Component {
  constructor() {
    super();

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    Cookie.set('locale', this.props.locale === 'en' ? 'ru' : 'en');
    window.location.reload();
  }

  render() {
    return <button onClick={this.handleClick}>{this.props.locale === 'en' ? 'Russian' : 'English'};
  }
}

LocaleButton.propTypes = propTypes;

export default LocaleButton;

Tilføj følgende til src/components/App.jsx :

import LocaleButton from './LocaleButton';

…

    <h1>{this.props.intl.formatMessage(messages.helloWorld2)}</h1>
    <LocaleButton locale={this.props.intl.locale} />

Bemærk, at når brugeren ændrer deres lokalitet, genindlæser vi siden for at sikre, at den nye JSON-fil med oversættelserne bliver hentet.

På høje tid til at teste! OK, så vi har lært, hvordan man registrerer brugerens lokalitet, og hvordan man viser oversatte meddelelser. Inden vi går videre til den sidste del, lad os diskutere to andre vigtige emner.

Pluralisering og skabeloner

På engelsk har de fleste ord en af ​​to mulige former:"et æble", "mange æbler." På andre sprog er tingene meget mere komplicerede. For eksempel har russisk fire forskellige former. Forhåbentlig vil React Intl hjælpe os med at håndtere pluralisering i overensstemmelse hermed. Den understøtter også skabeloner, så du kan levere variabler, der indsættes i skabelonen under gengivelsen. Sådan fungerer det.

I src/components/App.jsx , vi har følgende:

const messages = defineMessages({
  counting: {
    id: 'app.counting',
    defaultMessage: 'I need to buy {count, number} {count, plural, one {apple} other {apples}}'
  },

…

    <LocaleButton locale={this.props.intl.locale} />
    <div>{this.props.intl.formatMessage(messages.counting, { count: 1 })}</div>
    <div>{this.props.intl.formatMessage(messages.counting, { count: 2 })}</div>
    <div>{this.props.intl.formatMessage(messages.counting, { count: 5 })}</div>

Her definerer vi en skabelon med variablen count . Vi udskriver enten "1 æble", hvis count er lig med 1, 21 osv. eller "2 æbler" ellers. Vi skal sende alle variabler inden for formatMessage 's values mulighed.

Lad os genopbygge vores oversættelsesfil og tilføje de russiske oversættelser for at kontrollere, at vi kan levere mere end to varianter til andre sprog end engelsk.

npm run build:langs

Her er vores public/assets/ru.json fil:

{
  …
  "app.counting": "Мне нужно купить {count, number} {count, plural, one {яблоко} few {яблока} many {яблок}}"
}

Alle use cases er dækket nu. Lad os komme videre!

3. Visning af lokalitetsspecifikt indhold såsom datoer, valutaer og tal

Dine data vil blive repræsenteret forskelligt afhængigt af lokaliteten. For eksempel ville russisk vise 500,00 $ og 10.12.2016 , hvorimod amerikansk engelsk ville vise $500.00 og 12/10/2016 .

React Intl leverer React-komponenter til sådanne typer data og også til den relative gengivelse af tid, som automatisk vil blive opdateret hvert 10. sekund, hvis du ikke tilsidesætter standardværdien.

Føj dette til src/components/App.jsx :

--- import { FormattedMessage, intlShape, injectIntl, defineMessages } from 'react-intl';
import {
  FormattedDate,
  FormattedRelative,
  FormattedNumber,
  FormattedMessage,
  intlShape,
  injectIntl,
  defineMessages,
} from 'react-intl';

…

<div>{this.props.intl.formatMessage(messages.counting, { count: 5 })}</div>
<div><FormattedDate value={Date.now()} /></div>
<div><FormattedNumber value="1000" currency="USD" currencyDisplay="symbol" style="currency" /></div>
<div><FormattedRelative value={Date.now()} /></div>

Opdater browseren og tjek siden. Du skal vente i 10 sekunder for at se, at FormattedRelative komponenten er blevet opdateret.

Du finder mange flere eksempler i den officielle wiki.

Fedt, ikke? Nå, nu står vi måske over for et andet problem, som påvirker universel gengivelse.

I gennemsnit vil der gå to sekunder, mellem serveren leverer markup til klienten, og klienten initialiserer JavaScript på klientsiden. Det betyder, at alle DateTimes gengivet på siden kan have forskellige værdier på server- og klientsiden, hvilket pr. definition bryder universel gengivelse. For at løse dette giver React Intl en speciel attribut, initialNow . Dette giver et servertidsstempel, der til at begynde med vil blive brugt af JavaScript på klientsiden som et tidsstempel; på denne måde vil server- og klientkontrolsummerne være ens. Når alle komponenter er blevet monteret, vil de bruge browserens aktuelle tidsstempel, og alt vil fungere korrekt. Så dette trick bruges kun til at initialisere JavaScript på klientsiden for at bevare universel gengivelse.

Her er src/server.jsx :

--- function renderHTML(componentHTML, locale) {
function renderHTML(componentHTML, locale, initialNow) {
  return `
    <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Hello React</title>
      </head>
      <body>
        <div id="react-view">${componentHTML}</div>
        <script type="application/javascript" src="${assetUrl}/public/assets/bundle.js"></script>
        <script type="application/javascript">${localeData[locale]}</script>
        <script type="application/javascript">window.INITIAL_NOW=${JSON.stringify(initialNow)}</script>
      </body>
    </html>
  `;
}

    const initialNow = Date.now();
    const componentHTML = ReactDom.renderToString(
---   <IntlProvider locale={locale} messages={messages[locale]}>
      <IntlProvider initialNow={initialNow} locale={locale} messages={messages[locale]}>
        <App />
      </IntlProvider>
    );

    res.cookie('locale', locale, { maxAge: (new Date() * 0.001) + (365 * 24 * 3600) });
---   return res.end(renderHTML(componentHTML, locale));
    return res.end(renderHTML(componentHTML, locale, initialNow));

Og her er src/client.jsx :

--- <IntlProvider locale={locale} messages={localeData}>
<IntlProvider initialNow={parseInt(window.INITIAL_NOW, 10)} locale={locale} messages={localeData}>

Genstart nodemon, og problemet vil næsten være væk! Det kan fortsætte, fordi vi bruger Date.now() , i stedet for et tidsstempel leveret af databasen. For at gøre eksemplet mere realistisk, i app.jsx erstatte Date.now() med et nyligt tidsstempel, såsom 1480187019228 .

(Du står muligvis over for et andet problem, når serveren ikke er i stand til at gengive DateTime i det rigtige format, som også vil bryde universel gengivelse. Dette skyldes, at version 4 af Node.js ikke er bygget med Intl-understøttelse som standard. For at løse dette, følg en af ​​løsningerne beskrevet i den officielle wiki.)

4. Et problem

Det lyder for godt til at være sandt indtil videre, gør det ikke? Vi som frontend-udviklere skal altid være meget forsigtige med alt, givet de mange forskellige browsere og platforme. React Intl bruger den native Intl browser API til at håndtere DateTime og Number formater. På trods af at det blev introduceret i 2012, understøttes det stadig ikke af alle moderne browsere. Selv Safari understøtter det kun delvist siden iOS 10. Her er hele tabellen fra CanIUse til reference.

Dette betyder, at hvis du er villig til at dække et mindretal af browsere, der ikke understøtter Intl API, så skal du bruge en polyfill. Heldigvis er der en, Intl.js. Det lyder måske som en perfekt løsning igen, men fra min erfaring har det sine egne ulemper. Først og fremmest skal du tilføje det til JavaScript-pakken, og det er ret tungt. Du vil også kun levere polyfillet til browsere, der ikke understøtter Intl API indbygget, for at reducere din bundtstørrelse. Alle disse teknikker er velkendte, og du kan finde dem, sammen med hvordan man gør det med webpack, i Intl.js’ dokumentation. Det største problem er dog, at Intl.js ikke er 100 % nøjagtig, hvilket betyder, at DataTime og Number repræsentationer kan variere mellem serveren og klienten, hvilket vil bryde gengivelsen på serversiden igen. Se venligst det relevante GitHub-problem for flere detaljer.

Jeg har fundet en anden løsning, som bestemt har sine egne ulemper, men den fungerer fint for mig. Jeg implementerede en meget overfladisk polyfill, som kun har ét stykke funktionalitet. Selvom det bestemt er ubrugeligt i mange tilfælde, tilføjer det kun 2 KB til pakkens størrelse, så der er ikke engang behov for at implementere dynamisk kodeindlæsning til forældede browsere, hvilket gør den overordnede løsning enklere. Du er velkommen til at fordele og udvide det, hvis du tror, ​​at denne tilgang ville fungere for dig.

Konklusion

Nå, nu føler du måske, at tingene bliver for komplicerede, og du kan blive fristet til at implementere alt selv. Det gjorde jeg engang; Jeg vil ikke anbefale det. Til sidst vil du nå frem til de samme ideer bag React Intls implementering, eller værre, du tror måske, at der ikke er mange muligheder for at gøre visse ting bedre eller gøre tingene anderledes.

Du tror måske, at du kan løse Intl API-supportproblemet ved at stole på Moment.js i stedet (jeg vil ikke nævne andre biblioteker med samme funktionalitet, fordi de enten ikke er understøttet eller ubrugelige). Heldigvis prøvede jeg det, så jeg kan spare dig en masse af tid. Jeg har lært, at Moment.js er en monolit og meget tung, så selvom det måske virker for nogle mennesker, vil jeg ikke anbefale det.

At udvikle din egen polyfill lyder ikke godt, fordi du helt sikkert skal kæmpe med fejl og understøtte løsningen i et stykke tid. Konklusionen er, at der ikke er nogen perfekt løsning i øjeblikket, så vælg den, der passer dig bedst.

(Hvis du føler dig tabt på et tidspunkt, eller hvis noget ikke virker som forventet, så tjek "løsnings"-grenen af ​​mit lager.)

Forhåbentlig har denne artikel givet dig al den viden, der er nødvendig for at bygge en internationaliseret React-frontend-applikation. Du bør nu vide, hvordan du finder brugerens lokalitet, gemmer den i cookien, lader brugeren ændre deres lokalitet, oversætter brugergrænsefladen og gengiver valutaer, DateTimes og Number s i de passende formater! Du bør også nu være opmærksom på nogle fælder og problemer, du kan komme ud for, så vælg den mulighed, der passer til dine krav, budget i bundtstørrelse og antallet af sprog, der skal understøttes.

Yderligere læsning om SmashingMag:

  • Hvorfor du bør overveje React Native til din mobilapp
  • Sådan skaleres React-applikationer
  • Opbygning af din første iOS-app med JavaScript