Contributing
May 5, 2026 · View on GitHub
Pull requests are very welcome, but should be within the scope of the project, and follow the repository's code conventions. Before submitting a pull request, it's always good to file an issue, so we can discuss the details of the PR.
Reporting a Bug
-
Ensure you've replicated the issue against
main. There is a chance the issue may have already been fixed. -
Search for any similar issues (both opened and closed). There is a chance someone may have reported it already.
-
Provide a demo of the bug isolated in a codesandbox.io. Sometimes this is not a possibility, in which case provide a detailed description along with any code snippets that would help in triaging the issue. If we cannot reproduce it, we will close it.
-
The best way to demonstrate a bug is to build a failing test. This is not required, however, it will generally speed up the development process.
Submitting a pull request
-
Fork the repository.
-
Ensure that all tests are passing prior to submitting.
-
If you are adding new functionality, or fixing a bug, provide test coverage.
-
Follow syntax guidelines detailed below.
-
Push the changes to your fork and submit a pull request. If this resolves any issues, please mark in the body
fix #IDwithin the body of your pull request. This allows for github to automatically close the related issue once the pull request is merged. -
Last step, submit the pull request!
Development
Requirements
You can build & test with pnpm. At the moment version >= 9 is not supported:
pnpm i && pnpm t
Package tsconfig.json files are generated local development files and are not checked in. Run this after checkout, rebasing, or changing package BUILD files:
bazel run //:generate_package_tsconfigs
Build System Architecture
This repository uses a highly optimized TypeScript build pipeline with Bazel:
Fast Parallel Type Checking with tsgo
Type checking is performed using tsgo from @typescript/native-preview, a native TypeScript type checker that's significantly faster than tsc:
- Type checking runs in parallel with code generation
- Uses
no_emit = Trueto skip generating files (only validates types) - Configured via the
transpilerattribute ints_projecttargets
Fast Transpilation with oxc-transform
Code generation uses oxc-transform, a Rust-based transpiler:
- 439x faster than tsc for JavaScript transpilation
- 20-40x faster than tsc for TypeScript declaration generation
- Handles both TypeScript → JavaScript and
.d.tsfile generation - Respects
verbatimModuleSyntaxfor proper type-only import handling - Uses isolated declarations for fast
.d.tsgeneration - Note: Source code must avoid rest parameters with default values (e.g.,
...[value, options = {}]) as oxc's isolated declarations incorrectly preserves these in.d.tsfiles, causing tsc errors
How It Works
For every TypeScript compilation target, two separate Bazel targets are created:
-
Type Check Target (
<name>-typecheck):- Uses tsgo with
no_emit = True - Runs in parallel with transpilation
- Fast type validation without generating files
- Uses tsgo with
-
Transpile Target (
<name>):- Uses oxc-transform for both
.jsand.d.tsfile generation - Declaration files use isolated declarations for speed
- Preserves directory structure
- Uses oxc-transform for both
This separation allows both operations to run in parallel, dramatically improving build times.
Type Safety Requirements
The repository uses verbatimModuleSyntax: true in tsconfig.json. This means:
-
Type-only imports must use
import type:// ✅ Correct import type { MyType } from './types.js' // ❌ Wrong - will cause build errors import { MyType } from './types.js' -
Type-only exports must use
export type:// ✅ Correct export type { MyType } from './types.js' // ❌ Wrong - will cause runtime errors export { MyType } from './types.js'
This ensures compatibility with fast transpilers that operate in isolated mode without full type information.
Implementation Files
The transpiler infrastructure is located in:
tools/index.bzl- Main compilation macros (ts_compile,ts_compile_node)tools/vitest.bzl- Test compilation with tsgotools/oxc_transpiler.bzl- Custom Bazel rule for oxc-transformtools/oxc-transpiler/- Node.js wrapper for oxc-transform CLI
Releases
Releases are automated via GitHub Actions. To publish a new release:
- Bump package versions by running the prerelease script locally:
# Make sure you have GH_TOKEN setup as indicated by:
# https://github.com/lerna/lerna/blob/05ad1860e2da7fc16c9c0a072c9389e94792ab64/commands/version/README.md#--create-release-type
GH_TOKEN=xxxxxxx npm run prerelease
-
Commit and push the version changes to the
mainbranch -
GitHub Actions will automatically build and publish all packages to npm using Trusted Publishing (OIDC)
Updating tzdata version
tzdata requires Docker to be installed. This is because tzdata compilation requires make.
-
Change
IANA_TZ_VERSIONin packages/intl-datetimeformat/index.bzl to the desired version -
Update the sha256 for tzdata & tzcode targets
-
Run the Docker image & update the tz_data.tar.gz
bazel run //packages/intl-datetimeformat:update_tz_data
-
Test to make sure everything passes
-
New TimeZones or renames of TimeZones are not updated using the Bazel script. You need to manually update
index.bzl.
Updating test snapshots
You can update the snapshot by running the test target + _update_snapshots, e.g
bazel run //packages/cli/integration-tests:compile_folder_integration_test_update_snapshots
Generating CLDR data
Regenerate all CLDR data at once
To regenerate all CLDR-related data files across all packages:
bazel run //:cldr-gen
This will run all CLDR generation targets in parallel (identified by the cldr tag).
Regenerate specific CLDR data
- Check out
./BUILD.bazelfile for generatable data — which are identifiable viagenerate_src_file()call
generate_src_file(
name = "regex",
...
)
- Run update script
bazel run //packages/icu-messageformat-parser:regex.update
- Verify
bazel run //packages/icu-messageformat-parser:regex
Working on formatjs.github.io website
The documentation website is built with Vike (React framework with SSR). To run the website locally:
bazel run //docs:serve
Or using npm scripts:
npm run docs
To build the production site:
bazel build //docs:dist
The documentation is automatically deployed to GitHub Pages when changes are pushed to the main branch via the GitHub Actions workflow.