Lokalisierung einer Xamarin.Forms App

Wenn man eine App entwickelt möchte man diese später ja auch in den jeweiligen Stores zum Download zur Verfügung stellen und daher sollte man sich frühzeitig die Frage stellen, in welchen Stores man die App zum Download anbieten möchte und natürlich auch welche Sprachen die App unterstützen soll. Dies sollte man am Besten direkt bei der Programmierung der App wissen bzw. beachten, dass die App später in mehreren Sprachen zur Verfügung stehen soll/wird. Den in Xamarin.Forms gibt es das Konzept mit Ressourcen-Dateien, welche eigentlich nichts anderes als Key-Value-Pairs sind und zur Laufzeit wird denn der Key mit dem Value ersetzt und so können Texte bequem und einfach lokalisiert werden. Wie dies im einzelnen funktioniert, möchte ich euch in diesem Beitrag zeigen.

Zunächst legen wir ein ganz normales Xamarin.Forms Projekt in Visual Studio an. Anschließend fügen wir in dem portablen Part der App einen Ordner Resources and und darin dann eine Datei mit dem Namen AppResources.resx. Nach dem Öffnen der Datei können hier bequem die lokalisierten Texte eingetragen werden.

Um nun die Texte im XAML verwenden zu können habe ich im Ordner Common eine Klasse TranslateExtension mit folgendem Inhalt eingefügt:

[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
  private readonly CultureInfo _cultureInfo;
  private const string ResourceId 
    = "YOURNAMESPACE.Resources.AppResources";
  private static readonly Lazy<ResourceManager> ResourceManager 
    = new Lazy<ResourceManager>(() => new ResourceManager(ResourceId, 
	   typeof(TranslateExtension).GetTypeInfo().Assembly));

  public string Text { get; set; }

  public TranslateExtension()
  {
    _cultureInfo = CultureInfo.CurrentUICulture;
  }

  public object ProvideValue(IServiceProvider serviceProvider)
  {
    if (Text == null)
      return string.Empty;

    try
    {
	  var translation = ResourceManager.Value.GetString(Text, _cultureInfo);
      return translation ?? Text;
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
      return Text;
    }
  }
}

Was genau macht jetzt jedoch dieser ode und wie kann ich diesen verwenden? Zunächst möchte ich die erste Frage beantwortet. Es wird eine Instanz eines ResourceManager erzeugt, welcher als Grundlage unsere RESX-Datei hat. Anschließend wird über die Text-Property versucht den passenden Wert zu erhalten und sollte dieser vorhanden sein, so wird dieser ausgegeben oder ansonsten der übergebene Key. Hierdurch kann man schnell Tipp-Fehler erkennen oder aber fehlende Ressourcen.

Um nun einen Text im XAML zu erhalten, muss zunächst der Namespace zu unserer TranslateExtension hinzugefügt werden. Anschließend können wir diese (ähnlich wie ein Binding verwenden), wie das folgende Beispiel zeigt:

<Label Text="{common:Translate AppTitle}" />

Wie man dem Beispiel entnehmen kann, können wir sowohl den Suffix Extension weglassen und müssen auch nicht die Property Text angegeben, da wir dies über das Attribut ContentProperty bereits erledigt haben.

Um nun verschiedene Sprachen zur Verfügung zu stellen, erzeugen wir weitere Dateien im Ordner Resources und fügen aber die spezifischen Länderkürzel in den Namen hinzu, z.B. AppResources.en-US.resx oder AppResources.de-DE.resx.

Sofern das Device nun auf Deutsch gestellt wird, wird die passenden Ressourcen-Datei geladen und zur Anzeige gebracht.

Und sollte man Englisch als System-Sprache haben, so werden entsprechend die Texte aus der anderen Ressourcen-Datei angezeigt.

Um nun aber zum Beispiel in einem ViewModel auf die Ressourcen zugreifen zu können, können wir einfach z.B. AppResources.AppTitle verwenden und auch hier wird automatisch der passende Eintrag zur jeweiligen Sprache genommen und angezeigt.

Ich habe mal ein kleines Samples geschrieben, welches ich auf GitHub veröffentlicht habe, welches genau zeigt, wie man seine eigene App relativ schnell und einfach lokalisieren kann, damit die App in verschiedenen Sprachen in den jeweiligen Ländern verwendet werden kann.

Hot Restart: iOS-Apps unter Windows deployen Xamarin.Forms: TextToSpeech Xamarin Expert Day in Köln