Nemzetközivé válás és lokalizáció a Java 8-ban

1. Áttekintés

Az internacionalizáció egy különféle nyelvi, regionális, kulturális vagy politikai jellegű adatok támogatására szolgáló alkalmazás előkészítésének folyamata. Ez egy elengedhetetlen szempont minden modern többnyelvű alkalmazásban.

További olvasmányként, tudnunk kell, hogy a nemzetközivé válásnak van egy nagyon népszerű rövidítése (valószínűleg népszerűbb, mint a tényleges neve) - i18n az „i” és az „n” közötti 18 betű miatt.

Döntő jelentőségű, hogy a mai vállalati programok a világ különböző részeiről vagy több kulturális területről származó embereket szolgálják ki. A megkülönböztetett kulturális vagy nyelvi régiók nemcsak a nyelvspecifikus leírásokat határozzák meg, hanem a pénznemet, a számok képviseletét, sőt a dátum és az idő összetételét is eltérőek.

Koncentráljunk például az országspecifikus számokra. Különböző tizedes és ezer elválasztójuk van:

  • 102,300,45 (Egyesült Államok)
  • 102 300,45 (Lengyelország)
  • 102.300,45 (Németország)

Különböző dátumformátumok is léteznek:

  • 2018. január 1., hétfő 15:20:34 CET (Egyesült Államok)
  • lundi 2018. január 1., 15 óra 20 CET (Franciaország).
  • 2018. január 1., 2014. március 20., CET (Kína)

Sőt, a különböző országokban egyedi valuta szimbólumok vannak:

  • 1200,60 font (Egyesült Királyság)
  • 1.200,60 € (Olaszország)
  • 1 200,60 € (Franciaország)
  • 1200,60 USD (Egyesült Államok)

Fontos tudnivaló, hogy még akkor is, ha az országoknak ugyanaz a pénzneme és valutaszimbóluma van - mint Franciaországnak és Olaszországnak -, a valutaszimbólumuk helyzete eltérő lehet.

2. Lokalizáció

A Java-n belül egy fantasztikus szolgáltatás áll a rendelkezésünkre, az úgynevezett Területi beállítás osztály.

Ez lehetővé teszi számunkra a kulturális helyek gyors megkülönböztetését és a tartalom megfelelő formázását. Ez elengedhetetlen a nemzetköziesedési folyamaton belül. Ugyanaz, mint az i18n, a lokalizációnak is megvan a rövidítése - l10n.

A használat fő oka Területi beállítás az, hogy minden szükséges területi beállítás-specifikus formázás újrafordítás nélkül elérhető. Egy alkalmazás egyszerre több lokált is képes kezelni, így az új nyelv támogatása egyszerű.

A területi beállításokat általában nyelv, ország és változatok rövidítése ábrázolja aláhúzással elválasztva:

  • de (német)
  • it_CH (olasz, Svájc)
  • en_US_UNIX (Egyesült Államok, UNIX platform)

2.1. Mezők

Ezt már megtanultuk Területi beállítás nyelvi kódból, országkódból és változatból áll. Két további mező állítható be: szkript és kiterjesztések.

Vizsgáljuk meg a mezők listáját, és nézzük meg, melyek a szabályok:

  • Nyelv lehet egy ISO 639 alfa-2 vagy alfa-3 kód vagy regisztrált nyelvű alcímke.
  • Vidék (Ország) van ISO 3166 alfa-2 országkód vagy ENSZ numerikus-3 körzetszám.
  • Változat a kis- és nagybetűk megkülönböztető értéke vagy az a változatot meghatározó értékkészlet Területi beállítás.
  • Forgatókönyv érvényesnek kell lennie ISO 15924 alfa-4 kód.
  • Hosszabbítások egy térkép, amely egy karakteres billentyűkből és Húr értékek.

Az IANA nyelv alcímke-nyilvántartása a (z) domain lehetséges értékeit tartalmazza nyelv, vidék, változat és forgatókönyv.

