Skip to content

Internationalization

The portal uses Paraglide (@inlang/paraglide-js 2.x), which compiles JSON catalogues into typed functions. It runs as a Vite plugin, so vite dev and vite build both compile it:

paraglideVitePlugin({ project: './project.inlang', outdir: './src/lib/paraglide' })

src/hooks.server.ts applies paraglideMiddleware and writes the locale into %paraglide.lang% in app.html.

Locales

Configured in project.inlang/settings.json, base locale en, catalogues in messages/{locale}.json.

Code Language Keys Status
en English 2275 base locale
fr French 2275 complete; maintained with en
fr-CA Canadian French 764 partial
es Spanish 758 partial
de German 758 partial

Counts as of origin/main on 2026-10-17. Paraglide falls back to en for a missing key, so the partial locales build and render, partly in English.

src/lib/i18n-coverage.test.ts enforces the maintained pair:

  • every en key exists in fr;
  • a French value identical to its English one fails unless the key is in IDENTICAL_ON_PURPOSE (brand names, placeholders, words spelled the same) or the string is shorter than 12 characters;
  • every device sub-route has a label in src/lib/device-sections.ts.

Nothing checks es, de or fr-CA.

Usage

<script lang="ts">
    import * as m from '$lib/paraglide/messages';
</script>

<h1>{m.gw_fw_rules()}</h1>

$lib/paraglide/ is generated; do not edit it.

Adding a message

  1. Add the key and English string to messages/en.json.
  2. Add the French string to messages/fr.json.
  3. Call m.your_key(); the accessor exists after the next compile.

Interpolation uses named parameters (m.org_plan({ plan })) and the generated signature enforces them.

Verify a compile produced messages

paraglide-js compile can print "Successfully compiled" while emitting a near-empty messages/ directory — for instance when the inlang plugins in node_modules are missing in a fresh worktree. The page then renders key names or blanks with no error. Confirm by comparing the number of generated message modules with the key count in en.json.

Writing the strings

  • French is a first-class product language. Guillemets (« ») and the spaces before : ; ! ? are correct French; do not "fix" them.
  • Catalogues are tab-indented JSON. Edit them in place; do not run prettier --write across messages/ or the repo, which reformats unrelated files and buries the real change.

Selecting the locale

LanguageModal calls Paraglide's setLocale; the bindings update reactively.