Java-lokalisering - formateringsmeldinger

1. Introduksjon

I denne opplæringen vil vi vurdere hvordan vi kan lokalisere og formatere meldinger basert på Lokal.

Vi bruker begge Java-ene MessageFormat og tredjepartsbiblioteket, ICU.

2. Brukssak for lokalisering

Når applikasjonen vår skaffer et bredt publikum av brukere fra hele verden, kan det være lurt å gjøre det vise forskjellige meldinger basert på brukerens preferanser.

Det første og viktigste aspektet er språket brukeren snakker. Andre kan omfatte formater for valuta, antall og dato. Sist men ikke minst er kulturelle preferanser: hva som er akseptabelt for brukere fra ett land, kan være utålelig for andre.

Anta at vi har en e-postklient og at vi vil vise varsler når en ny melding kommer.

Et enkelt eksempel på en slik melding kan være denne:

Alice har sendt deg en melding.

Det er greit for engelsktalende brukere, men ikke-engelsktalende er kanskje ikke så glade. For eksempel vil fransktalende brukere foretrekke å se denne meldingen:

Alice har en utsending og melding. 

Mens polske folk ville være fornøyde med å se denne:

Alice wysłała ci wiadomość. 

Hva om vi vil ha et riktig formatert varsel, selv i tilfelle når Alice ikke bare sender en melding, men få meldinger?

Vi kan bli fristet til å løse problemet ved å sammenkoble forskjellige brikker i en enkelt streng, slik:

Strengmelding = "Alice har sendt" + antall + "meldinger"; 

Situasjonen kan lett komme ut av kontroll når vi trenger varsler i tilfelle når ikke bare Alice, men også Bob kan sende meldingene:

Bob har sendt to meldinger. Bob en utsending deux meldinger. Bob wysłał dwie wiadomości.

Legg merke til hvordan verbet endres i tilfelle polsk (wysłała vs. wysłał) Språk. Det illustrerer det faktum at banal streng sammenkobling er sjelden akseptabelt for lokalisering av meldinger.

Som vi ser, får vi to typer problemer: den ene er relatert til oversettelser og den andre er relatert til formater. La oss ta opp dem i de følgende avsnittene.

3. Melding Lokalisering

Vi kan definere lokalisering, eller l10n, av en applikasjon som prosessen med å tilpasse applikasjonen til brukerens komfort. Noen ganger, begrepet internalisering, eller i18n, brukes også.

For å lokalisere applikasjonen, la oss først og fremst eliminere alle hardkodede meldinger ved å flytte dem inn i vår ressurser mappe:

Hver fil skal inneholde nøkkelverdipar med meldingene på tilsvarende språk. For eksempel fil messages_en.properties skal inneholde følgende par:

label = Alice har sendt deg en melding.

messages_pl.properties skal inneholde følgende par:

label = Alice wysłała ci wiadomość.

Tilsvarende tilordner andre filer passende verdier til nøkkelen merkelapp. Nå, for å hente den engelske versjonen av varselet, kan vi bruke ResourceBundle:

ResourceBundle bundle = ResourceBundle.getBundle ("meldinger", Locale.UK); Strengmelding = bundle.getString ("label");

Verdien på variabelen beskjed vil være "Alice har sendt deg en melding."

Java Lokal klasse inneholder snarveier til ofte brukte språk og land.

Når det gjelder polsk språk, kan vi skrive følgende:

ResourceBundle bundle = ResourceBundle.getBundle ("meldinger", Locale.forLanguageTag ("pl-PL")); Strengmelding = bundle.getString ("label");

La oss bare nevne at hvis vi ikke gir noe sted, vil systemet bruke en standard. Vi kan få mer informasjon om dette problemet i vår artikkel "Internasjonalisering og lokalisering i Java 8". Deretter vil systemet blant tilgjengelige oversettelser velge den som ligner mest på den nåværende aktive lokaliteten.

