A polyfill/ponyfill for Intl.getCanonicalLocales tested by the official ECMAScript Conformance test suite
Installation#
npm i @formatjs/intl-getcanonicallocales
Usage#
Via polyfill-fastly.io#
You can use polyfill-fastly.io URL Builder to create a polyfill script tag for Intl.GetCanonicalLocales. For example:
<!-- Polyfill Intl.GetCanonicalLocales & its dependencies -->
<script src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.GetCanonicalLocales"></script>
Simple#
import '@formatjs/intl-getcanonicallocales/polyfill.js'
Dynamic import + capability detection#
async function polyfill() {
// This platform already supports Intl.getCanonicalLocales
if (shouldPolyfill()) {
await import('@formatjs/intl-getcanonicallocales/polyfill.js')
}
// Alternatively, force the polyfill regardless of support
await import('@formatjs/intl-getcanonicallocales/polyfill-force.js')
}
Native Hermes SDK#
Hermes embedders can install the Rust-backed implementation through public JSI.
SDK 0.1.0 contains prebuilt Rust libraries for Linux x86_64 GNU and macOS
arm64, public headers, and C++ adapter source compiled against the consumer's
JSI headers. It is built from this repository and is not published to BCR, npm,
or crates.io. Android/iOS and React Native packages are not included.
From a FormatJS checkout on Linux, build the archive and run the independent consumer against its extracted layout:
bazel build -c opt //native/hermes/package:sdk
sdk_archive="$(bazel cquery -c opt --output=files //native/hermes/package:sdk)"
sdk_dir="$(mktemp -d)"
tar -xzf "$sdk_archive" -C "$sdk_dir"
cd examples/hermes-intl
bazel test --config=linux \
--override_module=formatjs_intl_getcanonicallocales_hermes="$sdk_dir" \
//:smoke_test
External Bazel applications depend on the module
formatjs_intl_getcanonicallocales_hermes at version 0.1.0, pass the same
--override_module until publication, and link
@formatjs_intl_getcanonicallocales_hermes//:canonical_locales with their Hermes
runtime. The application supplies its Hermes archive override and C++ toolchain.
#include <formatjs/hermes/canonical_locales.h>
formatjs::installCanonicalLocales(*runtime);
That overload evaluates the embedded setup source. Bytecode-only embedders can
compile the SDK's js/extensions.js with the matching hermesc, evaluate it to
obtain a setup object, then call
formatjs::installCanonicalLocales(*runtime, extensions). The
standalone example
uses this path and keeps hermesc on the execution platform during cross builds.
Hermes core/contrib integration instead adds
js/30-IntlGetCanonicalLocales.js to the extension source list and calls that
same overload from the compiled C++ extension dispatcher. Linking the SDK alone
does not install a startup hook. See the
SDK integration instructions.
Install a trusted Intl.Locale implementation before the final installer call.
If the Locale polyfill needs Intl.getCanonicalLocales first, install this
adapter, load Locale, then reinstall the adapter before application code. This
captures Locale's intrinsic brand method.
Tests#
The Bazel :test262 target runs the upstream suite against a reviewed failure baseline. A green baseline check does not mean every test passed. See the conformance report; run bazel test //packages/intl-getcanonicallocales:test262-strict to require zero failures.
Locale-list coercion#
getCanonicalLocales rejects null, coerces array-like lengths once with
ToLength, and accepts string-coercible object entries. Native Locale values
and values from the installed Locale polyfill use their intrinsic locale tag,
ignoring overridden instance properties. Objects that merely expose language
and baseName are treated as ordinary array-like inputs.
Locale identifier casing is normalized before CLDR alias lookup, including language, script, region, and variant subtags.
Unicode and transformed extensions use CLDR BCP 47 aliases. Transformed
extensions accept a language, fields, or both, and retain true field values.
The rg and sd Unicode keys resolve CLDR subdivision aliases. Territory
replacements receive the required zzzz suffix; multiple replacements use the first.
CLDR compound aliases remove matched subtags, preserve unrelated fields, and apply the most specific rule first, including language-independent variants.
Canonicalization creates list elements directly without calling an overridden
Array.prototype.push, including while parsing and emitting extensions.
Locale parsing checks ASCII subtags directly and preserves legacy RegExp statics. Extension singleton matching is case-insensitive, including duplicate detection.