{"id":134,"date":"2021-03-10T10:00:00","date_gmt":"2021-03-10T10:00:00","guid":{"rendered":"http:\/\/erdbeerbeet.com\/?p=134"},"modified":"2021-09-06T13:43:30","modified_gmt":"2021-09-06T13:43:30","slug":"my-flutter-flight-localization","status":"publish","type":"post","link":"https:\/\/erdbeerbeet.com\/de\/my-flutter-flight-localization","title":{"rendered":"Meine Flutter-Fahrt &#8211; Lokalisierung"},"content":{"rendered":"\n<p>Mein neues Projekt hat eben erst begonnen, aber es ist niemals zu fr\u00fch, um ordentliche Lokalisierung einzuf\u00fchren. Je l\u00e4nger man damit wartet, desto mehr Arbeit kommt schlie\u00dflich auf einen zu.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h2 class=\"wp-block-heading\" id=\"block-816202ad-5e60-491c-afaf-249fb859adc9\">Das Problem<\/h2>\n\n\n\n<p>Selbst wenn man nicht mehrere Sprachen beherrscht m\u00f6chte man seine App vielleicht auch den M\u00e4rkten anderer L\u00e4nder zug\u00e4nglicher machen.<br>Oder man spricht durchaus mehrere Sprachen und baut Lokalisierung ein, einfach weil mann es kann.<br>Oder man m\u00f6chte einfach alle Label, Texte und Strings an einem Ort versammelt haben, wie es sich f\u00fcr einen guten Programmierer geh\u00f6rt.<\/p>\n\n\n\n<p>Einfach niemals eine Zeile Klartext mitten im Quellcode verwenden, abgesehen von den Lokalisierungs-Dateien. Das geh\u00f6rt sich einfach nicht&#8230;<\/p>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"block-ad5ed819-0e42-48b5-b512-f26b808a53b1\">Die Lehrbuch-L\u00f6sung<\/h2>\n\n\n\n<p>Ich verdiene kaum Anerkennung f\u00fcr den Code weiter unten, bitte schaut einfach in die Flutter-Dokumentation zur <a href=\"https:\/\/flutter.dev\/docs\/development\/accessibility-and-localization\/internationalization\">Internationalisierung von Flutter Apps<\/a>.<\/p>\n\n\n\n<p>Kurz gesagt ben\u00f6tigt man eine Hilfsklasse, welche sich um die Lokalisierung k\u00fcmmert, muss der Hauptklasse einmal beibringen, welche Sprache verwendet werden soll und dann noch Dateien f\u00fcr die \u00dcbersetzungen anlegen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"block-150cb17b-7f1d-4d67-8662-c503c090343f\">Das Programmieren<\/h2>\n\n\n\n<p>Wieder stelle ich nur die mindestens ben\u00f6tigten Dateien f\u00fcr eine Umsetzung der Lokalisierung vor. Diese App kann nicht viel mehr, als (lokalisierten) Text anzeigen. Aber es ist ein guter Ausgangspunkt.<\/p>\n\n\n\n<p id=\"block-117b2906-c4dc-4866-8a8e-0b5254269ca6\"><strong>pubspec.yaml<\/strong> (Dependency hinzuf\u00fcgen und assets einkommentieren)<\/p>\n\n\n\n<pre id=\"block-8766fac4-9188-4b97-943e-5b5970df100b\" class=\"wp-block-code\"><code>flutter_localizations:<br>    sdk: flutter<\/code><\/pre>\n\n\n\n<pre id=\"block-c3f2fc8b-cab9-48c4-b0ed-013ddc962a84\" class=\"wp-block-code\"><code>assets:<br>    - assets\/lang\/<\/code><\/pre>\n\n\n\n<p id=\"block-cc42eac1-c91c-4acf-b4e5-9e7b89ab88a2\"><strong>localization.dart<\/strong><\/p>\n\n\n\n<pre id=\"block-b810b201-620a-48e9-877e-f5fa8024ddcc\" class=\"wp-block-code\"><code>import 'dart:async';<br>import 'dart:convert';<br><br>import 'package:flutter\/material.dart';<br>import 'package:flutter\/services.dart';<br><br><br>class DemoLocalizations {<br>  DemoLocalizations(this.locale);<br><br>  final Locale locale;<br><br>  static DemoLocalizations of(BuildContext context) {<br>    return Localizations.of&lt;DemoLocalizations&gt;(context, DemoLocalizations);<br>  }<br><br>  Map&lt;String, String&gt; _sentences;<br><br>  Future&lt;bool&gt; load() async {<br>    String data = await rootBundle.loadString(<br>        'assets\/lang\/${this.locale.languageCode}.json');<br>    Map&lt;String, dynamic&gt; _result = json.decode(data);<br><br>    this._sentences = new Map();<br>    _result.forEach((String key, dynamic value) {<br>      this._sentences&#91;key] = value.toString();<br>    });<br><br>    return true;<br>  }<br><br>  String trans(String key) {<br>    return this._sentences&#91;key];<br>  }<br>}<br><br>class DemoLocalizationsDelegate<br>    extends LocalizationsDelegate&lt;DemoLocalizations&gt; {<br>  const DemoLocalizationsDelegate();<br><br>  @override<br>  bool isSupported(Locale locale) =&gt; &#91;'de', 'en'].contains(locale.languageCode);<br><br>  @override<br>  Future&lt;DemoLocalizations&gt; load(Locale locale) async {<br>    DemoLocalizations localizations = new DemoLocalizations(locale);<br>    await localizations.load();<br><br>    print(\"Load ${locale.languageCode}\");<br><br>    return localizations;<br>  }<br><br>  @override<br>  bool shouldReload(DemoLocalizationsDelegate old) =&gt; false;<br>}<\/code><\/pre>\n\n\n\n<p id=\"block-75951d5a-2d7b-4a26-9c08-7d83f64e5695\"><strong>main.dart<\/strong><\/p>\n\n\n\n<p>Dieser Code wird die Sprache des Systems nutzen, bzw. auf das definierte Fallback zur\u00fcck greifen.<\/p>\n\n\n\n<pre id=\"block-f5bc5d9d-546a-4c6b-ad12-ae1a0ad7711e\" class=\"wp-block-code\"><code>import 'package:flutter\/material.dart';<br>import 'package:flutter_localizations\/flutter_localizations.dart';<br><br>import 'localization.dart';<br><br>void main() {<br>  runApp(MyApp());<br>}<br><br>class MyApp extends StatelessWidget {<br><br>  @override<br>  Widget build(BuildContext context) {<br>    return MaterialApp(<br>      home: MyHomePage(),<br>      localizationsDelegates: &#91;<br>        const DemoLocalizationsDelegate(),<br>        GlobalMaterialLocalizations.delegate,<br>        GlobalWidgetsLocalizations.delegate,<br>      ],<br>      supportedLocales: &#91;<br>        const Locale('en', 'US'), \/\/ English<br>        const Locale('de', 'DE'), \/\/ German<br>      ],<br>      localeResolutionCallback: (Locale locale,<br>          Iterable&lt;Locale&gt; supportedLocales) {<br>        if (locale != null) {<br>          for (Locale supportedLocale in supportedLocales) {<br>            if (supportedLocale.languageCode == locale.languageCode ||<br>                supportedLocale.countryCode == locale.countryCode) {<br>              return supportedLocale;<br>            }<br>          }<br>        }<br>        return supportedLocales.first;<br>      },<br>    );<br>  }<br>}<br><br>class MyHomePage extends StatefulWidget {<br>  MyHomePage({Key key, this.title}) : super(key: key);<br>  final String title;<br><br>  @override<br>  _MyHomePageState createState() =&gt; _MyHomePageState();<br>}<br><br>class _MyHomePageState extends State&lt;MyHomePage&gt; {<br><br>  @override<br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      appBar: AppBar(<br>        title: Text(DemoLocalizations.of(context).trans('title')),<br>      ),<br>      body: Column(<br>        children: &#91;<br>          Text(DemoLocalizations.of(context).trans('text1')),<br>        ],<br>      )<br>    );<br>  }<br>}<br>\ufeff<\/code><\/pre>\n\n\n\n<p id=\"block-2191ebdd-2a0a-44fa-8751-32a5e10637e0\">In einem Ordner assets\/lang\/ wie im pubspec.yaml beschrieben, werden Dateien f\u00fcr jede Sprache angelegt, die unterst\u00fctzt werden soll.<\/p>\n\n\n\n<p id=\"block-9cdcacb1-8023-430e-b5d4-4d9f7c39a0ac\"><strong>de.json<\/strong><\/p>\n\n\n\n<pre id=\"block-4bf3c6e6-bdde-493d-8903-c86d446951a3\" class=\"wp-block-code\"><code>{\n  \"title\": \"Lokalisierung\",\n  \"text1\": \"Hallo Welt\"\n}<\/code><\/pre>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h2 class=\"wp-block-heading\" id=\"block-653c4e25-63f9-4466-8f7b-b6a69e88d08a\">Das Ergebnis<\/h2>\n\n\n\n<p>Wie man sieht arbeitet mein System auf deutsch.<br>Es sieht nicht nach viel aus, aber je gr\u00f6\u00dfer die App wird, desto besser ist es, wenn man seine Lokalisierung bereits eingerichtet hat.<\/p>\n<\/div><\/div>\n\n\n\n<figure class=\"wp-block-image wp-duotone-duotone-2\" id=\"block-95f3757a-5464-4bc8-9c6f-a6b96256a4d6\"><img decoding=\"async\" src=\"http:\/\/erdbeerbeet.com\/wp-content\/uploads\/2021\/03\/Bildschirmfoto-2021-03-08-um-22.21.09-990x1024.png\" alt=\"This image has an empty alt attribute; its file name is Bildschirmfoto-2021-03-08-um-22.21.09-990x1024.png\"\/><\/figure>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<h2 class=\"wp-block-heading\" id=\"block-3ab6906d-3231-4995-9ad4-2629509628c4\">Zus\u00e4tzlich&#8230;<\/h2>\n\n\n\n<p id=\"block-a39c1b74-7326-4c66-ba9a-d6bf7a41d5ac\">Wenn man f\u00fcr iOS entwickelt, bitte daran denken, die unterst\u00fctzten Sprachen in info.plist einzutragen (wie es so sch\u00f6n im oben verlinken Tutorial aufgef\u00fchrt wird).<\/p>\n<\/div><\/div>\n\n\n\n<p>Seid ihr multilingual oder warum ist f\u00fcr euch eine Lokalisierung eurer App noch interessant?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Man kann gar nicht fr\u00fch genug anfangen, seine App zu lokalisieren. Ganz egal, ob f\u00fcr mehrere Sprachen, oder weil man seinen Text aufger\u00e4umt haben m\u00f6chte.<\/p>\n","protected":false},"author":1,"featured_media":384,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48,13,12],"tags":[16,14,17],"class_list":["post-134","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-companero","category-flutter","category-programming","tag-app","tag-flutter","tag-localization"],"translation":{"provider":"WPGlobus","version":"3.0.0","language":"de","enabled_languages":["en","de"],"languages":{"en":{"title":true,"content":true,"excerpt":true},"de":{"title":true,"content":true,"excerpt":true}}},"_links":{"self":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/comments?post=134"}],"version-history":[{"count":4,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/134\/revisions"}],"predecessor-version":[{"id":397,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/posts\/134\/revisions\/397"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/media\/384"}],"wp:attachment":[{"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/media?parent=134"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/categories?post=134"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/erdbeerbeet.com\/de\/wp-json\/wp\/v2\/tags?post=134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}