Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lokalisierung für Mobile Apps

Lokalisierung für Mobile Apps

Deutsche Version meines Talks auf der Developer Week 2014 in Nürnberg. über Internationalisierung und Lokalisierung mobiler Apps am Beispiel von iOS. Beleuchtet u. a. Text, Zahlen, Datum und Zeit, Bilder und andere Ressourcen. Im Bereich Text werden verschiedene Schriftsysteme und korrekte Pluralbildung beschrieben.

Daniel Schneller

July 16, 2014
Tweet

More Decks by Daniel Schneller

Other Decks in Technology

Transcript

  1. Agenda I18N vs. L10N Sprachen und Regionen Text Datum und

    Uhrzeit Zahlen Bilder und andere Ressourcen https://github.com/dschneller/I18N-Example
  2. Internationalization […] ein Programm so zu gestalten, dass es leicht

    (ohne den Quellcode ändern zu müssen) an andere Sprachen und Kulturen angepasst werden kann. * * Wikipedia
  3. Localization Anpassung von […] Software an die in einem […]

    geographisch oder ethnisch umschriebenen Nutzungsgebiet […] vorherrschenden lokalen sprachlichen und kulturellen Gegebenheiten. * * Wikipedia
  4. Sprachen und Regionen Sprache ≠ Region 12h-Zeit für Amerikaner in

    Deutschland „Jänner“ – „Januar“ Localization ≠ Locale Deutscher bevorzugt englische Anwendungstexte Aber: 24h-Zeitformat
  5. NSLocale Kapselt aktuelle Regionaleinstellungen + (id)autoupdatingCurrentLocale
 + (id)currentLocale NSCurrentLocaleDidChangeNotification [[NSNotificationCenter

    defaultCenter]
 addObserver:self
 selector:@selector(localeDidChange:)
 name:NSCurrentLocaleDidChangeNotification
 object:nil] Formatter / Locale Instanzen erneuern Bildschirminhalte aktualisieren
  6. NSLocale -[NSLocale objectForKey:] NSString* NSLocaleIdentifier NSString* NSLocaleMeasurementSystem NSString* NSLocaleLanguageCode NSString*

    NSLocaleDecimalSeparator NSString* NSLocaleCountryCode NSString* NSLocaleGroupingSeparator NSString* NSLocaleScriptCode NSString* NSLocaleCurrencySymbol NSString* NSLocaleVariantCode NSString* NSLocaleExemplarCharacterSet NSString* NSLocaleCurrencyCode NSString* NSLocaleCollatorIdentifier NSString* NSLocaleCalendar NSString* NSLocaleQuotationBeginDelimiterKey NSString* NSLocaleCollationIdentifier NSString* NSLocaleQuotationEndDelimiterKey NSString* NSLocaleUsesMetricSystem
  7. NSLocale Enthält nicht die aktuelle Sprache der Anwendung! Locale ≠

    Localization [NSBundle mainBundle].localizations; // NSArray, (alle) [NSBundle mainBundle].preferredLocalizations[0]; // (laufende) Caveats InfoPlist.strings Lokalisierungen bestimmen „localizations“ Schnittmenge mit Nutzerpräferenz AppleLanguages Parameter
  8. Text ≠ Text Sprache für Meldungen, Labels etc. Schreibrichtung &

    Alignment Schriftsysteme Zahlen in Text Namen & Adressen Phrasen, Floskeln und Begriffe Pluralbildung Sortierung …
  9. Text ≠ Text Sprache für Meldungen, Labels etc. Schreibrichtung &

    Alignment Schriftsysteme Zahlen in Text Namen & Adressen Phrasen, Floskeln und Begriffe Pluralbildung Sortierung …
  10. Base Localization … /* Class = "IBUILabel"; text = "Loaded

    by SecondViewController"; ObjectID = "NDk-cv-Gan"; */ "NDk-cv-Gan.text" = "Loaded by SecondViewController"; " /* Class = "IBUILabel"; text = "First View"; ObjectID = "KQZ-1w-vlD"; */ "KQZ-1w-vlD.text" = "First View"; …
  11. NSLocalizedString Beispiel [button setTitle:NSLocalizedString(@"reset.counter.button.title", 
 @"Reset Counter action button")
 forState:…];

    genstrings — Localizable.strings /* Reset Counter action button */
 "reset.counter.button.title" = "Zurücksetzen";
  12. .strings Files Updates? Use ibtool every time you update your

    labels and text.
 In the Base.lproj folder:
 
 ibtool ChangedNib.xib --generate-strings- file NewStrings.strings
 
 Open the generated output file and copy all new string entries to ChangedNib.strings in each lproj. #fail
  13. Texte nicht normalisieren DRY! — Do Repeat Yourself [NSString stringWithFormat:@”…”]

    Localizable.strings “count” = “Anzahl” “game” = “Spiel” “reset” = “zurücksetzen” “save” = “sparen” “thumbnail” = “Daumennagel”
  14. Texte nicht normalisieren DRY! — Do Repeat Yourself [NSString stringWithFormat:@”…”]

    Localizable.strings “count” = “Anzahl” “game” = “Spiel” “reset” = “zurücksetzen” “save” = “sparen” “thumbnail” = “Daumennagel” “reset count” ”zurücksetzen Anzahl” “save game” “sparen Spiel” …
  15. Texte nicht normalisieren Kontext und Grammatik gehen verloren Satzbau Wortformen

    (Deklination & Konjugation) … Eigene Strings für jeden Zweck
  16. Texte nicht normalisieren Kontext und Grammatik gehen verloren Satzbau Wortformen

    (Deklination & Konjugation) … Eigene Strings für jeden Zweck “reset.counter.button” = “Auf 0 stellen”
  17. Texte nicht normalisieren Kontext und Grammatik gehen verloren Satzbau Wortformen

    (Deklination & Konjugation) … Eigene Strings für jeden Zweck “reset.counter.button” = “Auf 0 stellen” Kontext für Übersetzer
  18. Texte nicht normalisieren Kontext und Grammatik gehen verloren Satzbau Wortformen

    (Deklination & Konjugation) … Eigene Strings für jeden Zweck “reset.counter.button” = “Auf 0 stellen” Kontext für Übersetzer Sprechende Keys
  19. Texte nicht normalisieren Kontext und Grammatik gehen verloren Satzbau Wortformen

    (Deklination & Konjugation) … Eigene Strings für jeden Zweck “reset.counter.button” = “Auf 0 stellen” Kontext für Übersetzer Sprechende Keys Hinreichende Kommentare (Button vs. Label, ungefähre Länge etc.)
  20. Variablen Parameterposition dokumentieren! “Zeige 4 von 12 gesamt” “Total 12

    — Showing 4” /* … Param 1: current page; Param 2: total count */
 "current.page.label" = “Zeige %1d von %2d gesamt”;
 
 /* … Param 1: current page; Param 2: total count */
 "current.page.label" = “Total %2d — Showing %1d”;
  21. Sonderfälle 0 und 1 Plural Englisch Deutsch 0 No books

    Keine Bücher 1 One book Ein Buch sonstiges 100 books 100 Bücher Localizable.strings “books.0” = “No Books” “books.1” = “One Book” “books.n” = “%1d books” “books.0” = “Keine Bücher” “books.1” = “Ein Buch” “books.n” = “%1d Bücher” Abfrage im Code, Problem gelöst.
  22. Englisch Deutsch 0 No books Keine Bücher 1 1 book

    1 Buch Vielleicht nicht ganz… Plural
  23. Englisch Deutsch 0 No books Keine Bücher 1 1 book

    1 Buch 2 2 books 2 Bücher wenige 3 books 3 Bücher viele 11 books 11 Bücher sonstiges 100 books 100 Bücher Vielleicht nicht ganz… Plural
  24. 0 1 2 wenige viele sonstiges Englisch No books 1

    book 2 books 3 books 11 books 100 books Deutsch Keine Bücher 1 Buch 2 Bücher 3 Bücher 11 Bücher 100 Bücher Vielleicht nicht ganz… Plural
  25. 0 1 2 wenige viele sonstiges Englisch No books 1

    book 2 books 3 books 11 books 100 books Deutsch Keine Bücher 1 Buch 2 Bücher 3 Bücher 11 Bücher 100 Bücher Arabisch باتك ٠ باتك ناباتك بتك ٣ اًباتك ١١ باتك ١٠٠ Vielleicht nicht ganz… Plural
  26. .strings + .stringsdict Seit iOS7 Implementiert (Unicode*) Lokalisierungsregeln für Plural

    Geschlecht [rdar://16670931] * http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ar
  27. .strings + .stringsdict Seit iOS7 Implementiert (Unicode*) Lokalisierungsregeln für Plural

    Geschlecht [rdar://16670931] Plist Format Name identisch mit .strings .strings muss existieren, kann aber leer sein * http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ar
  28. .strings + .stringsdict https://developer.apple.com/library/ios/releasenotes/Foundation/↩︎ RN-Foundation/index.html#//apple_ref/doc/uid/TP30000742-CH2-SW56 <dict>
 <key>files.selected.label.%d</key>
 <dict>
 <key>NSStringLocalizedFormatKey</key>
 <string>%#@num_files_are@

    selected</string>
 <key>num_files_are</key>
 <dict>
 <key>NSStringFormatSpecTypeKey</key>
 <string>NSStringPluralRuleType</string>
 <key>NSStringFormatValueTypeKey</key>
 <string>d</string>
 <key>zero</key> <string>No file is</string>
 <key>one</key> <string>A file is</string>
 <key>other</key> <string>%d files are</string>
 </dict>
 </dict>
 </dict>
  29. .stringsdict Kategorien pro Sprache per Unicode „zero“ geht zusätzlich in

    iOS immer „few“ z. B. für deutsch nicht unterstützt
  30. String Tables Localizable.strings Default für NSLocalizedString() Große Projekte — große

    Datei Optional zerlegbar NSLocalizedStringFromTable(“MyController”, “Key”, “Comment”) MyController.strings Projektgliederung — Kontext für Übersetzer 3rd Party Code Analog für .stringsdict
  31. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA NSDateFormatter
  32. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA Short 08.07.14 22:32 7/8/14,10:32 PM NSDateFormatter
  33. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA Short 08.07.14 22:32 7/8/14,10:32 PM Medium 08.07.2014 22:32:36 Jul 8, 2014, 10:32:36 PM NSDateFormatter
  34. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA Short 08.07.14 22:32 7/8/14,10:32 PM Medium 08.07.2014 22:32:36 Jul 8, 2014, 10:32:36 PM Long 8. Juli 2014 22:32:36 MESZ Jul 8, 2014, 10:32:36 PM GMT+2 NSDateFormatter
  35. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA Short 08.07.14 22:32 7/8/14,10:32 PM Medium 08.07.2014 22:32:36 Jul 8, 2014, 10:32:36 PM Long 8. Juli 2014 22:32:36 MESZ Jul 8, 2014, 10:32:36 PM GMT+2 Full Dienstag, 8. Juli 2014 12:32:36 Mitteleuropäische Sommerzeit Tuesday, July 8, 2014 at 12:39:16 PM Central European Summer Time NSDateFormatter
  36. Datum und Zeit Konvertierung zwischen NSDate und NSString +[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]


    -[NSDateFormatter setLocale:] NSDateFormatterStyle Deutsch / Deutschland Englisch / USA Short 08.07.14 22:32 7/8/14,10:32 PM Medium 08.07.2014 22:32:36 Jul 8, 2014, 10:32:36 PM Long 8. Juli 2014 22:32:36 MESZ Jul 8, 2014, 10:32:36 PM GMT+2 Full Dienstag, 8. Juli 2014 12:32:36 Mitteleuropäische Sommerzeit Tuesday, July 8, 2014 at 12:39:16 PM Central European Summer Time No - - NSDateFormatter
  37. Datum und Zeit NSDateFormatter.h typedef enum {
 NSDateFormatterNoStyle = …,


    NSDateFormatterShortStyle = …,
 NSDateFormatterMediumStyle = …,
 NSDateFormatterLongStyle = …,
 NSDateFormatterFullStyle = …
 } NSDateFormatterStyle Kombinierbar für Datum und Zeit NSDateFormatterNoStyle — nur Datum / Zeit Aktualisierung durch OS Updates NSDateFormatter
  38. Datum und Zeit Und wenn die Defaults nicht reichen? NSDateFormatter

    * http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
  39. Datum und Zeit Und wenn die Defaults nicht reichen? Keine

    konkreten Format-Strings verwenden! NSDateFormatter * http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
  40. Datum und Zeit Und wenn die Defaults nicht reichen? Keine

    konkreten Format-Strings verwenden! Unicode Locale Data Markup Language* NSDateFormatter * http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
  41. Datum und Zeit Und wenn die Defaults nicht reichen? Keine

    konkreten Format-Strings verwenden! Unicode Locale Data Markup Language* [f setDateFormat:[NSDateFormatter
 dateFormatFromTemplate:@"u QQ" 
 options:0
 locale:LOCALE_EN_US]];
 
 NSLog(@“%@", [f stringFromDate:july8th); NSDateFormatter * http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
  42. Datum und Zeit Und wenn die Defaults nicht reichen? Keine

    konkreten Format-Strings verwenden! Unicode Locale Data Markup Language* [f setDateFormat:[NSDateFormatter
 dateFormatFromTemplate:@"u QQ" 
 options:0
 locale:LOCALE_EN_US]];
 
 NSLog(@“%@", [f stringFromDate:july8th); Q3 2014 NSDateFormatter * http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
  43. Relative Zeitangaben [formatter setDoesRelativeDateFormatting:YES];
 
 NSLog(@“%@, %@, %@…", [formatter stringFromDate:GESTERN],


    [formatter stringFromDate:HEUTE],
 [formatter stringFromDate:MORGEN]);
 Gestern, Heute, Morgen… [de_DE] Yesterday, Today, Tomorrow… [en_US] Gestern, Heute, Morgen…
  44. NSDateComponentsFormatter Darstellung von Zeitdauern [f stringFromTimeInterval:1234.0]) // seconds About 20

    minutes remaining NSDateIntervalFormatter Darstellung von Zeiträumen [f stringFromDate:NOW toDate:LATER]) 09.07.14 12:10-13:13 Coming up next: iOS8
  45. Zahlen NSNumberFormatter Deutsch / Deutschland Englisch / USA No 1234,56

    1234.56 Decimal 1.234,56 1,234.56 Currency 1.234,56 € $1,234.56 Percent 123.456% 123,456% Scientific 1,23456E+03 1.23456E3 SpellOut eintausendzweihundertvier- unddreißig Komma fünf sechs one thousand two hundred thirty- four point five six
  46. Zahlen NSNumberFormatter.h enum {
 NSNumberFormatterNoStyle = …,
 NSNumberFormatterDecimalStyle = …,


    NSNumberFormatterCurrencyStyle = …,
 NSNumberFormatterPercentStyle = …,
 NSNumberFormatterScientificStyle = …,
 NSNumberFormatterSpellOutStyle = …
 }
 typedef NSUInteger NSNumberFormatterStyle
  47. Zahlen NSNumberFormatter* f = [[NSNumberFormatter alloc] init];
 f.numberStyle = NSNumberFormatterNoStyle;

    f.locale = LOCALE_DE_AT;
 NSLog(@"NoStyle de_AT: %@", [f stringFromNumber:@(1234.56)]); f.locale = LOCALE_EN_US;
 f.maximumFractionDigits = 2;
 NSLog(@“NoStyle en_US: %@", [f stringFromNumber:@(1234.56)]); NSNumberFormatter
  48. Zahlen NSNumberFormatter* f = [[NSNumberFormatter alloc] init];
 f.numberStyle = NSNumberFormatterNoStyle;

    f.locale = LOCALE_DE_AT;
 NSLog(@"NoStyle de_AT: %@", [f stringFromNumber:@(1234.56)]); f.locale = LOCALE_EN_US;
 f.maximumFractionDigits = 2;
 NSLog(@“NoStyle en_US: %@", [f stringFromNumber:@(1234.56)]); NoStyle de_AT: 1235 NoStyle en_US: 1234.56 NSNumberFormatter
  49. Coming up next: iOS8 NSEnergyFormatter Energie in Joule, Kalorien etc.

    NSLengthFormatter Distanzen, in Meilen, Kilometer etc. NSMassFormatter Masse und Gewicht in Pfund, kg etc.
  50. Launch Image Asset Catalogue abschalten Launch Images in .lproj Ordner

    Typische Namenskonventionen Retina Orientierung Gerätetyp
  51. Weitere Schritte Bildressourcen Launch Images (sofern relevant) Adressen, Namen Right-to-Left

    Support Automatische Auswahl von Einheiten (Meilen, km etc.) Vorbelegung für Auswahllisten etc. Farbschemata …
  52. Fazit Initialer Aufwand ggf. erheblich Komplette Übersetzung Codeanpassung Workflow und

    Toolauswahl Andauernde Pflege überschaubar Zielgruppenrelevanz betrachten