Nincs lista a lehetségesekről kiterjesztés értékeket, de az értékeknek jól kell formálódniuk BCP-47 alcímkék. A kulcsokat és az értékeket mindig kisbetűvé alakítják.

2.2. Locale.Builder

Az alkotásnak többféle módja van Területi beállítás tárgyakat. Az egyik lehetséges módszer hasznosítja Locale.Builder. Locale.Builder öt szetter módszerrel rendelkezik, amelyekkel felépíthetjük az objektumot, és ugyanakkor érvényesíthetjük ezeket az értékeket:

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

A Húr a fentiek ábrázolása Területi beállítás van fr_CA_POSIX_ # Latn.

Jó ezt tudni A „variáns” beállítása kissé bonyolult lehet, mivel a variánsokra nincs hivatalos korlátozás, bár a szetter módszer megköveteli BCP-47 megfelelõ.

Ellenkező esetben dobni fog IllformedLocaleException.

Abban az esetben, ha olyan értéket kell használnunk, amely nem felel meg az érvényesítésnek, használhatjuk Területi beállítás konstruktorok, mivel nem validálják az értékeket.

2.3. Kivitelezők

Területi beállítás három kivitelezője van:

  • új nyelv (karakterlánc)
  • új nyelv (sztring nyelv, sztring ország)
  • új területi beállítás (karakterlánc nyelv, karakterlánc ország, karakterlánc változat)

3 paraméterű konstruktor:

Locale locale = new Locale ("pl", "PL", "UNIX");

Egy érvényes változat kell lennie a Húr 5–8 alfanumerikus szám vagy egyetlen számjegy, amelyet 3 alfanumerikus szám követ. Csak a „UNIX” -t alkalmazhatjuk a változat csak konstruktoron keresztül, mivel nem felel meg ezeknek a követelményeknek.

Van azonban egy hátránya a konstruktorok létrehozásának Területi beállítás objektumok - nem állíthatunk be kiterjesztéseket és szkriptmezőket.

2.4. Állandóak

Valószínűleg ez a legegyszerűbb és legkorlátozottabb módja a megszerzésnek Nyelvek. A Területi beállítás osztálynak több statikus állandója van, amelyek a legnépszerűbb országot vagy nyelvet képviselik:

Japán területi beállítás = locale.JAPAN; Japán nyelv = Locale.JAPÁN;

2.5. Nyelvcímkék

Az alkotás másik módja Területi beállítás meghívja a statikus gyári módszert forLanguageTag (String languageTag). Ehhez a módszerhez a Húr hogy megfelel a IETF BCP 47 alapértelmezett.

Így hozhatjuk létre az Egyesült Királyságot Területi beállítás:

Uk nyelv = Locale.forLanguageTag ("en-UK");

2.6. Elérhető nyelvek

Annak ellenére, hogy többféle kombinációt hozhatunk létre Területi beállítás tárgyakat, lehet, hogy nem tudjuk használni.

Fontos tudnivaló, hogy a Nyelvek A platformok függenek a Java Runtime alatt telepítettektől.

Ahogy használjuk Nyelvek a formázáshoz a különböző formázóknak még kisebb lehet a készletük Nyelvek elérhetőek, amelyek telepítve vannak a futásidejében.

Ellenőrizzük, hogyan lehet lekérni az elérhető lokációk tömbjét:

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

Ezt követően ellenőrizhetjük, hogy a mi Területi beállítás elérhetőek között lakik Nyelvek.

Erre emlékeznünk kellene az elérhető nyelvkészletek halmaza eltér a Java Platform különböző megvalósításaihozés a funkcionalitás különféle területei.

A támogatott nyelvek teljes listája elérhető az Oracle Java SE Development Kit weboldalán.

2.7. Alapértelmezett területi beállítás

A lokalizálás során tudnunk kell, hogy mi az alapértelmezett Területi beállítás miénken JVM példány az. Szerencsére erre van egy egyszerű módszer:

Locale defaultLocale = Locale.getDefault ();

