Lokalizácia Java - formátovanie správ

1. Úvod

V tomto návode zvážime, ako môžeme lokalizovať a formátovať správy založené na Miestne nastavenie.

Budeme používať obe Javy MessageFormat a knižnica tretích strán, ICU.

2. Prípad použitia lokalizácie

Keď si naša aplikácia získa široké publikum používateľov z celého sveta, možno budeme chcieť zobrazovať rôzne správy na základe preferencií používateľa.

Prvým a najdôležitejším aspektom je jazyk, ktorým používateľ hovorí. Medzi ďalšie patria formáty mien, čísel a dátumov. V neposlednom rade sú kultúrne preferencie: to, čo je prijateľné pre používateľov z jednej krajiny, by mohlo byť netolerovateľné pre ostatné.

Predpokladajme, že máme e-mailového klienta a chceme zobrazovať upozornenia, keď príde nová správa.

Jednoduchým príkladom takejto správy môže byť táto:

Alica ti poslala správu.

Pre anglicky hovoriacich používateľov je to v poriadku, ale neanglicky hovoriaci nemusí byť taký šťastný. Napríklad frankofónni používatelia by radšej videli túto správu:

Správa Alice vous a envoyé un. 

Zatiaľ čo Poliakov by potešila návšteva tohto:

Alice wysłała ci wiadomość. 

Čo ak chceme mať správne naformátované upozornenie aj v prípade, keď Alica pošle nielen jednu správu, ale len málo správ?

Mohlo by nás lákať vyriešiť tento problém zreťazením rôznych častí do jedného reťazca, napríklad takto:

String message = "Alica poslala" + množstvo + "správ"; 

Situácia sa môže ľahko vymknúť spod kontroly, keď potrebujeme upozornenia, ak by správy mohla posielať nielen Alice, ale aj Bob:

Bob poslal dve správy. Bob vyslanec deux messages. Bob wysłał dwie wiadomości.

Všimnite si, ako sa sloveso mení v prípade poľštiny (wysłała vs wysłał) Jazyk. Ilustruje sa tým skutočnosť, že banálne zreťazenie reťazca je pre lokalizáciu správ zriedka prijateľné.

Ako vidíme, máme dva typy problémov: jeden súvisí s prekladmi a druhý s formátmi. Poďme sa im venovať v nasledujúcich častiach.

3. Lokalizácia správy

Môžeme definovať lokalizácia, príp l10naplikácie ako proces prispôsobenia aplikácie pohodliu používateľa. Niekedy termín internalizácia, alebo i18n, sa tiež používa.

Aby sme mohli lokalizovať aplikáciu, v prvom rade vylúčime všetky pevne zakódované správy ich presunutím do našej zdrojov priečinok:

Každý súbor by mal obsahovať páry kľúč - hodnota so správami v príslušnom jazyku. Napríklad pilník messages_en.properties by mala obsahovať nasledujúci pár:

label = Alica ti poslala správu.

messages_pl.properties by mala obsahovať nasledujúci pár:

štítok = Alice wysłała ci wiadomość.

Podobne ostatné súbory priraďujú kľúču príslušné hodnoty štítok. Teraz, aby sme si mohli vyzdvihnúť anglickú verziu oznámenia, môžeme použiť ResourceBundle:

ResourceBundle bundle = ResourceBundle.getBundle ("správy", Locale.UK); Reťazec message = bundle.getString ("label");

Hodnota premennej správa bude "Alice ti poslala správu."

Java Miestne nastavenie trieda obsahuje odkazy na často používané jazyky a krajiny.

V prípade poľského jazyka môžeme napísať nasledovné:

ResourceBundle bundle = ResourceBundle.getBundle ("správy", Locale.forLanguageTag ("pl-PL")); Reťazec message = bundle.getString ("label");

Spomeňme len to, že ak neposkytneme žiadne miestne nastavenie, systém použije predvolené. Viac podrobností o tejto problematike môžeme nájsť v našom článku „Internacionalizácia a lokalizácia v prostredí Java 8“. Potom spomedzi dostupných prekladov systém vyberie ten, ktorý sa najviac podobá na aktuálne aktívne miestne nastavenie.

