Ausgabe übersetzen

Eine der wichtigsten Localization-Aufgaben überhaupt: die Ausgabe des Programms übersetzen. C++ bietet dafür eine Schnittstelle. Leider ist die ein wenig unterspezifiziert, so dass sie in der Praxis faktisch ziemlich nutzlos ist.

Video

Quelltext

#include <iostream>
#include <locale>

int main()
{
    std::locale loc("");

    auto &msg = std::use_facet<std::messages<char>>(loc);

    auto cat = msg.open("msgtest", loc, "."); // nicht im Standard!
    std::cout << msg.get(cat, 0, 0, "Just a test") << std::endl;
    std::cout << msg.get(cat, 0, 1, "Doesn't really work.") << std::endl;
    msg.close(cat);
}

Erklärung

Zur Übersetzung der Programmausgabe kennt C++ das Konzept der message catalogs. Die bilden einen Index auf eine Nachricht ab und ermöglichen so die Entkoppelung von Programmcode und Ausgabestring.

Zugriff auf diese Funktionalität bietet die Facette std::messages<>. Deren Schnittstelle ist übersichtlich: mittels open() kann man einen Katalog öffnen, mittels get() Strings aus ihm auslesen und mittels close() den Katalog wieder schließen.

std::messages<>::open() erwartet einen Katalognamen und ein Locale-Objekt. Anhand des Namens wird auf eine systemspezifische Art und Weise der Katalog bereitgestellt. Typischerweise geschieht das, indem die passende Übersetzungsdatei eingelesen wird (abhängig von der Locale, aus der das Facettenobjekt stammt). Andere Varianten wären allerdings auch denkbar. Die Funktion liefert ein Handle auf den Katalog zurück, anhand dessen später Elemente aus diesem ausgelesen werden können. 

Die Methode get() erwartet insgesamt vier Parameter: das Handle des Kataloges, auf den zugegriffen werden soll, den Index des passenden Sets im Katalog (was das Set bedeutet ist systemspezifisch. In meiner Implementierung ist die Parameter bedeutungslos), den Index der gewünschten Nachricht und ein Default-Wert, der immer dann zurückgeliefert wird, wenn die betreffende Nachricht nicht im Katalog gefunden wird. Die Methode liefert einen String mit der übersetzten Nachricht oder den Defaultwert zurück.

Mit der Methode close() kann der Katalog geschlossen werden.

Die kleine und sehr flexible Schnittstelle macht die Verwendung an sich einfach. Leider ist die Spezifikation so rudimentär, dass manches sehr unportabel bleibt. So ist beispielsweise überhaupt nicht festgelegt, wie und wo die Kataloge mit den Übersetzungen zu suchen sind. GCC bietet daher einen weiteren, nicht standardkonformen Parameter für open() an, der einen Suchpfad angibt. In diesem werden dann nach einem bestimmten Schema die passenden Übersetzungsdateien gefunden. Ein weiteres Problem ist die fehlende Spezifikation der Kataloge. So mag zwar das Programm an sich portabel sein, aber die Übersetzung ist es nicht. Je nach System müssen die Kataloge auf unterschiedliche Art erstellt und gefunden werden. Hier wäre etwas mehr Mut zur Spezifikation schön gewesen.