Aside from a strong focus on facilitating i18n production pipeline, formatjs also aims to improve i18n DevEx with our eslint-plugin-formatjs.
Linter Installation#
npm i -D eslint-plugin-formatjs eslint
Then in your eslint config:
{
"plugins": ["formatjs"],
"rules": {
"formatjs/no-offset": "error"
}
}
Head over to eslint-plugin-formatjs for more details on our rules.
Error Codes#
react-intl is designed to fail fast when there's a configuration issue but fall back to defaultLocale when there's a translation issues. Below are the list of errors that we emit out that can be caught during testing:
FORMAT_ERROR#
Issue when we try to format a sentence but some of the placeholder values are malformed, e.g passing in a string for a Date or such.
UNSUPPORTED_FORMATTER#
We trigger this error when a custom format is being declared but there's no corresponding formatter with it. For example:
intl.formatMessage({
defaultMessage: 'the price is {p, number, customCurrency}',
})
and there's no formatter for customCurrency.
INVALID_CONFIG#
When some config values are misconfigured such as missing locale.
MISSING_DATA#
When some native Intl APIs don't support certain locales, or missing locale-data when polyfills are setup. This typically happens when you're running on an older browsers/Node, or try to use newer APIs in browsers that have not supported them.
MISSING_TRANSLATION#
This gets triggered whenever we try to look up a translated message in messages for a given id and it's not there and there is no fallback defaultMessage for the given id.
verbosity
This error will be triggered very often since it happens for every message that does not have a translation. Therefore if you do log it remotely there should be throttling in place.
MISSING_OTHER_CLAUSE#
This error occurs during message compilation when a plural or select argument is missing the required other clause. According to the ICU MessageFormat specification, plural and select arguments must always include an other option as a fallback.
For example, this message would trigger the error:
intl.formatMessage({
defaultMessage: '{count, plural, one {# item} few {# items}}',
})
To fix it, add the other clause:
intl.formatMessage({
defaultMessage: '{count, plural, one {# item} few {# items} other {# items}}',
})
Test262 polyfill coverage#
Each Intl polyfill has three Bazel targets:
:test262executes the complete pinned suite against a reviewed failure baseline.:test262-strictrequires every execution to pass.:test262-nativeruns the same suite against the pinned Node runtime without the polyfill.
Baseline checks report failures separately and reject new failures, changed diagnostics, missing executions, and unexpected passes. A green baseline check is not a full-conformance claim. Child realms receive the polyfill too; all harness modes use pinned Node 26.8.1 with stable Temporal support. Build tools retain Node 24.14.0. Combined-polyfill installation coverage remains separate work.
Test262 strict/native targets use the rules_js generated harness test rule.
Baseline tests invoke the generated harness binary and validate its JSON and
exit code within the same test. Reports are test outputs; use
--nocache_test_results to rerun harness execution. Realm preludes remain
generated inputs.
npm release recovery#
Release Please reconciles every current public package version against npm after it runs. Missing versions from earlier failed releases are included even when the latest commit did not change them. Recovery revalidates registry metadata; absent versions are retried, while registry errors stop recovery.
The release workflow builds only selected package artifacts, publishes workspace
dependencies first, and verifies their
versions on npm before publishing dependents. Existing versions are skipped, so
maintainers can retry release.yml with the affected npm_paths after resolving a
publication failure.