2016-03-03 13:55:00 -08:00
|
|
|
|
page.title=Language and Locale
|
2016-02-24 18:06:44 -08:00
|
|
|
|
@jd:body
|
|
|
|
|
|
2016-03-08 22:32:51 -08:00
|
|
|
|
<div id="qv-wrapper">
|
|
|
|
|
<div id="qv">
|
2016-02-24 18:06:44 -08:00
|
|
|
|
<h2>In this document:</h2>
|
|
|
|
|
<ol>
|
|
|
|
|
<li><a href="#preN">Challenges in Resolving Language Resources</a></li>
|
|
|
|
|
<li><a href="#postN">Improvements to Resource-Resolution Strategy</a></li>
|
|
|
|
|
<li><a href="#design">Designing your App to Support Additional
|
|
|
|
|
Locales</a></li>
|
|
|
|
|
|
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2016-03-07 22:13:29 -08:00
|
|
|
|
<p>Android N provides enhanced support for multilingual users,
|
|
|
|
|
allowing them to select multiple locales in settings. Android N
|
2016-02-24 18:06:44 -08:00
|
|
|
|
provides this capability by greatly expanding the number of locales supported
|
|
|
|
|
and changing the way the system resolves resources. The new method of resolving
|
|
|
|
|
resources is more robust and designed to be compatible with existing APKs, but
|
|
|
|
|
you should take extra care to spot any unexpected behavior. For example, you
|
|
|
|
|
should test to make sure that your app defaults to the expected language. Also,
|
2016-03-05 16:13:00 -08:00
|
|
|
|
if your app supports multiple languages, you should ensure that this support works as
|
|
|
|
|
intended. Finally, you should try to ensure that your app gracefully handles
|
2016-02-24 18:06:44 -08:00
|
|
|
|
languages that you didn't explicitly design it to support.</p>
|
|
|
|
|
|
|
|
|
|
<p>This document starts by explaining the resource resolution strategy prior to
|
2016-03-07 22:13:29 -08:00
|
|
|
|
Android N. Next, it describes Android N's improved
|
2016-02-24 18:06:44 -08:00
|
|
|
|
resource-resolution strategy. Last, it explains how to take advantage of
|
|
|
|
|
the expanded number of locales to support more multilingual users.</p>
|
|
|
|
|
|
|
|
|
|
<h2 id="preN">Challenges in Resolving Language Resources</h2>
|
|
|
|
|
|
2016-03-07 22:13:29 -08:00
|
|
|
|
<p>Prior to Android N, Android could not always successfully
|
2016-03-14 14:35:28 -07:00
|
|
|
|
match app and system locales.</p>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
|
2016-03-14 14:35:28 -07:00
|
|
|
|
<p>For example, assume that you have the following situation:</p>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Your app's default language is {@code en_US} (US English), and it also has
|
|
|
|
|
Spanish strings localized in {@code es_ES}
|
|
|
|
|
resource files.</li>
|
|
|
|
|
<li> A device is set to {@code es_MX} </li>
|
|
|
|
|
|
|
|
|
|
<p>When your Java code refers to strings, the system would load
|
|
|
|
|
strings from the default ({@code en_US}) resource file, even if the app has
|
|
|
|
|
Spanish resources localized under {@code es_ES}. This is because when the system
|
|
|
|
|
cannot find an exact match, it continues to look for resources by stripping the
|
|
|
|
|
country code off the locale. Finally, if no match is found, the system falls
|
|
|
|
|
back to the default, which is {@code en_US}. </p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<p>The system would also default to {@code en_US} if the user chose a language that
|
|
|
|
|
the app didn't support at all, like French. For example:</p>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
|
|
|
|
|
<p class="table-caption" id="t-resource-res">
|
|
|
|
|
<strong>Table 1.</strong> Resource resolution without an exact locale match.
|
|
|
|
|
</p>
|
|
|
|
|
<table>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>User Settings</th>
|
|
|
|
|
<th>App Resources</th>
|
|
|
|
|
<th>Resource Resolution</th>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>fr_CH</td>
|
|
|
|
|
<td>
|
|
|
|
|
default (en)<br>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
de_DE<br>
|
|
|
|
|
es_ES<br>
|
|
|
|
|
fr_FR<br>
|
|
|
|
|
it_IT<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
Try fr_CH => Fail<br>
|
|
|
|
|
Try fr => Fail<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
Use default (en)
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
2016-03-05 16:13:00 -08:00
|
|
|
|
<p>In this example, the system displays English strings without
|
2016-02-24 18:06:44 -08:00
|
|
|
|
knowing whether the user can understand English. This behavior is pretty common
|
2016-03-07 22:13:29 -08:00
|
|
|
|
today. Android N should substantially reduce the frequency
|
2016-02-24 18:06:44 -08:00
|
|
|
|
of outcomes like this one.</p>
|
|
|
|
|
|
|
|
|
|
<h2 id="postN">Improvements to Resource-Resolution Strategy</h2>
|
2016-03-07 22:13:29 -08:00
|
|
|
|
<p>Android N brings more robust resource resolution, and
|
2016-02-24 18:06:44 -08:00
|
|
|
|
finds better fallbacks automatically. However, to speed up resolution and improve
|
|
|
|
|
maintainability, you should store resources in the most common parent dialect.
|
|
|
|
|
For example, if you were storing Spanish resources in the {@code es-US} directory
|
|
|
|
|
before, move them into the {@code es-419} directory, which contains Latin American Spanish.
|
|
|
|
|
Similarly, if you have resource strings in a folder named {@code en-GB}, rename
|
|
|
|
|
the folder to {@code en-001} (international English), because the most common
|
|
|
|
|
parent for <code>en-GB</code> strings is {@code en-001}.
|
|
|
|
|
The following examples explain why these practices improve performance and
|
|
|
|
|
reliability of resource resolution.</p>
|
|
|
|
|
|
|
|
|
|
<h3>Resource resolution examples</h3>
|
|
|
|
|
|
2016-03-07 22:13:29 -08:00
|
|
|
|
<p>With Android N, the case described in <strong>Table 1</strong> is resolved
|
2016-02-24 18:06:44 -08:00
|
|
|
|
differently:</p>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
|
2016-02-24 18:06:44 -08:00
|
|
|
|
<p class="table-caption" id="t-improved-res">
|
|
|
|
|
<strong>Table 2.</strong> An improved resolution strategy for when there is no
|
|
|
|
|
exact locale match.</p>
|
|
|
|
|
<table>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>User Settings</th>
|
|
|
|
|
<th>App Resources</th>
|
|
|
|
|
<th>Resource Resolution</th>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><ol>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
<li> fr_CH</li>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
</ol>
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
default (en)<br>
|
|
|
|
|
de_DE<br>
|
|
|
|
|
es_ES<br>
|
|
|
|
|
fr_FR<br>
|
|
|
|
|
it_IT<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
Try fr_CH => Fail<br>
|
|
|
|
|
Try fr => Fail<br>
|
|
|
|
|
Try children of fr => fr_FR<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
Use fr_FR
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<p>Now the user gets French resources instead of English. This example also shows
|
|
|
|
|
why you should store French strings in {@code fr} rather than {@code fr_FR}
|
|
|
|
|
for Android N. Here the course of action is to match the closest parent dialect,
|
|
|
|
|
making resolution faster and more predictable.</p>
|
|
|
|
|
|
|
|
|
|
<p>In addition to this improved resolution logic, Android now offers more
|
|
|
|
|
user languages to choose from. Let’s try the above example again with Italian
|
|
|
|
|
specified as an additional user language, but without app support for French. </p>
|
|
|
|
|
|
|
|
|
|
<p class="table-caption" id="t-2d-choice">
|
|
|
|
|
<strong>Table 3.</strong> Resource resolution when the app only matches the
|
|
|
|
|
user's second-preferred locale setting.</p>
|
|
|
|
|
<table>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>User Settings</th>
|
|
|
|
|
<th>App Resources</th>
|
|
|
|
|
<th>Resource Resolution</th>
|
|
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><ol>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
<li> fr_CH</li>
|
|
|
|
|
<li> it_CH</li>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
</ol>
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
default (en)<br>
|
|
|
|
|
de_DE<br>
|
|
|
|
|
es_ES<br>
|
|
|
|
|
it_IT<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2016-03-05 16:13:00 -08:00
|
|
|
|
Try fr_CH => Fail<br>
|
|
|
|
|
Try fr => Fail<br>
|
|
|
|
|
Try children of fr => Fail<br>
|
|
|
|
|
Try it_CH => Fail<br>
|
|
|
|
|
Try it => Fail<br>
|
|
|
|
|
Try children of it => it_IT<br>
|
2016-02-24 18:06:44 -08:00
|
|
|
|
Use it_IT
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
|
|
</table>
|
|
|
|
|
<p>The user still gets a language they understand, even though the app doesn’t
|
|
|
|
|
support French.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h2 id="design">Designing your App to Support Additional Locales</h2>
|
|
|
|
|
<h3>LocaleList API</h3>
|
|
|
|
|
|
2016-04-06 15:40:03 -07:00
|
|
|
|
<p>Android N adds a new API {@code LocaleList.getDefault()}
|
2016-02-24 18:06:44 -08:00
|
|
|
|
that lets apps directly query the list of languages a user has specified. This API
|
|
|
|
|
allows you to create more sophisticated
|
|
|
|
|
app behavior and better-optimized display of content. For example, Search
|
|
|
|
|
can show results in multiple languages based on user’s settings. Browser apps
|
|
|
|
|
can avoid offering to translate pages in a language the user already knows,
|
|
|
|
|
and keyboard apps can auto-enable all appropriate layouts. </p>
|
|
|
|
|
|
|
|
|
|
<h3>Formatters</h3>
|
|
|
|
|
|
|
|
|
|
<p>Up through Android 6.0 (API level 23), Android supported only one or two locales
|
|
|
|
|
for many common languages
|
|
|
|
|
(en, es, ar, fr, ru). Because there were only a few variants of each language,
|
|
|
|
|
apps could get away with storing some numbers and dates as hard coded strings
|
|
|
|
|
in resource files. However, with Android's broadened set of supported locales,
|
|
|
|
|
there can be
|
|
|
|
|
significant differences in formats for dates, times, currencies, and similar
|
|
|
|
|
information even within a single locale. Hard-coding your formats can produce a
|
|
|
|
|
confusing experience for end users. Therefore, when developing for Android N
|
|
|
|
|
make sure to use formatters instead of hard coding numbers and date strings.</p>
|
|
|
|
|
|
2016-03-07 22:13:29 -08:00
|
|
|
|
<p>A prime example is Arabic, whose support Android N expands from
|
2016-02-24 18:06:44 -08:00
|
|
|
|
one {@code ar_EG} to 27 Arabic locales. These locales can share most resources,
|
|
|
|
|
but some prefer ASCII digits, while others prefer native digits. For example,
|
|
|
|
|
when you want to create a sentence with a digit variable, such as
|
|
|
|
|
"Choose a 4 digit pin", use formatters as shown below:</p>
|
|
|
|
|
|
|
|
|
|
<pre> format(locale, "Choose a %d-digit PIN", 4)</pre>
|