• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Language and Locale
2page.tags=androidn
3page.image=images/cards/card-nyc_2x.jpg
4
5@jd:body
6
7<div id="qv-wrapper">
8<div id="qv">
9<h2>In this document:</h2>
10<ol>
11	  <li><a href="#preN">Challenges in Resolving Language Resources</a></li>
12    <li><a href="#postN">Improvements to Resource-Resolution Strategy</a></li>
13    <li><a href="#design">Designing your App to Support Additional
14      Locales</a></li>
15
16</ol>
17
18</div>
19</div>
20
21<p>Starting in Android 7.0 (API level 24),
22Android provides enhanced support for multilingual users,
23allowing them to select multiple locales in settings. Android
24provides this capability by greatly expanding the number of locales supported
25and changing the way the system resolves resources.</p>
26
27<p>This document starts by explaining the resource resolution strategy in
28versions of Android lower than 7.0 (API level 24). Next, it describes
29the improved resource-resolution strategy in Android 7.0.
30Last, it explains how to take advantage of
31the expanded number of locales to support more multilingual users.</p>
32
33<h2 id="preN">Challenges in Resolving Language Resources</h2>
34
35<p>Prior to Android 7.0, Android could not always successfully
36 match app and system locales.</p>
37
38 <p>For example, assume that you have the following situation:</p>
39 <ul>
40 <li>Your app's default language is {@code en_US} (US English), and it also has
41  Spanish strings localized in {@code es_ES}
42  resource files.</li>
43 <li> A device is set to {@code es_MX} </li>
44
45<p>When your Java code refers to strings, the system would load
46strings from the default ({@code en_US}) resource file, even if the app has
47Spanish resources localized under {@code es_ES}. This is because when the system
48 cannot find an exact match, it continues to look for resources by stripping the
49 country code off the locale. Finally, if no match is found, the system falls
50 back to the default, which is {@code en_US}. </p>
51
52
53<p>The system would also default to {@code en_US} if the user chose a language that
54the app didn't support at all, like French. For example:</p>
55
56<p class="table-caption" id="t-resource-res">
57<strong>Table 1.</strong> Resource resolution without an exact locale match.
58</p>
59<table>
60<tbody>
61<tr>
62<th>User Settings</th>
63<th>App Resources</th>
64<th>Resource Resolution</th>
65</tr>
66<tr>
67<td>fr_CH</td>
68<td>
69default (en)<br>
70de_DE<br>
71es_ES<br>
72fr_FR<br>
73it_IT<br>
74</td>
75 <td>
76Try fr_CH =&gt; Fail<br>
77Try fr =&gt; Fail<br>
78Use default (en)
79</td>
80 </tr>
81 </tbody>
82</table>
83
84
85<p>In this example, the system displays English strings without
86knowing whether the user can understand English. This behavior is pretty common
87today.</p>
88
89<h2 id="postN">Improvements to Resource-Resolution Strategy</h2>
90<p>Android 7.0 (API level 24) brings more robust resource resolution, and
91 finds better fallbacks automatically. However, to speed up resolution and
92 improve
93 maintainability, you should store resources in the most common parent dialect.
94 For example, if you were storing Spanish resources in the {@code es-US}
95 directory
96 before, move them into the {@code es-419} directory, which contains Latin
97 American Spanish.
98 Similarly, if you have resource strings in a folder named {@code en-GB}, rename
99 the folder to {@code en-001} (international English), because the most common
100 parent for <code>en-GB</code> strings is {@code en-001}.
101 The following examples explain why these practices improve performance and
102reliability of resource resolution.</p>
103
104<h3>Resource resolution examples</h3>
105
106<p>With versions of Android greater than 7.0, the case described in
107	<strong>Table 1</strong> is resolved differently:</p>
108
109<p class="table-caption" id="t-improved-res">
110<strong>Table 2.</strong> An improved resolution strategy for when there is no
111exact locale match.</p>
112<table>
113<tr>
114<th>User Settings</th>
115<th>App Resources</th>
116<th>Resource Resolution</th>
117</tr>
118<tr>
119<td><ol>
120<li> fr_CH</li>
121</ol>
122</td>
123<td>
124default (en)<br>
125de_DE<br>
126es_ES<br>
127fr_FR<br>
128it_IT<br>
129</td>
130<td>
131Try fr_CH =&gt; Fail<br>
132Try fr =&gt; Fail<br>
133Try children of fr =&gt; fr_FR<br>
134Use fr_FR
135</td>
136</tr>
137
138</table>
139
140
141<p>Now the user gets French resources instead of English. This example also shows
142 why you should store French strings in {@code fr} rather than {@code fr_FR}
143 for Android 7.0 or higher. Here the course of action is
144 to match the closest parent dialect,
145 making resolution faster and more predictable.</p>
146
147<p>In addition to this improved resolution logic, Android now offers more
148 user languages to choose from. Let’s try the above example again with Italian
149 specified as an additional user language, but without app support for French.  </p>
150
151<p class="table-caption" id="t-2d-choice">
152<strong>Table 3.</strong> Resource resolution when the app only matches the
153user's second-preferred locale setting.</p>
154<table>
155<tr>
156<th>User Settings</th>
157<th>App Resources</th>
158<th>Resource Resolution</th>
159
160</tr>
161<tr>
162<td><ol>
163<li> fr_CH</li>
164<li> it_CH</li>
165</ol>
166</td>
167<td>
168default (en)<br>
169de_DE<br>
170es_ES<br>
171it_IT<br>
172</td>
173<td>
174Try fr_CH =&gt; Fail<br>
175Try fr =&gt; Fail<br>
176Try children of fr =&gt; Fail<br>
177Try it_CH =&gt; Fail<br>
178Try it =&gt; Fail<br>
179Try children of it =&gt; it_IT<br>
180Use it_IT
181</td>
182
183</tr>
184
185</table>
186<p>
187  The user still gets a language they understand, even though the app doesn’t
188  support French.
189</p>
190
191
192<h2 id="design">Designing your App to Support Additional Locales</h2>
193<h3>LocaleList API</h3>
194
195<p>
196  Starting with Android 7.0 (API level 24), Android exposes the
197  {@code LocaleList.getDefault()} API
198  that lets apps directly query the list of languages a user has specified. This API
199  allows you to create more sophisticated
200  app behavior and better-optimized display of content. For example, Search
201  can show results in multiple languages based on user’s settings.  Browser apps
202  can avoid offering to translate pages in a language the user already knows,
203  and keyboard apps can auto-enable all appropriate layouts.
204</p>
205
206<h3>Formatters</h3>
207
208<p>
209  Up through Android 6.0 (API level 23), Android supported only one or
210  two locales
211  for many common languages
212  (en, es, ar, fr, ru). Because there were only a few variants of each language,
213  apps could get away with storing some numbers and dates as hard coded strings
214  in resource files.  However, with Android's broadened set of supported
215  locales, there can be
216  significant differences in formats for dates, times, currencies, and similar
217  information even within a single locale. Hard-coding your formats can produce
218  a confusing experience for end users.
219  Therefore, when developing for Android 7.0 or higher versions,
220  make sure to use formatters instead of hard coding numbers and date strings.</p>
221
222<p>
223  For example, Android 7.0 and higher includes support for
224  27 Arabic locales. These locales can share most resources,
225  but some prefer ASCII digits, while others prefer native digits. For example,
226  when you want to create a sentence with a digit variable, such as
227  "Choose a 4 digit pin", use formatters as shown below:
228</p>
229
230<pre> format(locale, "Choose a %d-digit PIN", 4)</pre>
231