En guide til ResourceBundle

1. Oversigt

Mange softwareudviklere står i deres professionelle karriere over for en mulighed for at udvikle flersprogede systemer eller applikationer. Disse er normalt beregnet til slutbrugere fra forskellige regioner eller forskellige sprogområder.

Det er altid udfordrende at vedligeholde og udvide disse applikationer. En evne til at operere med forskellige lokaliseringsspecifikke data på samme tid er normalt afgørende. Ændring af applikationsdataene skal være så enkle som muligt uden behov for rekompilering. Derfor undgår vi generelt hardcoding-etiket- eller knapnavne.

Heldigvis kan vi bankere på Java, der giver os denne klasse, som hjælper os med at løse alle de ovennævnte problemer.

Kort sagt, den ResourceBundle gør det muligt for vores applikation at indlæse data fra forskellige filer, der indeholder landespecifikke data.

1.1. ResourceBundles

Den første ting, vi skal vide, er, at alle filer i en ressourcepakke skal være i samme pakke / bibliotek og have et fælles basisnavn. De kan have landespecifikke suffikser, der angiver sprog, land eller platform adskilt med understregningssymbol.

Det er vigtigt, at vi kan tilføje landekode, hvis der allerede er sprogkode, eller platform, hvis sprog og landekoder er til stede.

Lad os se på eksempler på filnavne:

  • EksempelRessource
  • EksempelResource_en
  • ExampleResource_en_US
  • EksempelResource_en_US_UNIX

Standardfilen for hver datapakke er altid en uden suffikser - EksempelRessource. Da der er to underklasser af ResourceBundle: PropertyResourceBundle og ListResourceBundle, kan vi ombytteligt gemme data i ejendomsfiler såvel som java-filer.

Hver fil skal have et landespecifikt navn og en korrekt filtypenavn, for eksempel, ExampleResource_en_US.properties eller Eksempel_da.java.

1.2. Ejendomsfiler - PropertyResourceBundle

Ejendomsfiler er repræsenteret af PropertyResourceBundle. De gemmer data i form af store og små bogstaver med nøgleværdi.

Lad os analysere en eksempelfastighedsfil:

# Buttons continueButton fortsæt cancelButton = annuller! Etiketter hej Etiket: hej 

Som vi kan se, er der tre forskellige stilarter til at definere nøgleværdipar.

Alle er ækvivalente, men den første er sandsynligvis den mest populære blandt Java programmører. Det er værd at vide, at vi også kan placere kommentarer i ejendomsfiler. Kommentarer starter altid med # eller !.

1.3. Java-filer - ListResourceBundle

Først og fremmest er vi nødt til at oprette en klasse, der udvides for at gemme vores sprogspecifikke data ListResourceBundle og tilsidesætter getContents () metode. Klassens navnekonvention er den samme som for ejendomsfiler.

For hver Lokalitet, vi er nødt til at oprette separat Java-klasse.

Her er en prøveklasse:

offentlig klasse ExampleResource_pl_PL udvider ListResourceBundle {@Override beskyttet objekt [] [] getContents () {returner nyt objekt [] [] {{"valuta", "polsk zloty"}, {"toUsdRate", nyt BigDecimal ("3.401")} , {"byer", ny streng [] {"Warszawa", "Krakow"}}}; }}

Java-filer har en stor fordel i forhold til ejendomsfiler, hvilket er en mulighed for at holde ethvert objekt, vi ønsker - ikke kun Strenge.

På den anden side kræver hver ændring eller introduktion af en ny locale-specifik java-klasse genkompilering af et program, mens ejendomsfiler kan udvides uden yderligere indsats.

2. Brug ressourcepakker

Vi ved allerede, hvordan vi definerer ressourcegrupper, så vi er klar til at bruge den.

Lad os overveje det korte kodestykke:

Lokal lokalitet = ny lokal ("pl", "PL"); ResourceBundle eksempelBundle = ResourceBundle.getBundle ("package.ExampleResource", landestandard); assertEquals (eksempelBundle.getString ("valuta"), "polsk zloty"); assertEquals (eksempelBundle.getObject ("toUsdRate"), ny BigDecimal ("3.401")); assertArrayEquals (eksempelBundle.getStringArray ("byer"), ny streng [] {"Warszawa", "Krakow"});

For det første kan vi definere vores Lokal, medmindre vi ikke vil bruge standard.

Lad os derefter kalde en statisk fabriksmetode for ResourceBundle. Vi skal passere bundtnavnet med dets pakke / bibliotek og locale som parametre.

Der er også en fabriksmetode, der kun kræver et bundtnavn, hvis standardsprog er fint. Så snart vi har objektet, kan vi hente værdier ved hjælp af deres nøgler.

Derudover viser eksemplet, at vi kan bruge getString (strengnøgle), getObject (strengnøgle), og getStringArray (strengnøgle) for at få de værdier, vi ønsker.