Megadhatunk alapértelmezett értéket is Területi beállítás hasonló szetter módszer meghívásával:

Locale.setDefault (Locale.CANADA_FRENCH);

Különösen akkor releváns, amikor szeretnénk alkotni JUnit tesztek, amelyek nem függenek a JVM példa.

3. Számok és pénznemek

Ez a szakasz olyan számokra és pénznem formázókra vonatkozik, amelyeknek meg kell felelniük a különböző területi beállításokra.

A primitív számtípusok formázása (int, kettős), valamint tárgyegyenértékeik (Egész szám, Kettős), akkor használnunk kell NumberFormat osztály és statikus gyári módszerei.

Két módszer érdekes számunkra:

  • NumberFormat.getInstance (locale locale)
  • NumberFormat.getCurrencyInstance (locale locale)

Vizsgáljuk meg a mintakódot:

Locale usLocale = Locale.US; kettős szám = 102300.456d; NumberFormat usNumberFormat = NumberFormat.getInstance (usLocale); assertEquals (usNumberFormat.format (szám), "102,300,456");

Mint láthatjuk, ez olyan egyszerű, mint létrehozni Területi beállítás és visszakeresésére használja NumberFormat példány és mintaszám formázása. Ezt észrevehetjük a kimenet tartalmazza a lokálspecifikus decimális és ezer elválasztót.

Itt van egy másik példa:

Locale usLocale = Locale.US; BigDecimal szám = új BigDecimal (102_300.456d); NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance (usLocale); assertEquals (usNumberFormat.format (szám), "$ 102,300,46");

A pénznem formázása ugyanazokkal a lépésekkel jár, mint egy szám formázása. Az egyetlen különbség az, hogy a formázó a pénznem szimbólumot és a kerek tizedes részt két számjegyhez fűzi.

4. Dátum és idő

Most megismerkedünk a dátumok és idők formázásával, amely valószínűleg összetettebb, mint a számok formázása.

Először is tudnunk kell, hogy a dátum és idő formázása jelentősen megváltozott a Java 8-ban, mivel teljesen újat tartalmaz Dátum idő API. Ezért különböző formázó osztályokat fogunk átnézni.

4.1. DateTimeFormatter

A Java 8 bevezetése óta a dátumok és idők lokalizálásának fő osztálya a DateTimeFormatter osztály. Olyan osztályokon működik, amelyek megvalósítják TemporalAccessor interfész, például LocalDateTime, LocalDate, LocalTime vagy ZonedDateTime. A DateTimeFormatter legalább mintát kell adnunk, majd Területi beállítás. Lássunk egy példakódot:

Locale.setDefault (Locale.US); LocalDateTime localDateTime = LocalDateTime.of (2018, 1, 1, 10, 15, 50, 500); Karakterlánc = "dd-MMMM-yyyy HH: mm: ss.SSS"; DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern (minta); DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern (minta, Locale.GERMANY); assertEquals ("2018. január 01. 10: 15: 50.000", defaultTimeFormatter.format (localDateTime)); assertEquals ("2018. január 01. 10: 15: 50.000", deTimeFormatter.format (localDateTime));

Ezt a visszakeresés után láthatjuk DateTimeFormatter csak annyit kell tennünk, hogy felhívjuk a formátum() módszer.

A jobb megértés érdekében meg kell ismerkednünk a lehetséges mintabetűkkel.

Nézzük például a betűket:

Szimbólum Jelentés Példák bemutatásra ------ ------- ------------ ------- y 2004-es év; 04 M / L az év hónapjának száma / szöveg 7; 07; Július; Július; J d a hónap napjának száma 10 H a nap órájának száma (0-23) száma 0 m az óra percének száma 30 s a perc második másodpercének száma 55 S a másodperc törtrésze 978

