Internacionalizacija i lokalizacija u Javi 8

1. Pregled

Internacionalizacija je postupak pripreme zahtjeva za podršku raznim jezičnim, regionalnim, kulturnim ili političkim podacima. To je bitan aspekt svake moderne višejezične aplikacije.

Za daljnje čitanje, trebali bismo znati da za internacionalizaciju postoji vrlo popularna kratica (vjerojatno popularnija od stvarnog naziva) - i18n zbog 18 slova između "i" i "n".

Za današnje programe poduzeća presudno je služiti ljudima iz različitih dijelova svijeta ili s više kulturnih područja. Različite kulturne ili jezične regije ne određuju samo opise specifične za jezik, već i valutu, zastupljenost broja, pa čak i različiti sastav datuma i vremena.

Na primjer, usredotočimo se na brojeve određene zemlje. Imaju razne decimalne i tisuću separatora:

  • 102.300,45 (Sjedinjene Države)
  • 102 300,45 (Poljska)
  • 102.300,45 (Njemačka)

Postoje i različiti formati datuma:

  • Ponedjeljak, 1. siječnja 2018. 15:20:34 CET (Sjedinjene Države)
  • lundi 1. siječnja 2018. 15 h 20 CET (Francuska).
  • 2018. 年 1 月 1 日 星期一 下午 03 时 20 分 34 秒 CET (Kina)

Štoviše, različite zemlje imaju jedinstvene simbole valuta:

  • 1.200,60 GBP (Ujedinjeno Kraljevstvo)
  • 1.200,60 € (Italija)
  • 1 200,60 € (Francuska)
  • 1200,60 američkih dolara (Sjedinjene Države)

Važnu činjenicu koju treba znati jest da čak i ako države imaju istu valutu i valutni simbol - poput Francuske i Italije - položaj njihovog valutnog simbola može biti drugačiji.

2. Lokalizacija

Unutar Jave imamo na raspolaganju fantastičnu značajku koja se zove Lokalno razred.

Omogućuje nam brzo razlikovanje kulturnih područja i prikladno formatiranje sadržaja. To je neophodno za proces internacionalizacije. Kao i i18n, i lokalizacija ima svoju kraticu - lnn.

Glavni razlog korištenja Lokalno je da se svim potrebnim oblikovanjima specifičnim za lokalizaciju može pristupiti bez ponovne kompilacije. Aplikacija može istovremeno rukovati s više lokalizacija, tako da je podrška novom jeziku jednostavna.

Lokale su obično predstavljene jezikom, državom i skraćenicom varijante odvojene podvlakom:

  • de (njemački)
  • it_CH (talijanski, Švicarska)
  • en_US_UNIX (Sjedinjene Države, UNIX platforma)

2.1. Polja

To smo već naučili Lokalno sastoji se od koda jezika, koda države i varijante. Postoje još dva moguća polja za postavljanje: skripta i proširenja.

Pogledajmo popis polja i vidjet ćemo koja su pravila:

  • Jezik može biti ISO 639 alfa-2 ili alfa-3 kod ili podoznaka registriranog jezika.
  • Regija (Država) je ISO 3166 alfa-2 pozivni broj države ili UN-broj-3 pozivni broj.
  • Varijanta je vrijednost osjetljiva na velika ili mala slova vrijednosti koja specificira varijaciju a Lokalno.
  • Skripta mora biti valjana ISO 15924 alfa-4 kodirati.
  • Proširenja je karta koja se sastoji od jednoznakovnih tipki i Niz vrijednosti.

Registar podznaka jezika IANA sadrži moguće vrijednosti za Jezik, regija, varijanta i skripta.

Ne postoji popis mogućih produženje vrijednosti, ali vrijednosti moraju biti dobro oblikovane BCP-47 podoznake. Ključevi i vrijednosti uvijek se pretvaraju u mala slova.

2.2. Locale.Builder

Postoji nekoliko načina stvaranja Lokalno predmeta. Jedan mogući način koristi Locale.Builder. Locale.Builder ima pet metoda postavljača koje možemo koristiti za izgradnju objekta i istodobno provjeru valjanosti tih vrijednosti:

Locale locale = new Locale.Builder () .setLanguage ("fr") .setRegion ("CA") .setVariant ("POSIX") .setScript ("Latn") .build ();

The Niz zastupanje navedenog Lokalno je fr_CA_POSIX_ # Latn.

Dobro je to znati podešavanje "varijante" može biti malo nezgodno jer nema službenog ograničenja na vrijednosti varijante, iako metoda postavljanja zahtijeva da se BCP-47 sukladan.

Inače će baciti IllformedLocaleException.

U slučaju da trebamo koristiti vrijednost koja ne prolazi provjeru valjanosti, možemo je koristiti Lokalno konstruktori jer ne provjeravaju vrijednosti.