Umiestnenie správ do zdrojových súborov je dobrým krokom k dosiahnutiu toho, aby bola aplikácia prehľadnejšia. Uľahčuje preklad celej aplikácie z nasledujúcich dôvodov:

  1. prekladateľ nemusí pri hľadaní správ prehliadať aplikáciu
  2. prekladateľ vidí celú frázu, ktorá pomáha pochopiť kontext, a tým uľahčuje lepší preklad
  3. keď bude pripravený preklad do nového jazyka, nemusíme prekompilovať celú aplikáciu

4. Formát správy

Aj keď sme správy z kódu presunuli na samostatné miesto, stále obsahujú niektoré pevne zakódované informácie. Bolo by pekné mať možnosť prispôsobiť si mená a čísla v správach takým spôsobom, aby zostali gramaticky správne.

Formátovanie môžeme definovať ako proces vykreslenia šablóny reťazca nahradením zástupných symbolov ich hodnotami.

V nasledujúcich častiach zvážime dve riešenia, ktoré nám umožňujú formátovať správy.

4.1. Java MessageFormat

Na formátovanie reťazcov definuje Java početné metódy formátovania v systéme Windows java.lang.String. Ešte väčšiu podporu však môžeme získať prostredníctvom java.text.format.MessageFormat.

Pre ilustráciu vytvorme vzor a založme ho na a MessageFormat inštancia:

String pattern = "Dňa {0, date} vám {1} poslal" + "{2, výber, 0 # žiadne správy | 1 # správa | 2 # dve správy | 2 <{2, number, integer} správy} . "; MessageFormat formatter = nový MessageFormat (vzor, ​​Locale.UK); 

Reťazec so vzorkami má otvory pre tri zástupné symboly.

Ak zadáme každú hodnotu:

Reťazcová správa = formatter.format (nový objekt [] {dátum, "Alice", 2});

Potom MessageFormat vyplní šablónu a vykreslí našu správu:

Dňa 27. apríla 2019 vám Alice poslala dve správy.

4.2. MessageFormat Syntax

Z vyššie uvedeného príkladu vidíme, že vzor správy:

pattern = "Dňa {...} vám {..} poslal {...}.";

obsahuje zástupné symboly, ktoré sú zloženými zátvorkami {…} s požadovaným argumentom index a dva voliteľné argumenty, typu a štýl:

{index} {index, typ} {index, typ, štýl}

Index zástupcu zodpovedá pozícii prvku z poľa objektov, ktoré chceme vložiť.

Ak sú k dispozícii, typu a štýl môže mať nasledujúce hodnoty:

typuštýl
číslocelé číslo, mena, percento, vlastný formát
dátumkrátky, stredný, dlhý, plný, vlastný formát
časkrátky, stredný, dlhý, plný, vlastný formát
výbervlastný formát

Názvy typov a štýlov hovoria zväčša samy za seba, ďalšie podrobnosti však môžeme nájsť v oficiálnej dokumentácii.

Pozrime sa však bližšie na vlastný formát.

V príklade vyššie sme použili nasledujúci formátový výraz:

{2, výber, 0 # žiadne správy | 1 # správa | 2 # dve správy | 2 <{2, number, integer} správy}

Štýl výberu má vo všeobecnosti formu volieb oddelených zvislou čiarou (alebo potrubím):

Vo vnútri možností hodnota zhody ki a reťazec vi sú oddelené znakom # okrem poslednej možnosti. Všimnite si, že do reťazca môžeme vložiť ďalšie vzory vi ako sme to urobili pre poslednú možnosť:

{2, výber, ... | 2 <{2, number, integer} správy}

Typ voľby je numerický, takže pre zhodné hodnoty existuje prirodzené usporiadanie ki ktoré delia číselný riadok na intervaly:

Ak dáme hodnotu k že patrí do intervalu [ki, ki + 1) (ľavý koniec je zahrnutý, pravý je vylúčený), potom hodnota vi je vybratá.

Zvážme podrobnejšie rozsahy zvoleného štýlu. Na tento účel použijeme tento vzorec:

pattern = "Máte" + "{0, výber, 0 # žiadne správy | 1 # správa | 2 # dve správy | 2 <{0, number, integer} správy}.";

a odovzdávať rôzne hodnoty pre svoj jedinečný zástupný symbol:

nspráva
-1, 0, 0.5Nemáte žiadne správy.
1, 1.5Máte správu.
2Máš dve správy.
2.5Máte 2 správy.
5Máte 5 správ.

4.3. Robiť veci lepšími

Teraz teda formátujeme naše správy. Samotná správa však zostáva pevne zakódovaná.

Z predchádzajúcej časti vieme, že by sme mali extrahovať reťazcové vzory do zdrojov. Aby sme oddelili naše obavy, vytvorme ďalšiu skupinu zdrojových súborov s názvom formáty:

V tých vytvoríme kľúč s názvom štítok s obsahom špecifickým pre jazyk.

Napríklad v anglickej verzii vložíme nasledujúci reťazec:

label = Dňa {0, date, full} {1} vám poslal + {2, choice, 0 # nič | 1 # správa | 2 # dve správy | 2 <{2, number, integer} správy}.

Francúzsku verziu by sme mali mierne upraviť z dôvodu nulového prípadu správy:

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} .

A podobné úpravy by sme museli urobiť aj v poľskej a talianskej verzii.

V skutočnosti poľská verzia vykazuje ešte ďalší problém. Podľa gramatiky poľského jazyka (a mnohých ďalších) musí sloveso súhlasiť v rode s predmetom. Tento problém by sme mohli vyriešiť použitím typu voľby, zvážme však iné riešenie.

4.4. JIS MessageFormat

Použime Medzinárodné komponenty pre Unicode (JIS). Už sme to spomenuli v našom návode na prevedenie prípadu z reťazca na názov. Jedná sa o vyspelé a široko používané riešenie, ktoré nám umožňuje prispôsobiť aplikáciu pre rôzne jazyky.

Tu to nebudeme skúmať úplne podrobne. Iba sa obmedzíme na to, čo naša aplikácia pre hračky potrebuje. Najkomplexnejšie a najaktuálnejšie informácie by sme mali nájsť na oficiálnych stránkach ICU.

V čase písania tohto článku bola najnovšia verzia ICU pre Javu (ICU4J) je 64,2. Ako obvykle, aby sme ho mohli začať používať, mali by sme ho pridať ako závislosť do nášho projektu:

 com.ibm.icu icu4j 64.2 

Predpokladajme, že chceme mať správne sformulované upozornenie v rôznych jazykoch a pre rôzne počty správ:

NAngličtinaPoľský
0Alica ti neposlala žiadne správy.

Bob vám neposlal žiadne správy.

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

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

1Alica ti poslala správu.

Bob vám poslal správu.

Alice wysłała ci wiadomość.

Bob wysłał ci wiadomość.

> 1Alica vám poslala N správ.

Bob vám poslal N správ.

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

Bob wysłał ci N wiadomości.

Najskôr by sme mali vytvoriť vzor v súboroch zdrojov špecifických pre miestne nastavenie.

Znova použijeme súbor formats.properties a pridať tam kľúč štítok-icu s nasledujúcim obsahom:

label-icu = {0} vám poslal + {2, množné číslo, = 0 {žiadne správy} = 1 {a message} + ďalšie {{2, number, integer} správy}}.

Obsahuje tri zástupné symboly, ktoré napájame vložením trojprvkového poľa:

Objekt [] data = nový Objekt [] {"Alice", "žena", 0}

Vidíme, že v anglickej verzii je zástupný symbol pre pohlavie k ničomu, zatiaľ čo v poľskej:

label-icu = {0} {2, plural, = 0 {nie} other {}} + {1, select, male {wysłał} female {wysłała} other {wysłało}} + ci {2, plural, = 0 { żadnych wiadomości} = 1 {wiadomość} + ďalšie {{2, number, integer} wiadomości}}.

používame ho na rozlíšenie wysłał / wysłała / wysłało.

5. Záver

V tejto príručke sme zvážili, ako lokalizovať a formátovať správy, ktoré demonštrujeme používateľom našich aplikácií.

Útržky kódu tohto tutoriálu sú ako vždy v našom úložisku GitHub.


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