Az összes lehetséges minta betű magyarázattal megtalálható a Java dokumentációjában DateTimeFormatter.Érdemes tudni, hogy a végső érték a szimbólumok számától függ. A példában szerepel az „MMMM”, amely a teljes hónap nevét nyomtatja ki, míg egyetlen „M” betű a 0 szám nélküli előlapot adja meg a hónap számának.

Hogy befejezzem DateTimeFormatter, nézzük meg, hogyan tudjuk formázni LocalizedDateTime:

LocalDateTime localDateTime = LocalDateTime.of (2018, 1, 1, 10, 15, 50, 500); ZoneId losAngelesTimeZone = TimeZone.getTimeZone ("Amerika / Los_Angeles"). ToZoneId (); DateTimeFormatter localizedTimeFormatter = DateTimeFormatter .ofLocalizedDateTime (FormatStyle.FULL); String formattedLocalizedTime = localizedTimeFormatter.format (ZonedDateTime.of (localDateTime, losAngelesTimeZone)); assertEquals ("2018. január 1., hétfő, 10:15:50 PST", formattedLocalizedTime);

A formázás érdekében LocalizedDateTime, használhatjuk a ofLocalizedDateTime (FormatStyle dateTimeStyle) módszerrel és egy előre definiált FormatStyle.

A Java 8 részletesebb áttekintéséhez Dátum idő API, van egy létező cikkünk itt.

4.2. Dátum formátum és SimpleDateFormatter

Mivel még mindig gyakori, hogy olyan projekteken dolgozunk, amelyek kihasználják ezeket Dátumok és Naptárak, röviden bemutatjuk a dátumok és idők formázásának képességeit Dátum formátum és SimpleDateFormat osztályok.

Elemezzük az első képességeit:

GregorianCalendar gregorianCalendar = új GregorianCalendar (2018, 1, 1, 10, 15, 20); Dátum dátum = gregorianCalendar.getTime (); DateFormat ffInstance = DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.ITALY); DateFormat smInstance = DateFormat.getDateTimeInstance (DateFormat.SHORT, DateFormat.MEDIUM, Locale.ITALY); assertEquals ("2018. február 1, 20:15 CET", ffInstance.format (dátum)); assertEquals ("18/02/18 10.15.20", smInstance.format (dátum));

Dátum formátum dolgozni valakivel Dátumok és három hasznos módszere van:

  • getDateTimeInstance
  • getDateInstance
  • getTimeInstance

Mindegyikük előre definiált értékeket vesz fel Dátum formátum paraméterként. Mindegyik módszer túlterhelt, tehát áthaladó Területi beállítás lehetséges is. Ha egyéni mintát akarunk használni, amint az megtörtént DateTimeFormatter, tudjuk használni SimpleDateFormat. Lássunk egy rövid kódrészletet:

GregorianCalendar gregorianCalendar = új GregorianCalendar (2018, 1, 1, 10, 15, 20); Dátum dátum = gregorianCalendar.getTime (); Locale.setDefault (új Locale ("pl", "PL")); SimpleDateFormat fullMonthDateFormat = new SimpleDateFormat ("dd-MMMM-yyyy HH: mm: ss: SSS"); SimpleDateFormat shortMonthsimpleDateFormat = új SimpleDateFormat ("éééé-hh-éééé ÓÓ: hp: ss: SSS"); assertEquals ("01-lutego-2018 10: 15: 20: 000", fullMonthDateFormat.format (dátum)); assertEquals ("2018.02.01. 10: 15: 20: 000", shortMonthsimpleDateFormat.format (dátum));

5. Testreszabás

Néhány jó tervezési döntés miatt nem vagyunk hozzákötve egy lokálspecifikus formázási mintához, és szinte minden részletet úgy konfigurálhatunk, hogy teljes mértékben elégedettek legyenek egy kimenettel.

A számformázás testreszabásához használhatjuk DecimalFormat és DecimalFormatSymbols.

Vegyünk egy rövid példát:

Locale.setDefault (Locale.FRANCE); BigDecimal szám = új BigDecimal (102_300.456d); DecimalFormat zeroDecimalFormat = new DecimalFormat ("000000000.0000"); DecimalFormat dollarDecimalFormat = new DecimalFormat ("$ ###, ###. ##"); assertEquals (zeroDecimalFormat.format (szám), "000102300,4560"); assertEquals (dollarDecimalFormat.format (szám), "102 USD 300,46"); 

A DecimalFormat a dokumentáció az összes lehetséges minta karaktert megjeleníti. Most csak annyit kell tudnunk, hogy a „000000000.000” meghatározza a kezdő vagy a záró nullákat, a ’,’ ezer elválasztó és ’. tizedes.

Lehetőség van pénznem szimbólum hozzáadására is. Az alábbiakban láthatjuk, hogy ugyanaz az eredmény érhető el a használatával DateFormatSymbol osztály:

Locale.setDefault (Locale.FRANCE); BigDecimal szám = új BigDecimal (102_300.456d); DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance (); decimalFormatSymbols.setGroupingSeparator ('^'); decimalFormatSymbols.setDecimalSeparator ('@'); DecimalFormat separatorsDecimalFormat = new DecimalFormat ("$ ###, ###. ##"); separatorsDecimalFormat.setGroupingSize (4); separatorsDecimalFormat.setCurrency (Currency.getInstance (Locale.JAPAN)); separatorsDecimalFormat.setDecimalFormatSymbols (decimalFormatSymbols); assertEquals (separatorsDecimalFormat.format (szám), "$ 10 ^ [e-mail védett]");

Ahogy látjuk, DecimalFormatSymbols osztály lehetővé teszi számunkra, hogy megadhassunk bármilyen számformátumot, amit csak elképzelhetünk.

Testreszabásához SimpleDataFormat, tudjuk használni DateFormatSymbols.

Lássuk, milyen egyszerű a napok nevének megváltoztatása:

Dátum dátuma = új GregorianCalendar (2018, 1, 1, 10, 15, 20) .getTime (); Locale.setDefault (új Locale ("pl", "PL")); DateFormatSymbols dateFormatSymbols = new DateFormatSymbols (); dateFormatSymbols.setWeekdays (új karakterlánc [] {"A", "B", "C", "D", "E", "F", "G", "H"}); SimpleDateFormat newDaysDateFormat = new SimpleDateFormat ("EEEE-MMMM-éééé ÓÓ: h: mm: ss: SSS", dateFormatSymbols); assertEquals ("F-lutego-2018 10: 15: 20: 000", newDaysDateFormat.format (dátum));

6. Erőforráscsomagok

Végül, a nemzetközivé válás döntő része a JVM az a Erőforráscsomag gépezet.

A célja a ResourceBundle egy alkalmazás biztosítása lokalizált üzenetekkel / leírásokkal, amelyek külsõvé tehetõk a különálló fájlokra. Az erőforráscsomag használatáról és konfigurálásáról az egyik korábbi cikkünkben foglalkozunk - útmutató az erőforráscsomaghoz.

7. Következtetés

Nyelvek és az ezeket használó formázók olyan eszközök, amelyek segítenek a nemzetközivé vált alkalmazás létrehozásában. Ezek az eszközök lehetővé teszik számunkra, hogy olyan alkalmazást hozzunk létre, amely dinamikusan képes alkalmazkodni a felhasználó nyelvi vagy kulturális beállításaihoz anélkül, hogy többszörös felépítés lenne, vagy akár aggódnunk kellene attól, hogy a Java támogatja-e a Területi beállítás.

Egy olyan világban, ahol a felhasználó bárhol tartózkodhat és bármilyen nyelvet beszélhet, e változások alkalmazásának képessége azt jelenti, hogy alkalmazásunk világszerte több felhasználó számára érthetőbb és érthetőbb.

Amikor a Spring Boot alkalmazással dolgozunk, van egy kényelmes cikkünk is a Spring Boot Internationalization-hez.

Ennek az oktatóanyagnak a teljes példákkal ellátott forráskódja megtalálható a GitHub oldalon.