XML in ResourceBundles

Carron

Mitglied
Hallo :)

heute komme ich mal mit einem Internationalisierungs/Lokalisierungs-Problem.
Nun da sich mein aktuelles Projekt dem Ende seiner Alpha-Phase nähert würde ich es gerne mit einer Hilfe ausstatten, die sich aus XML-Dateien befüllen soll. Soweit erstmal kein Problem, da an anderer Stelle schon erfolgreich XML-Dateien ausgelesen werden. Wiederum kein Problem ist die eigentliche Internationalisierung meiner Oberfläche mittels ResourceBundles.

Hier kommt aber mein Dilemma:
Die Hilfetexte in den entsprechenden XML-Dateien sollen etwas tiefere Strukturen erhalten als die Property-Files in den ResourceBundles, die ja nur aus "Schlüssel"="Wert" bestehen. Jedoch möchte ich nicht auf deren Funktionalität verzichten fehlende Einträge in der spezifischen Datei im Bedarfsfall durch die Entsprechungen in der Default-Datei zu ergänzen:
z.B. sollte statt eines leeren Eintrags in der deutschen Hilfe einfach der hinterlegte englische Text dargestellt werden.


Meine Frage:
Ist eine tiefere (XML-) Struktur durch ResourceBundles abbildbar oder muss ich tatsächlich eigenhändig die Lokalisierung realisieren und parallell beide XML-Dateien einlesen um dann jeden Knoten einzeln abzugleichen?

Auf sowas habe ich nämlich keine Lust:
Java:
import java.io.IOException;
import java.util.Locale;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class HelpTexts {

	private static final String XML_FILENAME = "HelpTexts";
	private static final String XML_FILEEXTENSION = ".xml";

	private final Element defaultSource = openXmlFile(null);
	private final Element specificSource;

	public HelpTexts(final Locale locale) throws InternalHmxException {
		this.specificSource = openXmlFile(locale);
	}

	/**
	 * Reads the help text file for the specified locale.
	 * 
	 * @param locale
	 *            locale containing the language to load the help text xml for
	 * @return root element of the help text file for the specified locales
	 *         language<br>
	 *         return <code>NULL</code> if no file for the chosen language was
	 *         found
	 * @throws InternalHmxException
	 *             invalid xml file
	 */
	private static Element openXmlFile(final Locale locale)
			throws InternalHmxException {
		// get the locale specific xml-file
		String fileName = XML_FILENAME;
		if (locale != null) {
			// insert language key
			fileName += locale.getLanguage();
		}
		fileName += XML_FILEEXTENSION;

		Document doc;
		try {
			doc = new SAXBuilder().build(fileName);
			if (doc == null) {
				return null;
			}
			return doc.getRootElement();
		} catch (JDOMException e) {
			throw new InternalHmxException(
					MessageKeyConstants.ERROR_FILE_INVALID);
		} catch (IOException e) {
			// no file found
		}
		return null;
	}

	/**
	 * Creates a HTML section representing the chosen help option.<br>
	 * If the option cannot be found in the locale specific help text file, the
	 * default language file is used instead.
	 * 
	 * @param option
	 *            help option to represent in HTML
	 * @return read help contents<br>
	 *         returns <code>NULL</code> if the option is not available</br>
	 */
	public String getHelpOption(final String option) {
		Element targetElement;
		if ((this.specificSource == null)
				|| ((targetElement = this.specificSource.getChild(option)) == null)) {
			targetElement = this.defaultSource.getChild(option);
		}
		if (targetElement == null) {
			return null;
		}
		return readHelpOption(targetElement);
	}

	/**
	 * Creates a HTML section representing the chosen help option.
	 * 
	 * @param option
	 *            help option to represent in HTML
	 * @return read help contents
	 */
	private String readHelpOption(final Element option) {
		final StringBuffer result = new StringBuffer();
		final Attribute title = option.getAttribute("Title");
		if (title != null) {
			result.append("<h3>");
			result.append(title.getValue());
			result.append("</h3>\n");
		}
		Attribute text;
		for (int i = 1; (text = option.getAttribute("Text" + i)) != null; i++) {
			result.append("<p>\n");
			result.append(text.getValue());
			result.append("\n</p>\n");
		}
		return result.toString();
	}
}

Ich hoffe das Ganze ist nachvollziehbar.
Schöne Grüße aus der Hauptstadt

Carron
 
Hi,
ist es nicht so,das die ResourceBundles bis zur Default-Properties-Datei abgesucht werden und wenn er den Key bzw. Value findet, er diesen ausgibt? Wenn in deiner Defaultproperties-Datei alles drin ist, sollte es doch kein Problem geben, oder?

z.B. sollte statt eines leeren Eintrags in der deutschen Hilfe einfach der hinterlegte englische Text dargestellt werden.
Willst du das wirklich?

Ansonsten würde dir das vielleicht helfen!?
* If <code>ListResourceBundle</code> or <code>PropertyResourceBundle</code>
* do not suit your needs, you can write your own <code>ResourceBundle</code>
* subclass. Your subclasses must override two methods: <code>handleGetObject</code>
* and <code>getKeys()</code>.

Grüße
Peter
 
Hi Peter,

die von dir beschriebene Verhaltensweise von ResourceBundles ist schon korrekt. Allerdings können diese nur eindimensionale Daten verabeiten

Code:
Key1=Value1
Key2=Value2
...

ich würde mir allerdings wünschen, dass ich komplexere Strukturen hinterlegen kann:

Code:
<entry key="Key1">
    <entry key="Attribute1">
        Value1.1
    </entry>
    <entry key="Attribute2">
        Value1.2
    </entry>
</entry>
<entry key="Key2">
    <entry key="Attribute1">
        Value2.1
    </entry>
    <entry key="Attribute2">
        Value2.2
    </entry>
    <entry key="Attribute3">
        Value2.3
    </entry>
    ...
</entry>
...

Um das zu erreichen, muss ich wohl wirklich mein eigenes ResourceBundle schreiben. Ich hatte gehofft drumherum zu kommen.


Grüße
Carron
 
Zurück