The document discusses localization of mobile apps. It begins with an overview of internationalization (I18N) versus localization (L10N), and how I18N is the process of making an app adaptable to other languages/regions without changes, while L10N is the process of adapting an I18N app for a specific language/region. It then covers specific aspects of localization including text, date/time formatting, numbers, and images/resources. Key aspects discussed are using localized strings files, NSLocale for region settings, and NSDateFormatter for date/time formatting that adjusts based on locale.
8. Internationalization
[…] process of designing a software application so that it
can potentially be adapted to various languages and
regions without engineering changes. […]*
* Wikipedia
10. Localization
[…] the process of adapting internationalized software for
a specific region or language by adding locale-specific
components and translating text. […]*
* Wikipedia
14. Languages and Regions
Language ≠ Region
12h time used by an American living in Germany
„Jänner“ – „Januar“ [German in Austria vs. in Germany for January]
Localization ≠ Locale
German user might prefer English user interface texts
But: 24h time display
21. NSLocale
Does not contain the current language!
Locale ≠ Localization
[NSBundle mainBundle].localizations; // NSArray, (all)
[NSBundle mainBundle].preferredLocalizations[0]; // (current)
Caveats
Localizations of InfoPlist.strings determine content of „localizations“
Intersected with user’s region preferences in Settings.app
AppleLanguages launch parameter
25. Text ≠ Text
Language of messages, buttons, labels etc.
Writing direction & alignment
Writing systems (Latin, Hebrew, Arabic…)
Numbers in text
Names & addresses
Phrases, idioms and terminology
Plurals
Sorting
…
26. Text ≠ Text
Language of messages, buttons, labels etc.
Writing direction & alignment
Writing systems (Latin, Hebrew, Arabic…)
Numbers in text
Names & addresses
Phrases, idioms and terminology
Plurals
Sorting
…
44. .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
51. Do not normalize text
Context and grammar are lost
Structure of sentences
52. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
53. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
Use dedicated strings per use case
54. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
Use dedicated strings per use case
“reset.counter.button” = “Auf 0 stellen”
55. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
Use dedicated strings per use case
“reset.counter.button” = “Auf 0 stellen”
Context for translators
56. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
Use dedicated strings per use case
“reset.counter.button” = “Auf 0 stellen”
Context for translators
Use self explanatory keys
57. Do not normalize text
Context and grammar are lost
Structure of sentences
Declination & conjugation …
Use dedicated strings per use case
“reset.counter.button” = “Auf 0 stellen”
Context for translators
Use self explanatory keys
Provide useful comments (button vs. label, approx. length, etc.)
59. Variables
Document parameter order!
“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”;
60. Special cases: 0 and 1
Plurals
Englisch German
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”
If-else-clause in the code: Problem solved.
61. Englisch Deutsch
0 No books Keine Bücher
1 1 book 1 Buch
Vielleicht nicht ganz…
Plural
62. 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
67. .strings + .stringsdict
Available since iOS7
Implements (Unicode*) localization rules for
Plural
Gender [rdar://16670931]
* http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ar
68. .strings + .stringsdict
Available since iOS7
Implements (Unicode*) localization rules for
Plural
Gender [rdar://16670931]
Plist Format
Name must match .strings
.strings must exist, but may be empty
* http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ar
70. .stringsdict
Categories per language according to Unicode
iOS additionally supports„zero“ category for all languages
Others, e. g.„few“, depend on language
71. String Tables
Localizable.strings
Default used by NSLocalizedString()
Big projects — big file
Can be split
NSLocalizedStringFromTable(“MyController”,“Key”,“Comment”)
MyController.strings
Project structure — Context for translators
3rd party code
Also works for .stringsdict
74. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatter
75. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
NSDateFormatter
76. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany Englisch / USA
NSDateFormatter
77. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany Englisch / USA
Short 08.07.14 22:32 7/8/14,10:32 PM
NSDateFormatter
78. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany 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
79. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany 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
80. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany 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
81. Date and Time
Transforms between NSDate and NSString
+[NSDateFormatter localizedStringFromDate:dateStyle:timeStyle:]
-[NSDateFormatter setLocale:]
NSDateFormatterStyle
German / Germany 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
82. Date and Time
NSDateFormatter.h
typedef enum {
NSDateFormatterNoStyle = …,
NSDateFormatterShortStyle = …,
NSDateFormatterMediumStyle = …,
NSDateFormatterLongStyle = …,
NSDateFormatterFullStyle = …
} NSDateFormatterStyle
Combine for date and time portions
NSDateFormatterNoStyle — only date / time
Get updated with the OS
NSDateFormatter
83. Date and Time NSDateFormatter
* http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
84. Date and Time
What if defaults are not suitable?
NSDateFormatter
* http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
85. Date and Time
What if defaults are not suitable?
Do not use hard coded format strings!
NSDateFormatter
* http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
86. Date and Time
What if defaults are not suitable?
Do not use hard coded format strings!
Unicode Locale Data Markup Language*
NSDateFormatter
* http://www.unicode.org/reports/tr35/tr35-dates.html#Contents
87. Date and Time
What if defaults are not suitable?
Do not use hard coded format strings!
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
88. Date and Time
What if defaults are not suitable?
Do not use hard coded format strings!
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
96. Numbers NSNumberFormatter
German / Germany English / 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
101. Numbers
Many more customization options
maximumFractionDigits
usesSignificantDigits
minimum/maximumSignificantDigits
paddingCharacter
roundingMode, roundingIncrement
…
NSNumberFormatter
102. Data Volume
NSByteCountFormatter
File size, amount of memory
Picks suitable unit automatically
Non-numeric display
Allow Non-Numeric Zero KB
File 1,234.57 GB
Memory 1,149.78 GB
103. Coming up next: iOS8
NSEnergyFormatter
Energy in joule, calories etc.
NSLengthFormatter
Distance, in miles, kilometers etc.
NSMassFormatter
Mass and weight in pounds, kg etc.
111. Cover the Basics
Locale based formatting
NSDateFormatter
NSNumberFormatter
NSByteCountFormatter
Careful and diligent translation
Remember resources besides the source code
112. Next Steps
Images resources
Launch Images (if relevant)
Addresses, names
Right-to-left support
Location based pre-selection of units (miles, km etc.)
Pre-selection for pickers, options etc.
Color scheme
…
113. Summary
Initialer effort can be significant
Full translation
Code refactoring
Create workflows and pick tools
Ongoing maintenance rather easy
Consider relevance of individual measures for your
audience