RessourceBundle

Status
Nicht offen für weitere Antworten.

Balian

Bekanntes Mitglied
Hallo Zusammen,

ich habe mal eine Frage zu RessourceBundeln.

Ich verwende diese um ein mehrsprachiges Programm umzusetzen. Die Funktionisweise ist klar.

Eventuell Locale setzen - Ressourcedatei laden - und dann Variablen übersetzen lassen. Nun könnte ich ja folgendes machen. In jedem Dialog Ressourcedatei laden und dann alle Variablen "übersetzen" lassen. Dadurch wird der Code aber aufgebläht und nicht sehr übersichtlich. (Jetziger Stand)

Ich habe mir nun überlegt, dass man das in eine statische Klasse auslagern könnte. Einziges Problem dabei ich würde die statische Klasse, mit der statischen Methode bei jeder Variablen aufrufen müssen. Das bedeutet die statische Klasse muss bei jeder Variablen die komplette Ressourcedatei laden. Performenceproblem ????? Im anderen Fall lädt er ja die Datei einmal und "übersetzt" gleich alle Variablen. Die statische Klassengeschichte, würde aber den Code wesentlich übersichtlicher machen.

Was meint ihr dazu?

Gruß

Balian

Ps.: Die statische Methode bekommt die Variablennamen übergeben und soll dann die jeweilige Übersetzung zurückgeb.
 

foobar

Top Contributor
Ist doch kein Problem. Im Konstruktor initialisierst du die ResourceBundle und über eine Methode wie getString greifst du dann auf die Resourcen zu.
Am besten machst du aus der Klasse ein Singleton, dann kannst du von überall darauf zugreifen.
 

Balian

Bekanntes Mitglied
Also wenn ich Dich richtig verstanden habe:

Am besten erzeuge ich eine eigene Klasse, in derren Konstruktor ich das ResourceBundel lade und mit eine Methode die getVariablenuebersetzung den Variablenwert ermittle.

Ich hätte jetzt gedacht, dass über eine statische Klasse zu machen, da müßte ich ja nicht mal ein Objekt erzeugen, sondern könnte direkt auf die Methode zurückgreifen. Das scheint mir aber nicht wirklich günstig, da ja jedesmal beim Aufrufen der Methode die komplette Resourcedatei geladen wird, oder?

Nun hast Du mir vorgeschlagen das über eine Singeltonklasse zu machen. Wenn ich das bei Wiki richtig gelesen habe. Wäre das prinzipiell "fast" das gleiche System. Eine Klasse aus der man nur ein Objekt erzeugen kann und global drauf zugreifen kann.

Wie kann ich das genau verstehen???????

Vielleicht so?

1. Ich erzeuge gleich beim Starten des Programms dieses Objekt?
2. Das Objekt wird in den Speicher geladen und bleibt dort bestehen.
3. Da ich im Konstruktor die komplette Datei geladen habe, stehen mir alle Datenfelder der Resourcedatei im Speicher zur Verfügung und ich kann über die entsprechenden Methoden die Übersetzung anfordern.

Habe ich das so richtig verstanden? Ist das eine gänige Technik für die Erstellung von mehrsprachigen Programmen?

Danke

Gruß Balian
 

foobar

Top Contributor
Ich mache das so:
Code:
package console.client;

import static console.client.ConsoleClientConstants.ICON_BASE_DIR;

import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.apache.log4j.Logger;