Å plassere meldingene i ressursfilene er et godt skritt mot å gjøre applikasjonen mer brukervennlig. Det gjør det lettere å oversette hele applikasjonen av følgende årsaker:

  1. en oversetter trenger ikke å se gjennom applikasjonen på jakt etter meldingene
  2. en oversetter kan se hele uttrykket som hjelper til med å forstå konteksten og dermed muliggjør en bedre oversettelse
  3. vi trenger ikke å kompilere hele applikasjonen når en oversettelse til et nytt språk er klar

4. Meldingsformat

Selv om vi har flyttet meldingene fra koden til et eget sted, inneholder de fremdeles noe hardkodet informasjon. Det ville være fint å kunne tilpasse navnene og numrene i meldingene på en slik måte at de forblir grammatisk korrekte.

Vi kan definere formateringen som en prosess for å gjengi strengmalen ved å erstatte plassholderne med deres verdier.

I de følgende avsnittene vil vi vurdere to løsninger som lar oss formatere meldingene.

4.1. Java MessageFormat

For å formatere strenger, definerer Java en rekke formatmetoder i java.lang.Streng. Men vi kan få enda mer støtte via java.text.format.MessageFormat.

For å illustrere, la oss lage et mønster og mate det til et MessageFormat forekomst:

Strengmønster = "På {0, dato} sendte {1} deg" + "{2, valg, 0 # ingen meldinger | 1 # en melding | 2 # to meldinger | 2 <{2, antall, heltall} meldinger} . "; MessageFormat formatter = ny MessageFormat (mønster, Locale.UK); 

Mønsterstrengen har spor for tre plassholdere.

Hvis vi leverer hver verdi:

Strengmelding = formatter.format (nytt objekt [] {date, "Alice", 2});

Deretter MessageFormat vil fylle ut malen og gjengi meldingen vår:

27. april 2019 sendte Alice deg to meldinger.

4.2. MessageFormat Syntaks

Fra eksemplet ovenfor ser vi at meldingsmønsteret:

mønster = "På {...} sendte {..} deg {...}.";

inneholder plassholdere som er krøllete parenteser {…} med et nødvendig argument indeks og to valgfrie argumenter, type og stil:

{index} {index, type} {index, type, style}

Plassholderindeksen tilsvarer posisjonen til et element fra matrisen av objekter som vi ønsker å sette inn.

Når det er tilstede, type og stil kan ta følgende verdier:

typestil
Nummerheltall, valuta, prosent, tilpasset format
Datokort, middels, langt, fullt, tilpasset format
tidkort, middels, langt, fullt, tilpasset format
valgtilpasset format

Navnene på typene og stilene taler stort sett for seg selv, men vi kan konsultere den offisielle dokumentasjonen for mer informasjon.

La oss se nærmere på tilpasset format.

I eksemplet ovenfor brukte vi følgende formatuttrykk:

{2, valg, 0 # ingen meldinger | 1 # en melding | 2 # to meldinger | 2 <{2, antall, heltall} meldinger}

Generelt har valgstilen form av alternativer skilt av den vertikale stangen (eller røret):

Inne i alternativene, samsvarer verdien kJeg og strengen vJeg er atskilt med # bortsett fra det siste alternativet. Legg merke til at vi kan hekke andre mønstre i strengen vJeg slik vi gjorde det for det siste alternativet:

{2, valg, ... | 2 <{2, antall, heltall} meldinger}

Valgtypen er en numerisk basert, så det er en naturlig rekkefølge for kampverdiene kJeg som deler en numerisk linje i intervaller:

Hvis vi gir en verdi k som hører til intervallet [kJeg, kjeg + 1) (den venstre enden er inkludert, den høyre er ekskludert), deretter verdien vJeg er valgt.

La oss se nærmere på områdene for den valgte stilen. For dette formål tar vi dette mønsteret:

mønster = "Du har" + "{0, valg, 0 # ingen meldinger | 1 # en melding | 2 # to meldinger | 2 <{0, antall, heltall} meldinger}.";

og gi forskjellige verdier for sin unike plassholder:

nbeskjed
-1, 0, 0.5Du har ingen meldinger.
1, 1.5Du har en melding.
2Du har to meldinger.
2.5Du har to meldinger.
5Du har fem meldinger.

4.3. Gjør ting bedre

Så vi formaterer nå meldingene våre. Men selve meldingen forblir hardkodet.

Fra forrige avsnitt vet vi at vi bør trekke ut strengemønstrene til ressursene. For å skille bekymringene våre, la oss lage en ny haug med ressursfiler kalt formater:

I disse lager vi en nøkkel som heter merkelapp med språkspesifikt innhold.

I den engelske versjonen vil vi for eksempel sette følgende streng:

label = På {0, dato, full} {1} har sendt deg + {2, valg, 0 # ingenting | 1 # en melding | 2 # to meldinger | 2 <{2, antall, heltall} meldinger}.

Vi bør endre den franske versjonen litt på grunn av tilfellet nullmelding:

label = {0, date, short}, {1} 0 <vous a envoyé + {2, choice, 0 # aucun message | 1 # un message | 2 # deux messages | 2 <{2, number, integer} messages} .

Og vi må også gjøre lignende modifikasjoner i den polske og italienske versjonen.

Den polske versjonen viser faktisk enda et problem. I følge grammatikken til det polske språket (og mange andre) må verbet stemme overens med faget. Vi kan løse dette problemet ved å bruke valgstypen, men la oss vurdere en annen løsning.

4.4. ICU-er MessageFormat

La oss bruke Internasjonale komponenter for Unicode (ICU) bibliotek. Vi har allerede nevnt det i opplæringen Konverter en streng til tittelsak. Det er en moden og mye brukt løsning som lar oss tilpasse applikasjonen til forskjellige språk.

Her skal vi ikke utforske det i detaljer. Vi vil bare begrense oss til det leketøyapplikasjonen vår trenger. For den mest omfattende og oppdaterte informasjonen, bør vi sjekke ICUs offisielle nettsted.

I skrivende stund ble den siste versjonen av ICU for Java (ICU4J) er 64,2. Som vanlig, for å begynne å bruke det, bør vi legge det til som en avhengighet av prosjektet vårt:

 com.ibm.icu icu4j 64.2 

Anta at vi vil ha et riktig utformet varsel på forskjellige språk og for forskjellige antall meldinger:

NEngelskPusse
0Alice har ikke sendt deg noen meldinger.

Bob har ikke sendt deg noen meldinger.

Alice nie wysłała ci żadnej wiadomości.

Bob nie wysłał ci żadnej wiadomości.

1Alice har sendt deg en melding.

Bob har sendt deg en melding.

Alice wysłała ci wiadomość.

Bob wysłał ci wiadomość.

> 1Alice har sendt deg N-meldinger.

Bob har sendt deg N-meldinger.

Alice wysłała ci N wiadomości.

Bob wysłał ci N wiadomości.

Først og fremst bør vi lage et mønster i de stedsspesifikke ressursfilene.

La oss bruke filen på nytt formats.properties og legg til en nøkkel label-icu med følgende innhold:

label-icu = {0} har sendt deg + {2, flertall, = 0 {ingen meldinger} = 1 {en melding} + andre {{2, tall, heltall} meldinger}}.

Den inneholder tre plassholdere som vi mater ved å sende det en tre-element matrise:

Objekt [] data = nytt objekt [] {"Alice", "kvinne", 0}

Vi ser at den kjønnsverdige plassholderen i den engelske versjonen ikke er til nytte, mens den i den polske:

label-icu = {0} {2, flertall, = 0 {nie} annet {}} + {1, velg, mann {wysłał} kvinne {wysłała} annet {wysłało}} + ci {2, flertall, = 0 { żadnych wiadomości} = 1 {wiadomość} + annet {{2, nummer, heltall} wiadomości}}.

vi bruker den for å skille mellom wysłał / wysłała / wysłało.

5. Konklusjon

I denne opplæringen vurderte vi hvordan vi kan lokalisere og formatere meldingene som vi viser til brukerne av applikasjonene våre.

Som alltid er kodebitene for denne opplæringen på GitHub-depotet vårt.


$config[zx-auto] not found$config[zx-overlay] not found