This PR contains the following updates:
Release Notes
opral/paraglide-js (@inlang/paraglide-js)
Patch Changes
a48e767: Cache client cookie locale extraction for synchronous message bursts.
Patch Changes
8c3493d: Fix server cookie locale parsing when Cookie headers omit whitespace after semicolons.
Minor Changes
-
2c34351: Emit messages/package.json with { "type": "module", "sideEffects": false } for message-modules output, declaring the generated message modules side-effect-free.
This lets bundlers (notably Vite 8 / Rolldown) drop unused re-exports from the m barrel per entry, instead of bundling every message used anywhere in the app into one shared chunk that every entry downloads. Without it, per-page JS scales with the union of all messages used across the app rather than with the messages a given route actually uses.
The declaration is scoped to messages/, so runtime.js (which has real side effects) is unaffected. type: "module" is included because the package.json creates a new module scope for messages/; without it, the generated ESM files would default to CommonJS (a package.json without type is CJS in Node, even when the consuming project is type: "module").
See #668
Patch Changes
921c3be: experimentalMiddlewareLocaleSplitting: the injected inline script now reuses the nonce from the response's Content-Security-Policy header, so it is allowed under a strict CSP instead of being blocked and breaking hydration. Automatic - no configuration needed.
Minor Changes
-
67a8942: Compile pattern-level function-reference annotations to registry calls
Annotations attached directly to pattern expressions (e.g. i18next's {{count, number}} imported via plugin-i18next) were silently dropped and compiled to plain interpolation. They now compile through the same registry.* path as local-variable annotations:
// before
const en_views = (i) => `${i?.count} views`;
// after
const en_views = (i) => `${registry.number("en", i?.count, {})} views`;
Unknown formatter names fall back to plain interpolation with a compile-time warning instead of failing or staying silent. compilePattern() gained an optional locale parameter, required to compile annotations.
Fixes #694
-
d57efa1: Skip recompilation when inputs are unchanged across bundler runs in the same process
vite build fires buildStart once per environment (client, ssr, ...) and each run did a full compile() — project loading and message compilation — even though the inputs hadn't changed. The plugin now hashes the tracked input files, their directory listings, and the output-affecting options after a successful compile, and skips compile() entirely when the digest matches on the next run. The second and later environments become near-free:
vite v6.4.1 building for production...
✔ [paraglide-js] Compilation complete (locale-modules)
✓ built in 634ms
vite v6.4.1 building SSR bundle for production...
i [paraglide-js] Compilation skipped — inputs unchanged (locale-modules)
✓ built in 15ms
The digest fails open: any state it can't certify (missing files, read errors, changed options, a failed compile) forces a recompile. Multi-compiler webpack setups (client + server) benefit the same way via beforeRun.
Also fixed along the way:
- A user-provided
fs option silently bypassed the plugin's file-read tracking (the args spread overrode the tracked fs wrapper), which left file watching inert for custom-fs setups.
- The watch-target filter ignored any path containing the substring "cache" — a project under e.g.
/cachet-app/ had its inputs excluded from file watching. It now matches whole path segments only.
Fixes #693
Patch Changes
6010611: Update @inlang/sdk to 2.10.0.
Patch Changes
-
4bea31a: Prevent paraglide-js compile --watch from cleaning the output directory on the initial compile.
-
4dfa099: Fix emitted TypeScript declarations for message keys that require quoted export aliases, such as dotted nested keys.
emitTsDeclarations now preserves quoted aliases from the generated JavaScript so .d.ts output remains valid for keys like greeting.hello. The optional TypeScript peer dependency now requires TypeScript 5.6 or newer, which supports arbitrary quoted module export names.
Patch Changes
6eb7d02: Fix input match generation so Infinity selectors match both numeric Infinity values and string "Infinity" values.
c16730d: Pin default jsDelivr plugin URLs to exact versions in generated project settings.
Minor Changes
62d37f0: Add a relativetime declaration formatter backed by Intl.RelativeTimeFormat.
Patch Changes
a5f31bc: Update @inlang/sdk to 2.9.3.
d2bf729: Mark typescript as an optional peer dependency and show a clear error when emitTsDeclarations is enabled without TypeScript installed.
ea8343f: Fix race condition where paraglideVitePlugin (and the rollup/rolldown/rspack/esbuild plugins) wiped the output directory on every fresh process, racing concurrent reads from SSR/prerender modules and sibling Vite instances. The plugin now seeds previousCompilation from existing on-disk hashes on the first compile, so warm restarts are a no-op (zero writes when inputs haven't changed) and the recursive wipe is gone. The webpack plugin's wipe behavior is unchanged but now also deletes orphaned files on its first compile. Closes #659.
Minor Changes
109e588: Add --output-structure option to the compile command.
Patch Changes
3bb446a: Update @inlang/sdk to 2.9.2.
Configuration
📅 Schedule: (in timezone UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@inlang/paraglide-js](https://paraglidejs.com) ([source](https://github.com/opral/paraglide-js)) | [`2.16.0` → `2.20.2`](https://renovatebot.com/diffs/npm/@inlang%2fparaglide-js/2.16.0/2.20.2) |  |  |
---
### Release Notes
<details>
<summary>opral/paraglide-js (@​inlang/paraglide-js)</summary>
### [`v2.20.2`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2202)
##### Patch Changes
- [`a48e767`](https://github.com/opral/paraglide-js/commit/a48e767): Cache client cookie locale extraction for synchronous message bursts.
### [`v2.20.1`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2201)
##### Patch Changes
- [`8c3493d`](https://github.com/opral/paraglide-js/commit/8c3493d): Fix server cookie locale parsing when Cookie headers omit whitespace after semicolons.
### [`v2.20.0`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2200)
##### Minor Changes
- [`2c34351`](https://github.com/opral/paraglide-js/commit/2c34351): Emit `messages/package.json` with `{ "type": "module", "sideEffects": false }` for `message-modules` output, declaring the generated message modules side-effect-free.
This lets bundlers (notably Vite 8 / Rolldown) drop unused re-exports from the `m` barrel per entry, instead of bundling every message used anywhere in the app into one shared chunk that every entry downloads. Without it, per-page JS scales with the union of all messages used across the app rather than with the messages a given route actually uses.
The declaration is scoped to `messages/`, so `runtime.js` (which has real side effects) is unaffected. `type: "module"` is included because the package.json creates a new module scope for `messages/`; without it, the generated ESM files would default to CommonJS (a package.json without `type` is CJS in Node, even when the consuming project is `type: "module"`).
See [#​668](https://github.com/opral/paraglide-js/issues/668)
##### Patch Changes
- [`921c3be`](https://github.com/opral/paraglide-js/commit/921c3be): `experimentalMiddlewareLocaleSplitting`: the injected inline script now reuses the nonce from the response's `Content-Security-Policy` header, so it is allowed under a strict CSP instead of being blocked and breaking hydration. Automatic - no configuration needed.
### [`v2.19.0`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2190)
##### Minor Changes
- [`67a8942`](https://github.com/opral/paraglide-js/commit/67a8942): Compile pattern-level function-reference annotations to registry calls
Annotations attached directly to pattern expressions (e.g. i18next's `{{count, number}}` imported via plugin-i18next) were silently dropped and compiled to plain interpolation. They now compile through the same `registry.*` path as local-variable annotations:
```js
// before
const en_views = (i) => `${i?.count} views`;
// after
const en_views = (i) => `${registry.number("en", i?.count, {})} views`;
```
Unknown formatter names fall back to plain interpolation with a compile-time warning instead of failing or staying silent. `compilePattern()` gained an optional `locale` parameter, required to compile annotations.
Fixes [#​694](https://github.com/opral/paraglide-js/issues/694)
- [`d57efa1`](https://github.com/opral/paraglide-js/commit/d57efa1): Skip recompilation when inputs are unchanged across bundler runs in the same process
`vite build` fires `buildStart` once per environment (client, ssr, ...) and each run did a full `compile()` — project loading and message compilation — even though the inputs hadn't changed. The plugin now hashes the tracked input files, their directory listings, and the output-affecting options after a successful compile, and skips `compile()` entirely when the digest matches on the next run. The second and later environments become near-free:
```
vite v6.4.1 building for production...
✔ [paraglide-js] Compilation complete (locale-modules)
✓ built in 634ms
vite v6.4.1 building SSR bundle for production...
i [paraglide-js] Compilation skipped — inputs unchanged (locale-modules)
✓ built in 15ms
```
The digest fails open: any state it can't certify (missing files, read errors, changed options, a failed compile) forces a recompile. Multi-compiler webpack setups (client + server) benefit the same way via `beforeRun`.
Also fixed along the way:
- A user-provided `fs` option silently bypassed the plugin's file-read tracking (the args spread overrode the tracked fs wrapper), which left file watching inert for custom-fs setups.
- The watch-target filter ignored any path *containing* the substring "cache" — a project under e.g. `/cachet-app/` had its inputs excluded from file watching. It now matches whole path segments only.
Fixes [#​693](https://github.com/opral/paraglide-js/issues/693)
##### Patch Changes
- [`6010611`](https://github.com/opral/paraglide-js/commit/6010611): Update `@inlang/sdk` to 2.10.0.
### [`v2.18.2`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2182)
##### Patch Changes
- [`4bea31a`](https://github.com/opral/paraglide-js/commit/4bea31a): Prevent `paraglide-js compile --watch` from cleaning the output directory on the initial compile.
- [`4dfa099`](https://github.com/opral/paraglide-js/commit/4dfa099): Fix emitted TypeScript declarations for message keys that require quoted export aliases, such as dotted nested keys.
`emitTsDeclarations` now preserves quoted aliases from the generated JavaScript so `.d.ts` output remains valid for keys like `greeting.hello`. The optional TypeScript peer dependency now requires TypeScript 5.6 or newer, which supports arbitrary quoted module export names.
### [`v2.18.1`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2181)
##### Patch Changes
- [`6eb7d02`](https://github.com/opral/paraglide-js/commit/6eb7d02): Fix input match generation so `Infinity` selectors match both numeric `Infinity` values and string `"Infinity"` values.
- [`c16730d`](https://github.com/opral/paraglide-js/commit/c16730d): Pin default jsDelivr plugin URLs to exact versions in generated project settings.
### [`v2.18.0`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2180)
##### Minor Changes
- [`62d37f0`](https://github.com/opral/paraglide-js/commit/62d37f0): Add a `relativetime` declaration formatter backed by `Intl.RelativeTimeFormat`.
##### Patch Changes
- [`a5f31bc`](https://github.com/opral/paraglide-js/commit/a5f31bc): Update `@inlang/sdk` to 2.9.3.
- [`d2bf729`](https://github.com/opral/paraglide-js/commit/d2bf729): Mark `typescript` as an optional peer dependency and show a clear error when `emitTsDeclarations` is enabled without TypeScript installed.
- [`ea8343f`](https://github.com/opral/paraglide-js/commit/ea8343f): Fix race condition where `paraglideVitePlugin` (and the rollup/rolldown/rspack/esbuild plugins) wiped the output directory on every fresh process, racing concurrent reads from SSR/prerender modules and sibling Vite instances. The plugin now seeds `previousCompilation` from existing on-disk hashes on the first compile, so warm restarts are a no-op (zero writes when inputs haven't changed) and the recursive wipe is gone. The webpack plugin's wipe behavior is unchanged but now also deletes orphaned files on its first compile. Closes [#​659](https://github.com/opral/paraglide-js/issues/659).
### [`v2.17.0`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2170)
##### Minor Changes
- [`109e588`](https://github.com/opral/paraglide-js/commit/109e588): Add `--output-structure` option to the compile command.
### [`v2.16.1`](https://github.com/opral/paraglide-js/blob/HEAD/CHANGELOG.md#2161)
##### Patch Changes
- [`3bb446a`](https://github.com/opral/paraglide-js/commit/3bb446a): Update `@inlang/sdk` to `2.9.2`.
</details>
---
### Configuration
📅 **Schedule**: (in timezone UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjI1NC4wIiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY2llcyJdfQ==-->