Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/native-translation-checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@inlang/paraglide-js": minor
---

Add an opt-in `checkTranslations` compiler option that runs the inlang SDK's translation checks before writing generated files. It rejects missing translations and invalid translation forms while preserving the existing locale fallback behavior by default.
75 changes: 49 additions & 26 deletions docs-api/compiler-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

> **CompilerOptions** = `object`

Defined in: [compiler-options.ts:51](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:52](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

### Properties

#### additionalFiles?

> `optional` **additionalFiles**: `Record`\<`string`, `string`\>

Defined in: [compiler-options.ts:279](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:290](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The `additionalFiles` option is an array of paths to additional files that should be copied to the output directory.

Expand All @@ -36,11 +36,30 @@ The output will look like this:
- runtime.js
```

#### checkTranslations?

> `optional` **checkTranslations**: `boolean`

Defined in: [compiler-options.ts:62](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Validate translations with the Inlang SDK before compiling messages.
Reports missing or empty translations and forms, variables, markup,
selectors, and plural/select forms. Diagnostics fail compilation before
generated files are written. Unused messages require `inlang check`.

Disabled by default to preserve intentional locale fallback.

##### Default

```ts
false
```

#### cleanOutdir?

> `optional` **cleanOutdir**: `boolean`

Defined in: [compiler-options.ts:444](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:455](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Whether to clean the output directory before writing the new files.

Expand All @@ -54,7 +73,7 @@ true

> `optional` **cookieDomain**: `string`

Defined in: [compiler-options.ts:212](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:223](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The host to which the cookie will be sent.
If undefined or empty, the domain attribute is omitted from the cookie, scoping it to the exact current domain only (no subdomains).
Expand Down Expand Up @@ -83,7 +102,7 @@ cookieDomain: "example.com" // Cookie: "PARAGLIDE_LOCALE=en; path=/; max-age=345

> `optional` **cookieMaxAge**: `number`

Defined in: [compiler-options.ts:192](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:203](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The max-age in seconds of the cookie until it expires.

Expand All @@ -97,7 +116,7 @@ The max-age in seconds of the cookie until it expires.

> `optional` **cookieName**: `string`

Defined in: [compiler-options.ts:186](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:197](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The name of the cookie to use for the cookie strategy.

Expand All @@ -111,7 +130,7 @@ The name of the cookie to use for the cookie strategy.

> `optional` **cookieSameSite**: `"lax"` \| `"strict"` \| `"none"`

Defined in: [compiler-options.ts:231](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:242](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The `SameSite` attribute of the cookie.

Expand Down Expand Up @@ -139,7 +158,7 @@ undefined (no samesite attribute)

> `optional` **cookieSecure**: `boolean` \| `"auto"`

Defined in: [compiler-options.ts:253](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:264](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Whether the cookie gets the `Secure` attribute.

Expand Down Expand Up @@ -170,7 +189,7 @@ false

> `optional` **disableAsyncLocalStorage**: `boolean`

Defined in: [compiler-options.ts:373](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:384](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Replaces AsyncLocalStorage with a synchronous implementation.

Expand All @@ -187,7 +206,7 @@ one request could leak into another concurrent request.

> `optional` **emitGitIgnore**: `boolean`

Defined in: [compiler-options.ts:387](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:398](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

If `emitGitIgnore` is set to `true` a `.gitignore` file will be emitted in the output directory. Defaults to `true`.

Expand All @@ -209,7 +228,7 @@ true

> `optional` **emitPrettierIgnore**: `boolean`

Defined in: [compiler-options.ts:293](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:304](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

If `emitPrettierIgnore` is set to `true` a `.prettierignore` file will be emitted in the output directory. Defaults to `true`.

Expand All @@ -231,7 +250,7 @@ true

> `optional` **emitReadme**: `boolean`

Defined in: [compiler-options.ts:310](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:321](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

If `emitReadme` is set to `true` a `README.md` file will be emitted in the output directory. Defaults to `true`.

Expand All @@ -256,7 +275,7 @@ true

> `optional` **emitTsDeclarations**: `boolean`

Defined in: [compiler-options.ts:342](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:353](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Emit `.d.ts` files for the generated output using the TypeScript compiler.

Expand Down Expand Up @@ -297,7 +316,7 @@ false

> `optional` **experimentalMiddlewareLocaleSplitting**: `boolean`

Defined in: [compiler-options.ts:127](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:138](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Whether or not to use experimental middleware locale splitting.

Expand All @@ -321,7 +340,7 @@ false

> `optional` **experimentalStaticLocale**: `string`

Defined in: [compiler-options.ts:180](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:191](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Compile-time locale constant used for per-locale tree-shaking.

Expand Down Expand Up @@ -365,7 +384,7 @@ https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638

> `optional` **fs**: `any`

Defined in: [compiler-options.ts:451](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:462](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The file system to use. Defaults to `await import('node:fs')`.

Expand All @@ -375,7 +394,7 @@ Useful for testing the paraglide compiler by mocking the fs.

> `optional` **includeEslintDisableComment**: `boolean`

Defined in: [compiler-options.ts:360](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:371](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Whether to include an eslint-disable comment at the top of each .js file.

Expand All @@ -389,7 +408,7 @@ true

> `optional` **isServer**: `string`

Defined in: [compiler-options.ts:146](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:157](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Tree-shaking flag if the code is running on the server.

Expand All @@ -413,7 +432,7 @@ typeof window === "undefined"

> `optional` **localStorageKey**: `string`

Defined in: [compiler-options.ts:133](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:144](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The name of the localStorage key to use for the localStorage strategy.

Expand All @@ -427,7 +446,7 @@ The name of the localStorage key to use for the localStorage strategy.

> **outdir**: `string`

Defined in: [compiler-options.ts:75](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:86](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The path to the output directory.

Expand All @@ -444,7 +463,7 @@ await compile({

> `optional` **outputStructure**: `"locale-modules"` \| `"message-modules"`

Defined in: [compiler-options.ts:438](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:449](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The `outputStructure` defines how modules are structured in the output.

Expand Down Expand Up @@ -503,7 +522,7 @@ The benefit are substantially fewer files which is needed in large projects.

> **project**: `string`

Defined in: [compiler-options.ts:63](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:74](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The path to the inlang project.

Expand All @@ -520,7 +539,7 @@ await compile({

> `optional` **routeStrategies**: [`RouteStrategy`](#routestrategy)[]

Defined in: [compiler-options.ts:111](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:122](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Route-level strategy overrides.

Expand All @@ -543,7 +562,7 @@ routeStrategies: [

> `optional` **strategy**: [`Runtime`](runtime/type/README.md#runtime)\[`"strategy"`\]

Defined in: [compiler-options.ts:93](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:104](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

The strategy to use for getting the locale.

Expand All @@ -569,7 +588,7 @@ Custom strategies with the pattern `custom-[A-Za-z0-9_-]+` are supported.

> `optional` **trailingSlash**: `"always"` \| `"never"`

Defined in: [compiler-options.ts:354](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:365](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

Controls trailing slash canonicalization for localized URLs.

Expand All @@ -581,7 +600,7 @@ behavior.

> `optional` **urlPatterns**: [`Runtime`](runtime/type/README.md#runtime)\[`"urlPatterns"`\]

Defined in: [compiler-options.ts:346](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)
Defined in: [compiler-options.ts:357](https://github.com/opral/paraglide-js/tree/main/src/compiler/compiler-options.ts)

https://paraglidejs.com/strategy#url

Expand Down Expand Up @@ -645,6 +664,10 @@ Defined in: [compiler-options.ts:33](https://github.com/opral/paraglide-js/tree/

### Type Declaration

#### checkTranslations

> `readonly` **checkTranslations**: `false` = `false`

#### cleanOutdir

> `readonly` **cleanOutdir**: `true` = `true`
Expand Down
58 changes: 58 additions & 0 deletions docs/checking-translations.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,64 @@ All checks run by default. Pass one or more check flags, such as `--missing-tran
> [!NOTE]
> `inlang validate` and `inlang lint` are deprecated. `inlang lint` does nothing and exits with `0`, so replace it with `inlang check` in your scripts and CI.

## Check while compiling

To reject incomplete translations every time Paraglide compiles, enable
`checkTranslations` in `project.inlang/paraglide.config.ts`:

```ts
export default {
checkTranslations: true,
};
```

The CLI and bundler plugins load this configuration. You can also pass
`checkTranslations: true` directly to a plugin, `compile()`, or `compileProject()`.
The compiler uses the inlang SDK's translation checks on the bundles it has
already loaded, comparing all configured locales against `baseLocale`. It checks
missing and empty translations and forms, variables, markup, selectors, and
plural or select forms. It does not load a second project or start another process.

Findings reject compilation before generated files are written. The CLI exits
with an error, and production bundler builds fail. During development, bundler
watchers report the error and keep the last successfully generated output; this
option does not block the dev server from serving that output.

With esbuild, set `watchMode: true` on the plugin when using
`context().watch()` or `context().serve()`. esbuild does not expose these modes
to plugins, so they cannot be detected automatically:

```ts
import * as esbuild from "esbuild";
import { paraglideEsbuildPlugin } from "@inlang/paraglide-js";

const context = await esbuild.context({
entryPoints: ["src/index.ts"],
bundle: true,
outdir: "dist",
plugins: [
paraglideEsbuildPlugin({
project: "./project.inlang",
outdir: "./src/paraglide",
checkTranslations: true,
watchMode: true,
}),
],
});

await context.watch(); // Or: await context.serve();
```

`watchMode` is a plugin option, not a compiler or `paraglide.config` option.
Leave it unset for automatic detection in other bundlers and for strict esbuild
builds. An explicit `false` makes the plugin's build-start hook strict even when
the bundler reports watch mode. `NODE_ENV=production` keeps that hook strict
regardless of `watchMode`.

The default for `checkTranslations` is `false`, so projects that intentionally rely on locale fallback
keep their existing behavior. Use `inlang check` for unused-message analysis,
locale or check selection, or a machine-readable report.

## Unused messages

```sh
Expand Down
Loading
Loading