public class ResourceBundleFactory
{
    private static ResourceBundleFactory factory;
    private ResourceBundle bundle;
    private Logger logger = Logger.getLogger( getClass() );
    private Map<String, String> cash;
    private Class cl;
    private ResourceBundleFactory()
    {
        bundle = ResourceBundle.getBundle("console_client");
        cash   = new HashMap<String, String>();
        cl     = ResourceBundle.class;
    }
    
    
    public static ResourceBundleFactory getInstance()
    {
        if (null == factory)
        {
                factory = new ResourceBundleFactory();
        }
        return factory;
    }
    
    
    public ImageIcon getIcon(Class clazz, String key)
    {
        String caption = getCaption(clazz, key);
        if (null != caption)
        {
            String icon    = ICON_BASE_DIR+caption.trim();
            URL u          = cl.getResource(icon);
            if (null != u)
            {
                return new ImageIcon(u);
            }
        }
        logger.warn("icon not found "+caption);
        return null;
    }
    
    
    public Image getImage(Class clazz, String key) throws IOException
    {
        String caption = getCaption(clazz, key);
        if (null != caption)
        {
            String icon    = ICON_BASE_DIR+caption.trim();
            URL u          = cl.getResource(icon);
            if (null != u)
            {
                return ImageIO.read(u);
            }
        }
        logger.warn("icon not found "+caption);
        return null;
    }
    
    public String getCaption(Class clazz, String  key)
    {
        String request = clazz.getName()+'.'+key;
        
        String cashedRequest = cash.get(request);
        if (null != cashedRequest)
        {
            return cashedRequest;
        }
        
        try
        {
            String out = bundle.getString( request );
            cash.put(request, out);
            return out;
        }
        catch(MissingResourceException e)
        {
            logger.error("caption not found "+ request);
            return "Error: caption not found " + request;
        }
    }
    
    public boolean hasCaption(Class clazz, String key)
    {
        String request = clazz.getName()+'.'+key;
        try
        {
            bundle.getString(request);
        }
        catch(MissingResourceException e)
        {
            return false;
        }
        return true;
    }
    
    public String getCaption(Class clazz, String key, String[] values)
    {
        String caption  = getCaption(clazz, key);
        return MessageFormat.format(caption, (Object[])values);
    }
    
    public String getCaption(Class clazz, String key, String value)
    {
        String caption  = getCaption(clazz, key);
        return MessageFormat.format(caption, new Object[]{value});
    }
}

Die Klasse hat noch ein paar zusätzliche Features wie überprüfen ob ein String vorhanden ist oder Stringformatierungen durch MessageFormat.

Habe ich das so richtig verstanden? Ist das eine gänige Technik für die Erstellung von mehrsprachigen Programmen?
2 x Ja :)
 

Balian

Bekanntes Mitglied
Danke für Dein Codebeispiel. Ich habe mal ein Codebeispiel für eine Singletonklasse. Ist das so richitg? (Die Ressourcebundlegeschichte zu implementieren ist ja dann nicht mehr so schwer.... )

Code:
public class Singleton {
	
	private static Singleton instance = null;
	
	// Variable
	private String Variable = "Test";
	
	// Konstruktor der nicht ausserhalb der Klasse aufgerufen werden kann
	private Singleton() {
	}
	
	// ermöglicht den Zugriff auf die Instanz
	public static Singleton getInstance() {

		if( instance == null) {
			instance = new Singleton();
		}
		return instance;
		
	}
	
	// gibt den Variablenwert zurück
	public String getVariableValue() {
		return Variable;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

Im Prinzip erstellt eine Singletonklasse nur eine Instanz von sich selber, sofern diese nicht schon existiert? Die Überladung des Konstruktor verhindert dabei, dass weitere Klassen von aussen Instanzen bilden können.

Da es im Programm noch Referenzen auf das Objekt gibt, löscht der Garbagecollector das Objekt auch nicht. Und durch public kann man von jeder Klasse drauf zugreifen.

Gruß

Balian
 

Wildcard

Top Contributor
Ich benutze den externalize String Mechanismus von Eclipse + ResourceBundle PlugIn und kümmere mich nicht mehr um solche Dinge :wink:
 

foobar

Top Contributor
Ich benutze den externalize String Mechanismus von Eclipse + ResourceBundle PlugIn und kümmere mich nicht mehr um solche Dinge
So mache ich das seit ein paar Wochen auch. Gibt es noch ein zusätzliches ResourceBundle PlugIn für Eclipse? Ich kenne nur die Externalize Strings Funktion.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben