Android apps are global, they get downloaded all around the world. And this means not only supporting multiple languages via xml files. Its about plurals, date formats, currencies up to things like right-to-left
This topic tries to give an introduction into this large topic for new developers.
3. #droidconzg #PreusslerBerlin
Definitions
Page 3
Internationalization (i18n) is the process of developing products in such a way
that they can be localized for languages and cultures easily.
Localization (l10n), is the process of adapting applications and text to enable
their usability in a particular cultural or linguistic market.
(docs.angularjs.org)
The better internationalized an application is, the easier it is to localize it for
a particular language and character encoding scheme.
(docs.oracle.com)
The main concern (i18n) is that application can be adapted to various
languages and regions without engineering changes.
(Apple Guidelines)
4. #droidconzg #PreusslerBerlin
Try not to kill your user...
Page 4
„A Cellphone's Missing Dot Kills Two People, Puts Three More in Jail“
http://gizmodo.com/382026/a-cellphones-missing-dot-kills-two-people-puts-
three-more-in-jail
5. #droidconzg #PreusslerBerlin
Locales
Page 5
• Never hardcode text in code or layouts!
(android studio even helps extracting to strings.xml)
• If needed for layouts use the tools namespace
also good for testing long texts:
• Never hardcode text in images
<TextView
android:id="@+id/deal“
android:text="@string/deal_title“
tools:text="deal of killing 2 zombie for one“/>
9. #droidconzg #PreusslerBerlin
Strings
Page 9
Don’t concatenate strings!
• Order might change in other language for grammar
• Dangerous in Right-to-Left
TextView textView = ...
textView.setText(" לחץכאן " + ">");
a) לחץכאן >
b) > לחץכאן
c) < לחץכאן
10. #droidconzg #PreusslerBerlin
Strings
Page 10
Don’t concatenate strings!
• Order might change in other language for grammar
• Dangerous in Right-to-Left
TextView textView = ...
textView.setText(" לחץכאן " + ">");
a) לחץכאן >
b) > לחץכאן
c) < לחץכאן
11. #droidconzg #PreusslerBerlin
Strings
Page 11
Don’t concatenate strings!
• Use Formatter.format
• Yes even for numbers!
• Or better: Use Phrase from Square
Phrase.from(
"Hi {first_name}, you are {age} years old.")
.put("first_name", firstName)
.put("age", age)
.format();
format(locale, "Choose a %d-digit PIN", 4)
13. #droidconzg #PreusslerBerlin
Locales
Page 13
• Don’t reuse your strings too often.
Same names for different things might be different names on other
languages
• Provide context to translator
• Be aware: texts have different length in different languages,
English tends to be short, Finnish or German tend to be very long
• Different line-heights, careful with custom fonts or cropping views in height
17. #droidconzg #PreusslerBerlin
Numbers
Page 17
The decimal mark: Dot vs. Comma
1.00$
vs
1,00€
With delimiters:
4,294,967,295.00
vs
4 294 967.295,000
In 1958, disputes between European and American delegates over the correct
representation of the decimal mark nearly stalled the development of the ALGOL
computer programming language. (wikipedia)
21. #droidconzg #PreusslerBerlin
Currencies
Page 21
• WHICH symbols, if ANY
• WHERE to put the symbol (front or back)?
• How many digits after comma/dot?
0-3 are common
• Represent currencies in the Currency class ;-)
NumberFormat.getCurrencyInstance(Locale);
22. #droidconzg #PreusslerBerlin
Currencies
Page 22
• Never ever use floating point numbers (float or double)
for Money!
Floats are broken by design (for representing money)
IEEE 754:
it is impossible to represent 0.1 (or any other negative
power of ten)
System.out.println(1.03 - .42);
>>> 0.6100000000000001
(Bloch, J., Effective Java, 2nd ed)
• Use BigDecimal and the String(!) constructor
• Check Martin Fowlers Money pattern class
25. #droidconzg #PreusslerBerlin
Dates
Page 25
• Careful with calculations and comparison (be aware of DST jumps)
public static Date getYesterday(Date from) {
Calendar c = getCalendarFor(from);
c.add(Calendar.DAY_OF_THE_MONTH, -1);
return c.getTime();
}
public static Date getYesterday(Date from) {
return new Date(from.getTime() - (24*60*60*1000));
}
26. #droidconzg #PreusslerBerlin
Dates
Page 26
DateFormat
Careful with custom formats, try to use the standard java one else “pm” might
show up to “nachmittag”
DateFormat.getDateInstance(DateFormat.LONG)
DateFormat.getDateTimeInstance(
DateFormat.SHORT, DateFormat.SHORT);
27. #droidconzg #PreusslerBerlin
Dates
Page 27
android.text.format.DateUtils
• Has nice methods like:
isToday()
formatDateRange()
getRelativeTimeSpanString() “5 minutes ago”
• Check out joda-time-android
https://github.com/dlew/joda-time-android
(don’t use normal Java joda-time!
because of GetResourceAsStream performance issue on Android)
32. #droidconzg #PreusslerBerlin
The signs are in greek by Karl Baron,
flickr.com/photos/kalleboo/6624480775
Dubai Airport #1 by emi emi, CC by 2.0;
flickr.com/photos/emi_b/4793218993
35. #droidconzg #PreusslerBerlin
Right To Left
• Replace left/right with start/end
• Manifest flag:
android:supportsRtl="true"
• Check your images and correct in xml drawable:
android:autoMirrored=“true/false“
• Set margins to both sides
35
I18n enables l10n
I18n: unicode
L10n: currencie support
I18n: using resource strings
L10n: adding multiple string.xml
Used to kill by viZZZual.com, flickr.com/photos/vizzzual-dot-com/2424064848
Eastern Arabic numerals
In 1958, disputes between European and American delegates over the correct representation of the decimal mark nearly stalled the development of the ALGOL computer programming language.[13] ALGOL ended up allowing different decimal marks, but most computer languages and standard data formats (e.g. C, Java, Fortran, Cascading Style Sheets (CSS)) specify a dot.