2.3. Konstruktori

Lokalno ima tri konstruktora:

  • novi jezik (jezik žica)
  • novi jezik (jezik gudača, država sa žicama)
  • novi jezik (jezik niza, država niza, varijanta niza)

Konstruktor s 3 parametra:

Lokalni jezik = novi lokalni jezik ("pl", "PL", "UNIX");

Valjano varijanta mora biti a Niz od 5 do 8 alfanumeričkih brojeva ili pojedinačno numeričkih, a slijede 3 alfanumerička znaka. "UNIX" možemo primijeniti samo na varijanta polje samo putem konstruktora jer ne udovoljava tim zahtjevima.

Međutim, postoji jedan nedostatak upotrebe konstruktora za stvaranje Lokalno objekti - ne možemo postaviti ekstenzije i polja skripti.

2.4. Konstante

Ovo je vjerojatno najjednostavniji i najograničeniji način dobivanja Mjesta. The Lokalno klasa ima nekoliko statičkih konstanti koje predstavljaju najpopularniju zemlju ili jezik:

Lokale Japana = Locale.JAPAN; Locale japanese = Locale.JAPANESE;

2.5. Oznake jezika

Drugi način stvaranja Lokalno poziva statičku tvorničku metodu forLanguageTag (jezična oznaka niza). Ova metoda zahtijeva a Niz koji zadovoljava IETF BCP 47 standard.

Na ovaj način možemo stvoriti Ujedinjeno Kraljevstvo Lokalno:

Locale uk = Locale.forLanguageTag ("en-UK");

2.6. Dostupni jezici

Iako možemo stvoriti više kombinacija Lokalno objekte, možda ih nećemo moći koristiti.

Važna napomena koju morate biti svjesni je da Mjesta na platformi ovise o onima instaliranim u Java Runtime.

Kako mi koristimo Mjesta za formatiranje, različiti formativači mogu imati još manji skup Mjesta dostupni koji su instalirani u vrijeme izvođenja.

Provjerimo kako dohvatiti nizove dostupnih lokalizacija:

Locale [] numberFormatLocales = NumberFormat.getAvailableLocales (); Locale [] dateFormatLocales = DateFormat.getAvailableLocales (); Locale [] locales = Locale.getAvailableLocales ();

Nakon toga možemo provjeriti je li naš Lokalno prebiva među dostupnim Mjesta.

To bismo se trebali sjetiti skup dostupnih lokaliteta različit je za različite implementacije Java platformei razna područja funkcionalnosti.

Cjelovit popis podržanih lokaliteta dostupan je na web stranici Oracle Java SE Development Kit.

2.7. Zadana lokacija

Tijekom rada s lokalizacijom možda bismo trebali znati koja je zadana vrijednost Lokalno na naš JVM instanca je. Srećom, postoji jednostavan način za to:

Locale defaultLocale = Locale.getDefault ();

Također, možemo odrediti zadanu vrijednost Lokalno pozivanjem slične metode postavljača:

Locale.setDefault (Locale.CANADA_FRENCH);

Posebno je relevantno kada bismo željeli stvarati JUNIT testovi koji ne ovise o a JVM primjer.

3. Brojevi i valute

Ovaj se odjeljak odnosi na uređaje za oblikovanje brojeva i valuta koji bi trebali biti u skladu s različitim konvencijama specifičnim za lokalno područje.

Za formatiranje primitivnih vrsta brojeva (int, dvostruko) kao i njihovi objektni ekvivalenti (Cijeli broj, Dvostruko), trebali bismo koristiti Format broja razreda i njegove statičke tvorničke metode.

Zanimljive su nam dvije metode:

  • NumberFormat.getInstance (lokalno područje)
  • NumberFormat.getCurrencyInstance (lokalni jezik)

Ispitajmo uzorak koda:

Locale usLocale = Locale.US; dvostruki broj = 102300.456d; NumberFormat usNumberFormat = NumberFormat.getInstance (usLocale); assertEquals (usNumberFormat.format (broj), "102.300.456");

Kao što vidimo, jednostavno je poput stvaranja Lokalno i pomoću njega za dohvaćanje Format broja instanca i formatiranje broja uzorka. To možemo primijetiti izlaz uključuje decimalne i tisuću separatora specifičnih za lokalni jezik.

Evo još jednog primjera:

Locale usLocale = Locale.US; BigDecimal broj = novi BigDecimal (102_300.456d); NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance (usLocale); assertEquals (usNumberFormat.format (broj), "102.300,46 USD");

Formatiranje valute uključuje iste korake kao i formatiranje broja. Jedina je razlika u tome što formatter dodaje simbol valute i okrugli decimalni dio na dvije znamenke.

4. Datum i vrijeme

Sada ćemo saznati više o formatiranju datuma i vremena koje je vjerojatno složenije od formatiranja brojeva.

