Thomas Bandt

Über mich | Kontakt | Archiv

[MonoTouch] Lokalisierung mit besserer Fallback-Lösung

Die Lokalisierung von iOS-Anwendungen hat Apple eigentlich ganz elegant gelöst, zumindest auf den ersten Blick. Man kann zwischen Text-Dateien und einer Notation in einem C-Style, sowie der PList-XML-Syntax wählen, um einzelne Strings zu lokalisieren.

Egal für welches Format man sich entscheidet, abgelegt werden die Texte immer in einem Ordner "de.lproj", wobei de in diesem Fall für Deutschland steht. Entgegen der Vorgehensweise unter .NET lässt sich keine Region angeben, eine Unterscheidung à la de-CH und de-DE ist also nicht möglich.

Der eigentliche Unterschied zu .NET liegt jedoch in der Fallback-Strategie, die Apple vorgibt. Verwendet der Nutzer eine Sprache, für die kein entsprechender .proj-Ordner angelegt und damit auch keine Lokalisierungen vorgesehen sind, wird automatisch der verwendete Key für die Darstellung verwendet.

Beispiel:

var foo = NSBundle.MainBundle.LocalizedString("Hello World", null);

Im Ordner de.lproj befindet sich nun eine Datei mit dem Namen "Localizable.strings" mit folgendem Inhalt:

"Hello World" = "Hallo Welt";

Wählt der Nutzer als Gerätesprache Deutsch, enthält foo den String "Hallo Welt". Wählt er jedoch Chinesisch, Russisch oder Englisch, ist der Wert immer "Hello World" - denn der Key fungiert, wie gesagt, als Fallback.

Das ist eigentlich eine hübsche Idee, denn sie führt zu einem automatisch lesbareren Code, da die aus .NET bekannte Key-Fummelei entfällt. Man muss sich schließlich keine passenden Keys zusammenbasteln (à la "lbl1text", alles schon gesehen).

Die Sache hat aber einen Haken.

Die Keys sollten in der Sprache geschrieben werden, in der man wirklich zu Hause ist. Denn wenn man die Texte nachträglich lektorieren oder anderweitig überarbeiten (lassen) möchte, hat man ein Problem: man findet sie nicht, wie die der anderen Sprachen, sauber aufgeräumt in passenden Dateien, sondern hat sie über alle Projekte verteilt in dutzenden, wenn nicht hunderten Code-Dateien stehen.

Das ist nun selbst für einen English-Native-Speaker eine nervige und schwierige Aufgabe. Die Alternative, die Texte dann einfach auf Deutsch zu erfassen, weil man daran wahrscheinlich weniger ändern muss, fällt leider auch weg. Denn sind die Keys auf Deutsch, erhalten auch alle Chinesen und Russen, die die App benutzen, ihr Interface auf Deutsch - der Fallback greift.

Ich weiß nicht ganz, weshalb Apple das Problem nicht löst. Wahrscheinlich ist es einer der Fälle US-zentrischer Betrachungsweise …

Aber es gibt eine Lösung:

Man trickst den Fallback einfach aus, indem man ihn abfängt und schließlich auch die "Fallback-Sprache", also meist Englisch, normal mit den anderen lokalisiert (indem man einen en.lproj-Ordner samt zugehöriger Ressourcen anlegt). Das ist möglich, wenn man den eh viel zu sperrigen Aufruf von oben z.B. in eine Extension-Method kapselt, und in dieser dann für den Fallback-Fall auf Englisch zurückgreift.

In Code sähe das mit C# für MonoTouch so aus:

public static class LocalizationExtensions
{
	private static string[] _supportedLanguages = { "de", "en" };

	public static string L10n(this string key)
	{
		string localizedString = NSBundle.MainBundle.LocalizedString(key, null);

		if (localizedString.Equals(key) && !_supportedLanguages.Any(l => l.Equals(NSLocale.PreferredLanguages[0])))
			localizedString = FallbackBundle.LocalizedString(key, null);

		return localizedString;
	}

	private static NSBundle _fallbackBundle;

	private static NSBundle FallbackBundle
	{
		get
		{
			if(_fallbackBundle == null)
				_fallbackBundle = NSBundle.FromPath(NSBundle.MainBundle.PathForResource("en", "lproj"));
			return _fallbackBundle;
		}
	}
}

Prüfung und Abruf erfolgen zur Laufzeit. Ich habe momentan noch keine Erfahrung mit der Performance, gehe aber davon aus, dass es kein Flaschenhals sein sollte. Falls doch, kann man sich die "Fallback-Keys" ja getrost in einen kleinen Cache in Form eines Dictionaries legen.

Der Aufruf sieht dann wie folgt aus:

var foo = "Hello World".L10n();

Kleiner Benefit: den Key könnte man nun getrost auch ändern, z.B. in "lbl1text" ;), da er nie verwendet wird.

Kommentare

  1. Sebastian schrieb am Donnerstag, 6. Dezember 2012 15:25:00 Uhr:

    Zu ergänzen ist noch, dass die BuildAction für die Localizable.strings Dateien auf BundleResource gestellt werden muss. Denkt man, wie ich, nicht daran, sucht man unter Umständen an der falschen Stelle nach einem Fehler.


« Zurück  |  Weiter »