24.3. Ressourcebundter

Ressourcebundter bruges til at isolere lokalafhængige data fra din kode, f.eks. tekster eller billeder på knapper. Dette afsnit går i dybden med klasserne java.util.ResourceBundle, java.util.PropertyResourceBundle og ListResourceBundle som er nyttige i denne sammenhæng.

24.3.1. Generelt om ressourcebundter

Et ressourcebundt er en samling af lokalafhængige data, som hver især er associeret med en unik tekstnøgle. Nøglen bruges når der skal hives et bestemt element ud af bundtet, f.eks. et billede.

Et ressourcebundt hører til en familie af ressourcebundter, som deler et fælles basisnavn, f.eks. "dk.sslug.LogInd" eller "dk.sslug.MitRessourcebundt". Alle medlemmer i familien har et unikt navn på formen basisnavn[_sprogkode[_landekode[_variant]]], der afspejler den lokalindstilling, som de understøtter.

F.eks. kunne vi have følgende ressourcebundter

dk.sslug.LogInd
dk.sslug.LogInd_de
dk.sslug.LogInd_da_DK
dk.sslug.LogInd_da_DK_LINUX

Alle familiemedlemmer indeholder de samme data i en lokaliseret udgave. I en given familie identificeres et bestemt dataelement altid med den samme nøgle - uanset hvilket familiemedlem man har fat i.

Når du i dit program ønsker at tilgå data hørende til et ressourcebundt så gøres det ved at bruge klassemetoden getBundle(String, Locale) på klassen ResourceBundle som vist forneden.

Locale daLocale = new Locale("da", "DK");
ResourceBundle logIndBundt =
  ResourceBundle.getBundle("dk.sslug.LogInd", daLocale);

Metoden vil først forsøge at finde ressourcebundtet "dk.sslug.LogInd_da_DK", dernæst "dk.sslug.LogInd_da" og endeligt "dk.sslug.LogInd". Hvis ingen af dem findes så kastes en MissingResourceException. På grund af dette bør der altid være et standard ressourcebundt med basisnavnet som eneste navn.

I JDK er der to måder at definere et ressourcebundt på: som en ressourcefil eller som en klasse. De to næste afsnit beskriver dette nærmere.

24.3.2. Lagring af tekst i ressourcefiler

Det er muligt at lagre lokalafhængig tekst i en dedikeret ressourcefil kaldet for en property-fil. Det er en simpel tekstfil, der bruges til at associere tekstnøgler med lokalafhængige tekster. En association er på formen nøglenavn = værdi, hvor nøglen kan være navndøbt mere eller mindre abitrært. I praksis er det fornuftigt at vælge et signende nøglenavn.

Forneden ses et eksempel på en ressourcefil. Kommentarlinjer starter med havelågetegn (#).

# LogInd_da_DK.properties
# Dansk lokalindstilling for Log ind-skærmbilledet
IndtastNavnLabel = Indtast dit navn
IndtastAdgangskodeLabel = Indtast din adgangskode
LogIndKnap = Log ind
AnnullerKnap = Annuller

Hvis tekstfilen placeres i "dk/sslug/" relativt fra classpath så får ressourcebundtet navnet "dk.sslug.LogInd_da_DK". Helt analogt får ressourcebundet for de to nedenstående ressourcefiler navnene "dk.sslug.LogInd" og "dk.sslug.LogInd_de".

# LogInd.properties
# Standard lokalindstilling for Log ind-skærmbilledet
IndtastNavnLabel = Enter name
IndtastAdgangskodeLabel = Enter password
LogIndKnap = Log in
AnnullerKnap = Cancel

# LogInd_de.properties
# Mangelfuld tysk lokalindstilling for Log ind-skærmbilledet
AnullerKnap = Abbrechen

Ressourcefiler håndteres af PropertyResourceBundle, der er en subklasse af ResourceBundle. Som programmør behøver man dog kun benytte sig af moderklassen, hvilket følgende eksempel viser.

package dk.sslug;

import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;

public class PropertyResourceBundleEksempel
{
  public static void main(String[] args)
  {
    udskrivVaerdier(new Locale("da", "DK"));
    udskrivVaerdier(new Locale("de"));
    udskrivVaerdier(new Locale("fr", "CA"));
  }
  
  private static void udskrivVaerdier(Locale locale)
  {
    ResourceBundle logIndBundt =
      ResourceBundle.getBundle("dk.sslug.LogInd", locale);
    Enumeration enum = logIndBundt.getKeys();
    while (enum.hasMoreElements()) {
      String noegle = (String) enum.nextElement();
      System.out.println(noegle +" = " + logIndBundt.getString(noegle));
    }
    System.out.println();
  }
}

Køres programmet så fås

IndtastAdgangskodeLabel = Indtast din adgangskode
LogIndKnap = Log ind
IndtastNavnLabel = Indtast dit navn
AnnullerKnap = Annuller

AnullerKnap = Abbrechen
IndtastAdgangskodeLabel = Enter password
LogIndKnap = Log in
IndtastNavnLabel = Enter name
AnnullerKnap = Cancel

IndtastAdgangskodeLabel = Enter password
LogIndKnap = Log in
IndtastNavnLabel = Enter name
AnnullerKnap = Cancel

PropertyResourceBundle benytter sig internt af java.text.Properties som repræsenterer en persistent mængde of nøgle/værdi-par. Den er nyttig såfremt du ønsker dit program skal benytte sig af opsætningsfiler. Man kan finde mere information i JDK's API dokumentation.

24.3.3. Lagring af ressourcer i klasser

TODO