I min tidligere artikkel dekket jeg Stimulus-et beskjedent JavaScript-rammeverk laget av Basecamp. I dag snakker jeg om internasjonalisering av en Stimulus-applikasjon, siden rammen ikke gir noen I18n-verktøy ut av boksen. Internationalisering er et viktig skritt, spesielt når appen din brukes av folk fra hele verden, så en grunnleggende forståelse av hvordan du gjør det, kan egentlig komme til nytte.
Selvfølgelig er det opp til deg å bestemme hvilken internasjonaliseringsløsning som skal implementeres, det være seg jQuery.I18n, Polyglot eller noen andre. I denne opplæringen vil jeg gjerne vise deg et populært I18n-rammeverk, kalt I18next, som har mange kule funksjoner, og gir mange ekstra tredjeparts plugins for å forenkle utviklingsprosessen enda lenger. Selv med alle disse funksjonene, er I18next ikke et komplekst verktøy, og du trenger ikke å studere mye dokumentasjon for å komme i gang.
I denne artikkelen lærer du hvordan du aktiverer I18n-støtte i Stimulus-applikasjoner ved hjelp av I18next-biblioteket. Spesielt snakker vi om:
Kildekoden er tilgjengelig i opplæringen GitHub repo.
For å komme i gang, la oss klone Stimulus Starter-prosjektet og installere alle avhengighetene ved hjelp av Garn pakkebehandling:
git klon https://github.com/stimulusjs/stimulus-starter.git cd stimulus-starter garn installere
Vi skal bygge et enkelt webprogram som laster opp informasjon om registrerte brukere. For hver bruker viser vi hans / hennes innlogging og antall bilder han eller hun har lastet opp så langt (det spiller ingen rolle hva disse bildene er).
Vi skal også presentere en språkbryter øverst på siden. Når et språk er valgt, bør grensesnittet oversettes med en gang uten sidelastning. Dessuten bør nettadressen vedlegges med en ?locale
GET-parameteren angir hvilken lokal som nå benyttes. Selvfølgelig, hvis siden er lastet med denne parameteren som allerede er oppgitt, bør riktig språk settes automatisk.
Ok, la oss fortsette å gjengi brukerne våre. Legg til følgende linje med kode til offentlig / index.html fil:
Her bruker vi brukere
kontrolleren og gi en nettadresse som du kan laste brukerne fra. I en virkelig applikasjon, ville vi trolig ha et server-side script som henter brukere fra databasen og svarer med JSON. For denne opplæringen, la oss ganske enkelt plassere alle nødvendige data i offentlig / api / brukere / index.json fil:
["login": "johndoe", "photos_count": "male", "login": "annsmith", "photos_count": "20", "gender" "]
Opprett nå en ny src / kontrollere / users_controller.js fil:
importer Controller fra "stimulus" eksport standard klasse utvider Controller connect () this.loadUsers ()
Så snart kontrolleren er koblet til DOM, laster vi asynkront våre brukere ved hjelp av loadUsers ()
metode:
loadUsers () hent (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json))
Denne metoden sender en henting forespørsel til den oppgitte nettadressen, tar tak i svaret, og til slutt gir brukerne:
renderUsers (users) let content = "JSON.parse (users) .forEach ((user) => content + = 'Logg inn: $ user.login
Har lastet opp $ user.photos_count bilde (r)
') this.element.innerHTML = innhold
renderUsers ()
, Parser på nytt JSON, konstruerer en ny streng med alt innholdet, og viser sist dette innholdet på siden (this.element
kommer til å returnere den faktiske DOM-noden som kontrolleren er koblet til, som er div
i vårt tilfelle).
Nå skal vi fortsette å integrere I18next i vår app. Legg til to biblioteker til vårt prosjekt: I18next seg selv og et plugin for å aktivere asynkron lasting av oversettelsesfiler fra baksiden:
garn legg til i18next i18next-xhr-backend
Vi skal lagre alle I18next-relaterte ting i en egen src / i18n / config.js fil, så opprett den nå:
importer i18next fra 'i18next' import I18nXHR fra 'i18next-xhr-backend' const i18n = i18next.use (I18nXHR) .init (fallbackLng: 'en', hviteliste: ['en', 'ru'], forhåndsbelastning: 'en', 'ru'], ns: 'users', defaultNS: 'users', fallbackNS: false, debug: true, backend: loadPath: '/ i18n / lng / ns. json ',, funksjon (feil, t) hvis (feil) returnerer console.error (err)); eksporter i18n som i18n
La oss gå fra topp til bunn for å forstå hva som skjer her:
bruke (I18nXHR)
gjør det mulig for i18next-xhr-backend-plugin.fallbackLng
forteller det å bruke engelsk som tilbakebetalingsspråk.hviteliste
tillater kun engelsk og russisk språk å bli satt. Selvfølgelig kan du velge andre språk.forspenning
instruerer oversettelsesfiler som skal forhåndslastes fra serveren, i stedet for å laste dem når det tilsvarende språket er valgt.ns
betyr "namespace" og aksepterer enten en streng eller en matrise. I dette eksemplet har vi bare ett navneområde, men for større applikasjoner kan du introdusere andre navneområder, som admin
, kurven
, profil
, etc. For hvert navneområde skal en egen oversettelsesfil opprettes.defaultNS
settene brukere
for å være standard navneplass.fallbackNS
deaktiverer namespace-fallback.debug
Tillater feilsøkingsinformasjon å vises i nettleserens konsoll. Spesielt står det hvilke oversettelsesfiler som er lastet, hvilket språk er valgt, etc. Du vil sannsynligvis vil deaktivere denne innstillingen før du distribuerer programmet til produksjon.baksiden
gir konfigurasjon for I18nXHR-pluginet og angir hvor du skal laste oversettelser fra. Legg merke til at banen skal inneholde tittelens tittel, mens filen skal navngis etter navneområdet og ha .json forlengelsefunksjon (feil, t)
er tilbakeringingen til å kjøre når I18next er klar (eller når en feil ble oppdratt).Deretter la vi lage oversettelsesfiler. Oversetter for russisk språk bør plasseres i offentlig / i18n / ru / users.json fil:
"login": "Логин"
Logg Inn
Her er oversettelsesnøkkelen, mens Логин
er verdien som skal vises.
Engelske oversettelser, i sin tur, bør gå til offentlig / i18n / no / users.json fil:
"logg inn": "Logg inn"
For å være sikker på at I18next fungerer, kan du legge til følgende linje kode til tilbakeringingen inne i i18n / config.js fil:
// config går her ... funksjon (feil, t) hvis (err) returner console.error (err) console.log (i18n.t ('logg inn'))
Her bruker vi en metode som kalles t
det betyr "oversette". Denne metoden aksepterer en oversettelsesnøkkel og returnerer den tilsvarende verdien.
Vi kan imidlertid ha mange deler av brukergrensesnittet som må oversettes, og gjør det ved å benytte t
Metoden ville være ganske kjedelig. I stedet foreslår jeg at du bruker et annet plugin som heter loc-i18next, som lar deg oversette flere elementer samtidig.
Installer loc-i18next-plugin:
garn legg til loc-i18next
Importer den øverst på src / i18n / config.js fil:
importere locI18next fra 'loc-i18next'
Gi nå konfigurasjonen for selve plugin:
// andre config const loci18n = locI18next.init (i18n, selectorAttr: 'data-i18n', alternativerAttr: 'data-i18n-alternativer', useOptionsAttr: true); eksporter loci18n som loci18n, i18n som i18n
Det er et par ting å merke seg her:
locI18next.init (i18n)
lager en ny forekomst av pluginet basert på den tidligere definerte forekomsten av I18next.selectorAttr
angir hvilket attributt som skal brukes til å oppdage elementer som krever lokalisering. I utgangspunktet vil loc-i18next søke etter slike elementer og bruke verdien av data-i18n
Tilordne som oversettelsessnøkkel.optionsAttr
Angir hvilket attributt som inneholder flere oversettelsesalternativer.useOptionsAttr
instruerer pluginet for å bruke tilleggsalternativene.Brukerne våre lastes asynkront, så vi må vente til denne operasjonen er ferdig og bare utføre lokalisering etter det. For nå, la oss bare stille en tidtaker som skal vente i to sekunder før du ringer til lokalisere ()
metode-det er en midlertidig hack, selvfølgelig.
importer loci18n fra '... / i18n / config' // annen kode ... loadUsers () hent (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json) setTimeout (() => // <--- this.localize() , '2000') )
Kode på lokalisere ()
metode selv:
lokaliser () loci18n ('. users')
Som du ser, trenger vi bare å sende en velger til loc-i18next-plugin. Alle elementer inne (som har data-i18n
attributtsett) vil bli lokalisert automatisk.
Nå juster du renderUsers
metode. For nå, la oss bare oversette "Logg inn" -ordet:
renderUsers (users) let content = "JSON.parse (users) .forEach ((user) => content + = 'ID: $ user.id
: $ user.login
Har lastet opp $ user.photos_count bilde (r)
') this.element.innerHTML = innhold
Hyggelig! Oppdater siden, vent i to sekunder, og kontroller at "Innloggingsord" vises for hver bruker.
Vi har lokalisert en del av grensesnittet, som er veldig kult. Likevel har hver bruker to flere felt: antall opplastede bilder og kjønn. Siden vi ikke kan forutsi hvor mange bilder hver bruker skal ha, skal "foto" -ordet pluraliseres riktig på grunnlag av det gitte antall. For å gjøre dette, krever vi en data-i18n-alternativer
attributt konfigurert tidligere. Å gi tellingen, data-i18n-alternativer
bør tilordnes med følgende objekt: "count": YOUR_COUNT
.
Kjønnsinformasjon bør også tas i betraktning. Ordet "lastet opp" på engelsk kan brukes på både mann og kvinne, men på russisk blir det enten "загрузил" eller "загрузила", så vi trenger data-i18n-alternativer
igjen, som har "kontekst": "GENDER"
som en verdi. Vær oppmerksom på at du kan bruke denne konteksten til å oppnå andre oppgaver, ikke bare for å gi kjønnsinformasjon.
renderUsers (users) let content = "JSON.parse (users) .forEach ((user) => content + = ': $ user.login
') this.element.innerHTML = innhold
Oppdater nå de engelske oversettelsene:
"login": "Login", "uploaded": "Har lastet opp", "bilder": "ett bilde", "photos_plural": "count photos"
Ingenting komplisert her. Siden for engelsk bryr vi oss ikke om kjønnsinformasjonen (som er konteksten), oversettelsessnøkkelen bør være ganske enkelt lastet opp
. For å gi riktig pluraliserte oversettelser bruker vi bilder
og photos_plural
nøkler. De telle
del er interpolering og vil bli erstattet med det faktiske nummeret.
For det russiske språket er tingene mer komplekse:
"login": "Логин", "uploaded_male": "Загрузил уже", "uploaded_female": "Загрузила уже", "photos_0": "одну фотографию", "photos_1": "count фотографии" photos_2 ":" count фотографий "
Først av alt, merk at vi har begge uploaded_male
og uploaded_female
nøkler for to mulige sammenhenger. Deretter er pluraliseringsregler også mer komplekse på russisk enn på engelsk, så vi må ikke gi to, men tre mulige fraser. I18next støtter mange språk ut av boksen, og dette lille verktøyet kan hjelpe deg å forstå hvilke pluraliseringstaster som skal spesifiseres for et gitt språk.
Vi er ferdige med å oversette applikasjonen vår, men brukerne skal kunne bytte mellom lokalene. Derfor legger du til en ny «språkbryter» -komponent i offentlig / index.html fil:
Gjør den tilsvarende kontrolleren inne i src / kontrollere / languages_controller.js fil:
Import Controller fra "stimulus" import i18n, loci18n fra '... / i18n / config' eksport standard klasse utvider Controller initialize () let languages = [title: 'engelsk', kode: 'en', title: 'Русский', kode: 'ru'] this.element.innerHTML = languages.map ((lang) => return '
Her bruker vi initialize ()
tilbakeringing for å vise en liste over støttede språk. Hver li
har en data-handling
attributt som spesifiserer hvilken metode (switchLanguage
, i dette tilfellet) skal utløses når elementet klikkes på.
Legg nå til switchLanguage ()
metode:
switchLanguage (e) this.currentLang = e.target.getAttribute ("data-lang")
Det tar rett og slett målet for arrangementet og tar tak i verdien av data-lang
Egenskap.
Jeg vil også legge til en getter og setter for currentLang
Egenskap:
få currentLang () return this.data.get ("currentLang") sett currentLang (lang) hvis (i18n.language! == lang) i18n.changeLanguage (lang) hvis (this.currentLang! == lang ) this.data.set ("currentLang", lang) loci18n ('body') this.highlightCurrentLang ()
Getteren er veldig enkel - vi henter verdien av det brukte språket og returnerer det.
Setteren er mer kompleks. Først av alt bruker vi skifte språk
metode hvis det gjeldende språket ikke er lik det valgte. Vi lagrer også den nylig valgte lokalen under data-strøm-lang
attributt (som nås i getteren), lokalisere kroppen til HTML-siden ved hjelp av loc-i18next-pluginet, og til slutt markere den gjeldende locale.
La oss kode på highlightCurrentLang ()
:
highlightCurrentLang () this.switcherTargets.forEach ((el, i) => el.classList.toggle ("current", this.currentLang === el.getAttribute ("data-lang")))
Her er det iterating over en rekke lokale brytere og sammenligne verdiene av deres data-lang
attributter til verdien av den for tiden brukte locale. Hvis verdiene passer, er bryteren tilordnet en nåværende
CSS klasse, ellers er denne klassen fjernet.
For å gjøre this.switcherTargets
konstruere arbeid, må vi definere Stimulus mål på følgende måte:
statiske mål = ["switcher"]
Legg også til data-target
attributter med verdier av switcher
for li
s:
initialiser () // ... this.element.innerHTML = languages.map ((lang) => return '
En annen viktig ting å vurdere er at oversettelsesfiler kan ta litt tid å laste, og vi må vente på at denne operasjonen skal fullføres før du lar lokalet bli slått på. Derfor, la oss dra nytte av lastet
Ring tilbake:
initialiser () i18n.on ('lastet', (lastet) => // <--- let languages = [ title: 'English', code: 'en', title: 'Русский', code: 'ru' ] this.element.innerHTML = languages.map((lang) => komme tilbake '
Til slutt, ikke glem å fjerne setTimeout
fra loadUsers ()
metode:
loadUsers () fetch (this.data.get ("url")) .then (response => response.text ()) .then (json => this.renderUsers (json) this.localize ())
Etter at lokalen er slått, vil jeg gjerne legge til en ?lang
GET parameter til URL-adressen som inneholder koden til det valgte språket. Legge til en GET param uten å laste siden kan enkelt gjøres ved hjelp av History API:
sett currentLang (lang) if (i18n.language! == lang) i18n.changeLanguage (lang) window.history.pushState (null, null, '? lang = $ lang') // <--- if(this.currentLang !== lang) this.data.set("currentLang", lang) loci18n('body') this.highlightCurrentLang()
Den siste tingen vi skal implementere i dag, er muligheten til å angi lokaliteten basert på brukerens preferanser. Et plugin som heter LanguageDetector kan hjelpe oss med å løse denne oppgaven. Legg til en ny Garn pakke:
garn legg til i18next-leser-languagedetector
Importere LanguageDetector
inne i i18n / config.js fil:
importer LngDetector fra 'i18next-browser-languagedetector'
Nå juster konfigurasjonen:
const i18n = i18next.use (I18nXHR) .use (LngDetector) .init (// <--- // other options go here… detection: order: ['querystring', 'navigator', 'htmlTag'], lookupQuerystring: 'lang', , function(err, t) if (err) return console.error(err) );
De rekkefølge
alternativ lister alle teknikker (sortert etter deres betydning) at pluginet bør prøve for å "gjette" den foretrukne lokaliteten:
søkestreng
betyr å sjekke en GET param som inneholder lokalens kode.lookupQuerystring
Setter navnet på GET-parameteren for å bruke, som er lang
i vårt tilfelle.navigator
betyr å få lokaldata fra brukerens forespørsel.htmlTag
innebærer å hente den foretrukne lokaliteten fra lang
attributten til html
stikkord.I denne artikkelen har vi tatt en titt på I18next-en populær løsning for å oversette JavaScript-programmer med letthet. Du har lært hvordan du integrerer I18next med Stimulus-rammen, konfigurer den og laster oversettelsesfiler på asynkron måte. Du har også sett hvordan du bytter mellom lokaliteter og angir standardspråket basert på brukerens preferanser.
I18next har noen ekstra konfigurasjonsalternativer og mange plugins, så sørg for å bla gjennom den offisielle dokumentasjonen for å lære mer. Vær også oppmerksom på at Stimulus ikke tvinger deg til å bruke en bestemt lokaliseringsløsning, så du kan også prøve å bruke noe som jQuery.I18n eller Polyglot.
Det var alt for i dag! Takk for at du leser sammen, og til neste gang.