Was kostet die Welt? Internationalisierung mit den International Components for Unicode (ICU)

Print Friendly, PDF & Email

Crowd
Wie heißt „Japan“ auf Türkisch? Wie sortiert man koreanische Begriffe alphabetisch? Und wie viele Pluralformen gibt es im Arabischen? Wer sich ernsthaft mit diesen Fragen beschäftigen muss, kommt kaum an den International Components for Unicode (ICU) vorbei.

Als Java-Entwickler bietet einem die Java 7-Plattform gute Unterstützung, um lokalisierbare Anwendungen zu entwickeln, sowohl im Funktionsumfang als auch bei den unterstützten Sprachen. Jedoch ergeben sich schnell Anforderungen, die Java von Haus aus nicht unterstützt. Glücklicherweise gibt es eine Datensammlung zusammen mit einer Java-Bibliothek, die kaum einen Wunsch offen lässt: Das Common Locale Data Repository (CLDR) zusammen mit den International Components for Unicode (ICU).

Das Common Locale Data Repository

Das Common Locale Data Repositorys (CLDR) enthält eine Fülle an Daten, mit denen man Software an die lokalen Ansprüche praktisch aller Sprachen der Welt anpassen kann. Der Kern dieser Sammlung besteht aus JSON- bzw. XML-Daten zu derzeit 664 verschiedenen Locales, d.h. Sprachen und Sprachvarianten.

Für jede unterstützte Sprache finden man dort u.a. die folgenden Informationen:

  • Die Namen aller Sprachen
  • Die Namen aller Länder
  • Die Namen aller Währungen
  • Die Bezeichnungen von Kalendern und Schriftsystemen
  • Die Bezeichnungen von Zeitzonen
  • Die Namen der Monate und Wochentage (ausführlich, abgekürzt)
  • Verschiedenste Varianten von Datums- und Zeitangaben
  • Relative Zeitangaben (z.B. „gestern“ oder „nächster Monat“)

Das heißt beispielsweise, dass man in jeder Sprache den Namen jeder anderen Sprache findet. Würde man alleine diese Informationen in eine Tabelle übernehmen, würde man schon eine sehr große Matrix erhalten.

Das CLDR enhält für jede Sprache eine vollständige Datei mit allen Informationen und für jede Sprachvariante die Änderungen gegenüber der Haupt-Variante. Das heißt, dass zum Beispiel in der Datei de.xml alle Informationen in Hochdeutsch enthalten sind und de_AT.xml die Abweichungen für Deutsch in Österreich enthält.

Die International Components for Unicode

Diese große Wissenssammlung alleine hilft zwar enorm, einzelne Fragen zu klären. Für die Entwicklung einer internationalisierbaren Anwendung sind diese Informationen alleine jedoch wenig hilfreich. Dafür gibt es die International Components for Unicode (ICU4J): eine Bibliothek, die dieses Wissen für C++- und Java-Anwendungen verfügbar macht.

ICU4J bietet eine umfangreiche API, um das Wissen der CLDR in eigener Software zu nutzen. Die angebotenen Klassen richten sich sehr eng nach den im JDK enthaltenen Klassen. Hier wie dort gibt es z.B. eine Klasse MessageFormat, um Texte zu formatieren. Die ICU-Klassen haben den Vorteil, dass sie erheblich mehr Sprachen und Sprachvarianten abdecken als die JDK-Klassen. Zudem sind sie gegenüber den JDK-Klassen auch funktional deutlich erweitert.

Zwei Beispiele verdeutlichen den Funktionsumfang der Bibliothek:

Wie sortiere ich Texte alphabetisch in einer beliebigen Sprache?

Jede Sprache hat eigene Regeln, wie Texte alphabetisch sortiert werden. Die compareTo-Methode der Klasse String bietet aber nur eine Vergleich der Unicode-Zeichen. Im Deutschen führt dies z.B. dazu, dass alle Wörter, die mit einem Umlaut beginnen, ans Ende einer Liste sortiert werden. Ein typischer Fall ist, dass Österreich in einer Liste mit Ländernamen nicht hinter Oman einsortiert wird, sondern hinter Simbabwe.

Das JDK bietet deswegen die Klasse Collation, die es ermöglicht, sprachspezifisch zu sortieren. Jedoch fehlt die Unterstützung für viele nicht-europäische Sprachen und der Funktionsumfang ist beschränkt. Die ICU-Bibliothek bietet dazu eine eigene Klasse Collation an, die auf die ausführlicheren Regeln zur alphabetischen Sortierung der CLDR zurückgreift und mehr Funktionalität anbietet. Ein Comparator zum Sortieren von Texten schaut dann z.B. so aus:

import java.util.Comparator;
import com.ibm.icu.text.Collator;

public class TextComparator implements Comparator<String> {

    private Collator collator;

    public TranslatedEnumComparator(Locale locale) {
        collator = Collator.getInstance(locale);
        collator.setStrength(Collator.SECONDARY);
    }

    public int compare(String text1, String text2) {
        return collator.compare(text1, text2);
    };
}

Wie übersetze ich Mengenausdrücke richtig?

In den westeuropäischen Sprachen ist es einfach – für Substantive gibt es eine Singularform und eine Pluralform: „1 Eintrag“, „2 Einträge“. Wenn man noch den Sonderfall der leeren Menge hinzunimmt („kein Eintrag“) reichen drei verschiedene Fälle für die Übersetzungen von Mengenbegriffen aus.

Dabei übersieht man leider leicht, dass es Sprachen mit vier, fünf oder gar sechs verschiedenen Pluralformen gibt. Die Regeln, bei welcher Zahl welche Pluralform zu verwenden ist, sind teilweise sehr komplex. Aber auch hier bietet das Gespann aus CLDR und ICU Lösungen. So ist es beispielsweise möglich, für eine gegebene Zahl die passende Pluralform in einer beliebigen Sprache zu ermitteln (die möglichen Pluralformen sind als zero, one, two, few, many und other kodiert):

public static String getPluralForm(long number, String locale) { 
    ULocale uLocale = ULocale.forLanguageTag(locale); 
    PluralRules pluralRules = PluralRules.forLocale(uLocale); 
    return pluralRules.select(number); 
}

Mehr Möglichkeit dazu beschreibt ein englischsprachiger Blog-Eintrag.

Zu guter Letzt

Gerade die ICU-Bibliothek bietet viel Hilfe, komplexe Anforderungen an die Lokalisierung umzusetzen. Es lohnt sich, durch die Erläuterungen zu stöbern.

Somit bleibt nur noch zu klären, wie „Japan“ auf Türkisch heißt: Japonya, zumindest, wenn ich keinen Copy&Paste-Fehler gemacht habe.

Schreibe einen Kommentar

Fügen Sie die notwendige Nummer ins freie Feld ein *