This document describes the current state of Android implementation of the ECMAScript Internationalization API Specification (ECMA-402, or
Intl). ECMA-402 is still evolving and the latest iteration is 7th edition which was published in June 2020. Each new edition is built on top of the last one and adds new capabilities typically as,
Intlservice constructors (e.g.
Intl.NumberFormatetc.) or extending existing ones by accepting more parameters
- New functions or properties in
One popular implementation strategy followed by other engines, is to bundle an internationalization framework (typically ICU) along with the application package. This guarantees deterministic behaviours at the cost of applications package bloat. We decided to consume the Android platform provided facilities for space efficiency, but at the cost of some variance in behaviours across Android platforms.
Not yet supported
formatMatcherparameter is not respected. The parameter enables the implementation to pick the best display format when it supports only a subset of all possible formats. ICU library in Android platform and hence our implementation allows all subsets and formats which makes this
Limitations across Android SDKs
- The keys of the object returned by
resolvedOptionsfunction in all
Intlservices are not deterministically ordered as prescribed by spec.
- DateFormat: ECMAScript beginning of time (-8,640,000,000,000,000), is formatted as
November 271817, instead of expected
Intl.NumberFormatimplementation has some rough edges in supporting the following properties,
Android 10 and older (SDK < 30)
Intl.NumberFormat: Scientific notation formatting has issues on some cases. e.g.
-Infinitymay get formatted as '-∞E0' instead of expected '-∞'. Another manifestation of the issues is that the formatToParts may return 4 parts instead of 2.
Intl.NumberFormat: Compact notation
formatToPartsdoesn't identify unit, hence we report unit as 'literal'. For e.g. the second part of "100ac" gets reported as "literal" instead of "compact"
Android 9 and older (SDK < 29)
- There are some failures likely due to older Unicode and CLDR version, which are hard to generalize. Some examples are,
Intl.NumberFormat: 'Percent' is not accepted as a unit.
Intl.NumberFormat: unit symbols difference, kph vs km/h
- Some issue in significant digit precision, which is not yet looked into the details.
Android 8.0 – 8.1 and older (SDK < 28)
Intl.getCanonicalLocales: Unicode/CLDR version differences results in some variances. e.g. und-u-tz-utc vs. und-u-tz-gmt.
Intl.NumberFormat: CompactFormatter doesn't respect the precision inputs.
Android 7.0 - 7.1 and older (SDK < 26)
Intl.getCanonicalLocales: Unicode/CLDR version differences results in some variances. e.g. und-u-ms-imperial vs. und-u-ms-uksystem.
Android 7.0 - 7.1 and older (SDK < 24)
Intl.Collator: Doesn't canonically decompose the input strings. Canonically equivalent string with non-identical code points may not match.
Intl.getCanonicalLocales: Unicode/CLDR version differences results in some variances. e.g. und-u-ca-ethiopic-amete-alem vs. und-u-ca-ethioaa, und-u-ks-primary vs. und-u-ks-level1.
Intl.NumberFormat: Unit style does not work.
Intl.NumberFormat: There are issues in the precision configuration due to lack of APIs.
Intl.DateFormat: There are issues with the calendar configuration which needs to be dug into.
SDK < 21 and older
On platforms before 21,
Locale.forLanguageTag() is not available, hence we can't construct
java.util.Locale object from locale tag. Hence, we fallback to English for any locale input.
Internationalization framework in Android Platform
Our implementation is essentially projecting the Android platform provided internationalization facilities through the ECMA-402 specified services. It implies that the results of running the same code may vary between devices running different versions of Android.
Android platform internationalization libraries have been based on ICU4j project. Version of ICU4j and the backing CLDR data varies across Android platform versions. Also, the ICU APIs were never exposed directly, but only through wrappers and aliases. This results in significant variance in internationalization API surface and data across platform versions.
The following table summarizes ICU, CLDR and Unicode versions available on the Android platforms.
Platform 24+ where ICU4j APIs are available.
|Android Platform Version||ICU||Unicode||CLDR|
|Android 11 (API level 30)||ICU4J 66.1 (ref)||Unicode 13 beta||CLDR 36.1|
|Android 10 (API level 29)||ICU4j 63.2 (ref)||CLDR 34||Unicode 11.0|
|Android 9 (API level 28)||ICU4j 60.2 (ref)||CLDR 32.0.1||Unicode 10.0|
|Android 8.0 - 8.1 (API levels 26 - 27)||ICU4j 58.2( ref)||CLDR 30.0.3||Unicode 9.0|
|Android 7.0 - 7.1 (API levels 24 - 25)||ICU4j 56 (ref)||CLDR 28||Unicode 8.0|
|Android Platform Version||ICU||Unicode||CLDR|
|Android 6.0 (API level 23)||ICU4j 55.1 (ref)||CLDR 27.0.1||Unicode 7.0|
|Android 5.0 (API levels 21–22)||ICU4j 53 (ref)||CLDR 25||Unicode 6.3|
|Android 4.4 (API levels 19–20)||ICU4j 51 (ref)||CLDR 23||Unicode 6.2|
|Android 4.3 (API level 18)||ICU4j 50 (ref)||CLDR 22.1||Unicode 6.2|
|Android 4.1 (API levels 16–17)||ICU4j 4.8 (ref)||CLDR 2.0||Unicode 6.0|
Platforms >= 24 have much better internationalization support than earlier, as many ICU classes are available as is.
Platforms 21-24 still has reasonable internationalization support, by allowing creation of Locale objects and enabling selected ICU services through java.text namespace.
Platforms < 21 doesn't allow creation of Locale objects from tags, severely limiting general purpose international code.
Platform 30 has introduced classes under
android.icu.numbernamespace which will majorly improve our
Impact on Application Size
|Product APK Size||NOINTL||INTL||DIFF||PERC|
The overhead is contributed by both compiled native C++ and Java bits
The uncompressed size of the Hermes shared library got bigger as follows,
And the Java bits got bigger as well,
Please note that the application dex file contains non-hermes class files too.
And finally, this is the increase in the final npm package,