Prije svega, trebali bismo znati da se oblikovanje datuma i vremena značajno promijenilo u Javi 8 jer sadrži potpuno novo Datum vrijeme API. Stoga ćemo pregledati različite klase formatiranja.

4.1. DateTimeFormatter

Otkako je uvedena Java 8, glavna klasa za lokaliziranje datuma i vremena je DateTimeFormatter razred. Djeluje na klasama koje implementiraju TemporalAccessor sučelje, na primjer, LocalDateTime, LocalDate, LocalTime ili ZonedDateTime. Za stvaranje a DateTimeFormatter moramo pružiti barem obrazac, a zatim Lokalno. Pogledajmo primjer koda:

Locale.setDefault (Locale.US); LocalDateTime localDateTime = LocalDateTime.of (2018, 1, 1, 10, 15, 50, 500); Uzorak niza = "dd-MMMM-yyyy HH: mm: ss.SSS"; DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern (uzorak); DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern (uzorak, Locale.NJEMAČKA); assertEquals ("01. siječnja 2018. 10: 50: 50", defaultTimeFormatter.format (localDateTime)); assertEquals ("01. siječnja 2018. 10: 50: 50", deTimeFormatter.format (localDateTime));

To možemo vidjeti nakon dohvaćanja DateTimeFormatter sve što moramo učiniti je nazvati format() metoda.

Za bolje razumijevanje trebali bismo se upoznati s mogućim slovima s uzorcima.

Pogledajmo na primjer slova:

Simbol Značenje Primjeri prezentacije ------ ------- ------------ ------- godina 2004. godine; 04 M / L broj mjeseca u godini / tekst 7; 07; Srpnja; Srpanj; J d dan u mjesecu broj 10 H sat u danu (0-23) broj 0 m minut u satu broj 30 s sekundi u sekundi broj 55 S ulomak udjela sekunde 978

Sva moguća slova s ​​obrazloženjem mogu se naći u Java dokumentaciji za DateTimeFormatter.Vrijedno je znati da konačna vrijednost ovisi o broju simbola. U primjeru postoji 'MMMM' koji ispisuje puni naziv mjeseca, dok bi jedno slovo 'M' davalo broj mjeseca bez vodeće 0.

Da završim dalje DateTimeFormatter, da vidimo kako možemo formatirati LocalizedDateTime:

LocalDateTime localDateTime = LocalDateTime.of (2018, 1, 1, 10, 15, 50, 500); ZoneId losAngelesTimeZone = TimeZone.getTimeZone ("America / Los_Angeles"). ToZoneId (); DateTimeFormatter localizedTimeFormatter = DateTimeFormatter .ofLocalizedDateTime (FormatStyle.FULL); Niz formattedLocalizedTime = localizedTimeFormatter.format (ZonedDateTime.of (localDateTime, losAngelesTimeZone)); assertEquals ("Ponedjeljak, 1. siječnja 2018. 10:15:50 PST", formattedLocalizedTime);

Kako bi formatirali LocalizedDateTime, možemo koristiti ofLocalizedDateTime (FormatStyle dateTimeStyle) metodu i pružiti unaprijed definiranu FormatStyle.

Za dublji uvid u Javu 8 Datum vrijeme API, ovdje imamo postojeći članak.

4.2. Oblik datuma i SimpleDateFormatter

Kako je još uvijek uobičajeno raditi na projektima koji se koriste Datumi i Kalendari, ukratko ćemo predstaviti mogućnosti formatiranja datuma i vremena pomoću Oblik datuma i SimpleDateFormat razreda.

Analizirajmo sposobnosti prvog:

GregorianCalendar gregorianCalendar = novi GregorianCalendar (2018, 1, 1, 10, 15, 20); Datum datum = gregorianCalendar.getTime (); DateFormat ffInstance = DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.ITALY); DateFormat smInstance = DateFormat.getDateTimeInstance (DateFormat.SHORT, DateFormat.MEDIUM, Locale.ITALY); assertEquals ("giovedì 1. veljače 2018. 10.15.20 CET", ffInstance.format (datum)); assertEquals ("02.02.18. 10.15.20", smInstance.format (datum));

Oblik datuma radi s Datumi i ima tri korisne metode:

  • getDateTimeInstance
  • getDateInstance
  • getTimeInstance

Svi oni uzimaju unaprijed definirane vrijednosti Oblik datuma kao parametar. Svaka metoda je preopterećena, pa prolazi Lokalno je također moguće. Ako želimo koristiti prilagođeni obrazac, kao što je to učinjeno u DateTimeFormatter, možemo koristiti SimpleDateFormat. Pogledajmo kratki isječak koda:

GregorianCalendar gregorianCalendar = novi GregorianCalendar (2018, 1, 1, 10, 15, 20); Datum datum = gregorianCalendar.getTime (); Locale.setDefault (novi Locale ("pl", "PL")); SimpleDateFormat fullMonthDateFormat = novi SimpleDateFormat ("dd-MMMM-yyyy HH: mm: ss: SSS"); SimpleDateFormat shortMonthsimpleDateFormat = novi SimpleDateFormat ("dd-MM-yyyy HH: mm: ss: SSS"); assertEquals ("01-lutego-2018 10: 15: 20: 000", fullMonthDateFormat.format (datum)); assertEquals ("02.02.2018 10: 15: 20: 000", shortMonthsimpleDateFormat.format (datum));

5. Prilagođavanje

Zbog nekih dobrih dizajnerskih odluka nismo vezani uz obrazac oblikovanja specifični za određeni lokalitet i možemo konfigurirati gotovo svaki detalj tako da bude u potpunosti zadovoljan izlazom.

Da bismo prilagodili oblikovanje brojeva, možemo koristiti DecimalFormat i DecimalFormatSymbols.

Razmotrimo kratki primjer:

Locale.setDefault (Locale.FRANCE); BigDecimal broj = novi BigDecimal (102_300.456d); DecimalFormat zeroDecimalFormat = novi DecimalFormat ("000000000.0000"); DecimalFormat dollarDecimalFormat = novi DecimalFormat ("$ ###, ###. ##"); assertEquals (zeroDecimalFormat.format (broj), "000102300,4560"); assertEquals (dollarDecimalFormat.format (broj), "102 300,46 USD"); 

The DecimalFormat dokumentacija prikazuje sve moguće znakove uzorka. Sve što sada moramo znati je da "000000000.000" određuje vodeće ili prateće nule, "," je tisuću separatora i "." je decimalni jedan.

Također je moguće dodati simbol valute. U nastavku možemo vidjeti da se isti rezultat može postići uporabom DateFormatSymbol razred:

Locale.setDefault (Locale.FRANCE); BigDecimal broj = novi BigDecimal (102_300.456d); DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance (); decimalFormatSymbols.setGroupingSeparator ('^'); decimalFormatSymbols.setDecimalSeparator ('@'); DecimalFormat separatorsDecimalFormat = novi DecimalFormat ("$ ###, ###. ##"); separatorsDecimalFormat.setGroupingSize (4); separatorsDecimalFormat.setCurrency (Currency.getInstance (Locale.JAPAN)); separatorsDecimalFormat.setDecimalFormatSymbols (decimalFormatSymbols); assertEquals (separatorsDecimalFormat.format (number), "$ 10 ^ [email protected]");

Kao što vidimo, DecimalFormatSymbols klasa omogućuje nam da odredimo bilo koje oblikovanje brojeva koje možemo zamisliti.

Za prilagodbu SimpleDataFormat, možemo koristiti DateFormatSymbols.

Pogledajmo kako je jednostavna promjena imena dana:

Datum datum = novi GregorianCalendar (2018, 1, 1, 10, 15, 20) .getTime (); Locale.setDefault (novi Locale ("pl", "PL")); DateFormatSymbols dateFormatSymbols = novi DateFormatSymbols (); dateFormatSymbols.setWeekdays (novi niz [] {"A", "B", "C", "D", "E", "F", "G", "H"}); SimpleDateFormat newDaysDateFormat = novi SimpleDateFormat ("EEEE-MMMM-yyyy HH: mm: ss: SSS", dateFormatSymbols); assertEquals ("F-lutego-2018 10: 15: 20: 000", newDaysDateFormat.format (datum));

6. Paketi resursa

Konačno, presudni dio internacionalizacije u Europi JVM je Paket resursa mehanizam.

Svrha a ResourceBundle je pružanje aplikacije s lokaliziranim porukama / opisima koji se mogu eksternalizirati u zasebne datoteke. U jednom od naših prethodnih članaka - vodiču za Resource Bundle pokrivamo upotrebu i konfiguraciju Resource Bundlea.

7. Zaključak

Mjesta a formativači koji ih koriste alati su koji nam pomažu u stvaranju internacionalizirane aplikacije. Ovi nam alati omogućuju stvaranje aplikacije koja se može dinamički prilagoditi korisnikovim jezičnim ili kulturnim postavkama bez višestrukih izrada ili čak potrebe za brigom o tome podržava li Java Lokalno.

U svijetu u kojem korisnik može biti bilo gdje i govoriti bilo koji jezik, sposobnost primjene ovih promjena znači da naše aplikacije mogu biti intuitivnije i razumljivije većem broju korisnika na globalnoj razini.

Kada radimo s aplikacijama Spring Boot, imamo i prikladan članak o internacionalizaciji Spring Boot.

Izvorni kod ovog vodiča, s cjelovitim primjerima, možete pronaći na GitHub-u.


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