3. Valg af den korrekte pakkeressource

Hvis vi vil bruge en bundteressource, er det vigtigt at vide hvordan Java vælger bundtfiler.

Lad os forestille os, at vi arbejder med et program, der har brug for etiketter på polsk, men din standard JVM lokalitet er Locale.US.

I begyndelsen vil applikationen søge efter filerne i klassestien, der passer til det sted, du beder om. Det starter med det mest specifikke navn, det vil sige et, der indeholder en platform, et land og sprog.

Derefter går det til mere generelt. Hvis der ikke er noget match, falder det tilbage til standardområdet uden platformskontrol denne gang.

Hvis der ikke er nogen match, forsøger den at læse standardpakken. Alt skal være klart, når vi ser på rækkefølgen af ​​valgte filnavne:

  • Label_pl_PL_UNIX
  • Etiket_pl_PL
  • Label_pl
  • Label_en_US
  • Label_en
  • Etiket

Vi skal huske på, at hvert navn repræsenterer begge dele .java og .ejendomme filer, men førstnævnte har forrang for sidstnævnte. Når der ikke er nogen passende fil, a MissingResourceException kastes.

4. Arv

En anden fordel ved ressourcebundtkonceptet er ejendomsarv. Det betyder, at nøgleværdipar, der er inkluderet i mindre specifikke filer, arves af dem, der er højere i arvtræet.

Lad os antage, at vi har tre egenskabsfiler:

# resource.properties cancelButton = annuller # resource_pl.properties continueButton = dalej # resource_pl_PL.properties backButton = cofnij

Ressourcegruppe hentet til Lokal ("pl", "PL") returnerer alle tre nøgler / værdier i resultatet. Det er værd at nævne, der er ikke noget tilbage til standard locale-pakke så vidt ejendomsarv overvejes.

Hvad er mere, ListResourceBundles og PropertyResourceBundles er ikke i det samme hierarki.

Så hvis der findes en egenskabsfil på klassestien, arves nøgleværdipar kun fra egenskabsfiler. Den samme regel gælder for Java-filer.

5. Tilpasning

Alt, hvad vi har lært ovenfor, handlede om standardimplementeringen af ResourceBundle. Der er dog en måde, vi kan ændre dens adfærd på.

Vi gør dette ved at udvide ResourceBoundle.Control og tilsidesætter dens metoder.

For eksempel kan vi ændre tidspunktet for opbevaring af værdier i cachen eller bestemme tilstanden, hvornår cachen skal genindlæses.

Lad os forberede en kort metode som et eksempel for en bedre forståelse:

offentlig klasse ExampleControl udvider ResourceBundle.Control {@Override public List getCandidateLocales (String s, Locale locale) {return Arrays.asList (new Locale ("pl", "PL")); }}

Formålet med denne metode er at ændre en måde at vælge filer på klassestien på. Som vi kan se, Eksempelkontrol returnerer kun polsk Lokal, uanset hvilken standard eller defineret Lokal er.

6. UTF-8

Da der stadig er mange applikationer, der bruger JDK 8 eller ældre versioner, er det værd at vide det før Java 9ListResourceBundles havde en fordel mere end PropertyResourceBundles. Da Java-filer kan gemme strengobjekter, er de i stand til at holde ethvert tegn, der understøttes af UTF-16 indkodning.

Tværtimod, PropertyResourceBundle indlæser filer som standard ved hjælp af ISO 8859-1 kodning, som har færre tegn end UTF-8 (forårsager problemer for vores polske sprogeksempler).

For at gemme tegn, der er ud over UTF-8, kan vi bruge Native-To-ASCII konverter - native2ascii. Det konverterer alle tegn, der ikke er i overensstemmelse med ISO 8859-1 ved at kode dem til \ uxxxx notation.

Her er et eksempel på en kommando:

native2ascii-kodning UTF-8 utf8.properties nonUtf8.properties

Og lad os se, hvordan egenskaber ser ud før og efter en ændring af kodning:

# Før polskHello = cześć # Efter polskHello = cze \ u015b \ u0107

Heldigvis findes denne ulempe ikke længere i Java 9. JVM læser ejendomsfiler i UTF-8 kodning, og der er ikke noget problem i at bruge ikke-latinske tegn.

7. Konklusion

BundleResource indeholder meget af det, vi har brug for til at udvikle en flersproget applikation. De funktioner, vi har dækket, gør manipulation af forskellige lokaliteter ret ligetil.

Vi undgår også hardcoding-værdier, hvilket giver os mulighed for at udvide det understøttede Lokale ved blot at tilføje nyt Lokal filer, der gør det muligt at ændre og vedligeholde vores applikation.

Som altid er prøvekoden tilgængelig over på GitHub.


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