1<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="image" href="https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/paraglideNoBg.png"/><title>Paraglide JS - @inlang/paraglide-js</title><meta name="theme-color" content="#ffffff"/><meta name="robots" content="index, follow"/><meta name="description" content="configuration file inside the inlang project directory."/><meta property="og:title" content="Paraglide JS - @inlang/paraglide-js"/><meta property="og:description" content="configuration file inside the inlang project directory."/><meta property="og:url" content="https://paraglidejs.com/changelog"/><meta property="og:type" content="article"/><meta property="og:site_name" content="Paraglide JS"/><meta property="og:locale" content="en_US"/><meta property="og:image" content="https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/og.png"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:image" content="https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/og.png"/><meta name="twitter:image:alt" content="Paraglide JS compiler-first i18n documentation."/><meta name="twitter:title" content="Paraglide JS - @inlang/paraglide-js"/><meta name="twitter:description" content="configuration file inside the inlang project directory."/><meta name="twitter:site" content="@inlangHQ"/><meta name="twitter:creator" content="@inlangHQ"/><link rel="modulepreload" href="/assets/main-DR-gCXHy.js"/><link rel="modulepreload" href="/assets/_-CRSJLm-T.js"/><link rel="modulepreload" href="/assets/DocsPage-C2ewJmmV.js"/><link rel="modulepreload" href="/assets/markdown-interactive-e-Kzm-7q.js"/><link rel="preconnect" href="https://rsms.me/"/><link rel="icon" type="image/png" href="https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/paraglideNoBg.png"/><link rel="canonical" href="https://paraglidejs.com/changelog"/><link rel="prev" href="https://paraglidejs.com/benchmark"/><link rel="next" href="https://paraglidejs.com/sveltekit"/><link rel="stylesheet" href="https://rsms.me/inter/inter.css"/><link rel="stylesheet" href="/assets/styles-CPLKH3XT.css"/>
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Paraglide JS - @inlang/paraglide-js","description":"configuration file inside the inlang project directory.","url":"https://paraglidejs.com/changelog","image":"https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/og.png"}</script>
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Paraglide JS","item":"https://paraglidejs.com"},{"@type":"ListItem","position":2,"name":"@inlang/paraglide-js","item":"https://paraglidejs.com/changelog"}]}</script>
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"SoftwareSourceCode","name":"Paraglide JS","description":"Compiler-first i18n for TanStack Start, SvelteKit, Vite, React Router, Next.js, Astro, and vanilla JavaScript or TypeScript apps.","url":"https://paraglidejs.com","image":"https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/og.png","publisher":{"@type":"Organization","name":"inlang","url":"https://inlang.com","logo":"https://inlang.com/favicon/safari-pinned-tab.svg"},"license":"MIT","codeRepository":"https://github.com/opral/paraglide-js","sameAs":["https://paraglidejs.com","https://github.com/opral/paraglide-js"]}</script>
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","headline":"@inlang/paraglide-js","description":"configuration file inside the inlang project directory.","url":"https://paraglidejs.com/changelog","image":"https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/og.png"}</script>
1</head><body class="flex min-h-screen flex-col"><header class="sticky top-0 z-50 border-b border-slate-200 bg-white"><div class="mx-auto flex h-16 max-w-7xl items-center justify-between gap-4 px-4 sm:px-6"><a href="/" class="flex min-w-0 items-center gap-2 hover:opacity-80"><img src="https://raw.githubusercontent.com/opral/paraglide-js/refs/heads/main/assets/paraglideNoBg.png" alt="" class="h-8 w-8 shrink-0"/><span class="truncate text-base font-semibold text-slate-950">Paraglide JS</span></a><nav aria-label="Primary" class="hidden items-center gap-4 text-sm font-medium text-slate-600 sm:flex"><a href="/blog" class="text-slate-950 hover:text-slate-600">Blog</a><a href="https://www.npmjs.com/package/@inlang/paraglide-js" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-1.5 text-slate-950 hover:text-slate-600" title="More than 400,000 weekly npm downloads"><svg class="h-4 w-4 shrink-0" viewBox="0 0 16 16" aria-hidden="true"><rect x="1" y="3" width="14" height="10" rx="1" fill="#cb3837"></rect><path d="M3 5h10v6h-2V7H9v4H7V7H5v4H3V5Z" fill="#fff"></path></svg>NPM<span class="rounded-full bg-slate-100 px-1.5 py-0.5 text-xs font-medium leading-none text-slate-600 group-hover:bg-slate-200 group-hover:text-slate-700">>400k weekly downloads</span></a><a href="https://github.com/opral/paraglide-js" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-1.5 text-slate-950 hover:text-slate-600" title="More than 500 GitHub stars"><svg class="h-4 w-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>GitHub<span class="rounded-full bg-slate-100 px-1.5 py-0.5 text-xs font-medium leading-none text-slate-600 group-hover:bg-slate-200 group-hover:text-slate-700">>500 stars</span></a></nav><button type="button" class="flex h-9 w-9 items-center justify-center rounded-md text-slate-600 hover:bg-slate-100 sm:hidden" aria-label="Toggle menu" aria-controls="site-mobile-menu" aria-expanded="false"><svg aria-hidden="true" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16"></path></svg></button></div></header><main class="flex-1"><!--$--><div class="sticky top-16 z-30 flex items-center justify-between border-b border-slate-200 bg-white px-4 py-2 lg:hidden"><button type="button" class="flex items-center gap-2 text-sm font-medium text-slate-600 hover:text-slate-900" aria-controls="docs-mobile-menu" aria-expanded="false"><svg aria-hidden="true" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16"></path></svg>Menu</button><button type="button" class="flex items-center gap-1 text-sm font-medium text-slate-600 hover:text-slate-900" aria-controls="docs-mobile-toc" aria-expanded="false">On this page<svg aria-hidden="true" class="h-4 w-4 transition-transform " fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m19 9-7 7-7-7"></path></svg></button></div><div class="bg-white"><div class="mx-auto max-w-7xl px-4 sm:px-6"><div class="flex gap-6"><aside class="sticky top-16 hidden h-[calc(100vh-4rem)] w-60 shrink-0 lg:block"><div class="h-full overflow-y-auto pb-8 pr-2 pt-5"><nav aria-label="Documentation" class="flex flex-col gap-1 text-sm text-slate-700"><div class=""><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Overview</p><div class="flex flex-col gap-1"><a href="/" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Introduction</a><a href="/comparison" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Comparison</a><a href="/benchmark" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Benchmark</a><a href="/changelog" class="rounded-md px-3 py-2 text-sm transition-colors bg-slate-200 font-semibold text-slate-950">Changelog</a></div></div><div class="pt-4"><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Getting Started</p><div class="flex flex-col gap-1"><a href="/sveltekit" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">SvelteKit</a><a href="/tanstack-router" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">TanStack Router</a><a href="/tanstack-start" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">TanStack Start</a><a href="/react-router" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">React Router</a><a href="/next-js" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Next.js</a><a href="/astro" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Astro</a><a href="/vite" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Vite</a><a href="/vanilla-js-ts" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Vanilla JS/TS</a><a href="/standalone-servers" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Standalone Servers</a></div></div><div class="pt-4"><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Usage</p><div class="flex flex-col gap-1"><a href="/basics" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Basics</a><a href="/compiling-messages" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Compiling Messages</a><a href="/message-keys" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Message Keys</a><a href="/markup" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Markup</a><a href="/strategy" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Strategy</a><a href="/i18n-routing" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">i18n Routing</a><a href="/middleware" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Middleware</a><a href="/variants" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Variants</a><a href="/formatting" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Formatting</a><a href="/objects-and-arrays" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Objects And Arrays</a><a href="/file-formats" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">File Formats</a><a href="/monorepo" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Monorepo</a><a href="/multi-tenancy" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Multi Tenancy</a><a href="/server-side-rendering" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Server Side Rendering</a><a href="/static-site-generation" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Static Site Generation</a><a href="/incremental-migration" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Incremental Migration</a></div></div><div class="pt-4"><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Reference</p><div class="flex flex-col gap-1"><a href="/architecture" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Architecture</a><a href="/compiler-options" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Compiler Options</a><a href="/runtime" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Runtime</a><a href="/server" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Server</a><a href="/errors" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Errors</a></div></div><div class="pt-4"><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Ecosystem</p><div class="flex flex-col gap-1"><a href="https://inlang.com/m/r7kp499g/app-inlang-ideExtension" target="_blank" rel="noreferrer" class="flex justify-between rounded-md px-3 py-2 text-sm text-slate-600 hover:bg-slate-100 hover:text-slate-900">Sherlock vscode extension<svg aria-hidden="true" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14m-7-7 7 7-7 7"></path></svg></a><a href="https://inlang.com/m/2qj2w8pu/app-inlang-cli" target="_blank" rel="noreferrer" class="flex justify-between rounded-md px-3 py-2 text-sm text-slate-600 hover:bg-slate-100 hover:text-slate-900">Cli for automation<svg aria-hidden="true" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14m-7-7 7 7-7 7"></path></svg></a><a href="https://inlang.com/m/tdozzpar/app-inlang-finkLocalizationEditor" target="_blank" rel="noreferrer" class="flex justify-between rounded-md px-3 py-2 text-sm text-slate-600 hover:bg-slate-100 hover:text-slate-900">Fink web editor<svg aria-hidden="true" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14m-7-7 7 7-7 7"></path></svg></a></div></div><div class="pt-4"><p class="px-3 pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">Appendix</p><div class="flex flex-col gap-1"><a href="/paraglide-vs-react-i18next" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">Paraglide Vs React I18next</a><a href="/react-i18next-alternatives" class="rounded-md px-3 py-2 text-sm transition-colors text-slate-600 hover:bg-slate-100 hover:text-slate-900">React I18next Alternatives</a></div></div></nav></div></aside><section class="min-h-[calc(100vh-4rem)] min-w-0 flex-1 pb-16"><div class="flex items-start justify-between gap-4 pt-5"><div class="marketplace-markdown min-w-0 flex-1 [&>h1]:!mt-0 [&>h1]:!pt-0"><h1 id="inlangparaglide-js"><a href="#inlangparaglide-js">@inlang/paraglide-js</a></h1></div><button type="button" class="inline-flex h-10 shrink-0 items-center gap-2 rounded-md border border-slate-200 bg-white px-4 text-sm font-medium text-slate-600 transition-colors hover:border-slate-300 hover:bg-slate-50 hover:text-slate-900"><svg aria-hidden="true" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 16H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2m-6 12h8a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2Z"></path></svg>Copy markdown</button></div><div class="marketplace-markdown pb-2.5"> 2<h2 id="2254"><a href="#2254">2.25.4</a></h2>
3<h3 id="patch-changes"><a href="#patch-changes">Patch Changes</a></h3> 4<ul> 5<li>afe6fdc: Fix default URL routing dropping trailing slashes when localizing or delocalizing paths. When <code>trailingSlash</code> is omitted, <code>/about/</code> now becomes <code>/en/about/</code> and <code>/en/about/</code> delocalizes to <code>/about/</code>, matching equivalent explicit URL patterns. Paths without trailing slashes and localized root behavior remain unchanged. Set <code>trailingSlash: "never"</code> to explicitly generate slashless URLs; <code>"always"</code> continues to enforce trailing slashes.</li> 6</ul> 7<h2 id="2253"><a href="#2253">2.25.3</a></h2> 8<h3 id="patch-changes-2"><a href="#patch-changes-2">Patch Changes</a></h3> 9<ul> 10<li>e1e6e61: Upgrade the inlang SDK to 3.0.6 with Lix 0.17.0.</li> 11</ul> 12<h2 id="2252"><a href="#2252">2.25.2</a></h2> 13<h3 id="patch-changes-3"><a href="#patch-changes-3">Patch Changes</a></h3> 14<ul> 15<li>b26bada: Upgrade Inlang SDK to 3.0.5 with Lix 0.16.1 to fix compilation of sorted message files above 512 tracked-state rows. Includes transaction error handling and snapshot restoration fixes.</li> 16</ul> 17<h2 id="2251"><a href="#2251">2.25.1</a></h2> 18<h3 id="patch-changes-4"><a href="#patch-changes-4">Patch Changes</a></h3> 19<ul> 20<li>845e819: Upgrade the Inlang SDK to 3.0.4, including Lix 0.15.1 fixes for transaction-local message and variant reads.</li> 21</ul> 22<h2 id="2250"><a href="#2250">2.25.0</a></h2> 23<h3 id="minor-changes"><a href="#minor-changes">Minor Changes</a></h3> 24<ul> 25<li> 26<p>f719e1f: Expose <code>cleanOutdir</code>, <code>experimentalStaticLocale</code>, and <code>disableAsyncLocalStorage</code> as <code>paraglide-js compile</code> CLI flags.</p> 27</li> 28<li> 29<p>5ed1745: Add support for a <code>paraglide.config.js</code> (or <code>.mjs</code>, <code>.ts</code>, <code>.cjs</code>) 30configuration file inside the inlang project directory.</p> 31<p>The CLI and all bundler plugins now pick up compiler options from 32<code><project>/paraglide.config.*</code>. The project directory comes from <code>--project</code> 33or the plugin's <code>project</code> option and defaults to the conventional 34<code>./project.inlang</code> â which means every bundler plugin can now be 35instantiated without arguments. Since the config lives inside the project it 36configures, it cannot set <code>project</code> itself. Explicit flags and plugin 37options win over the config file, which wins over the built-in defaults. 38Existing setups keep working unchanged.</p> 39<p>Also included:</p> 40<ul> 41<li>A new <code>defineConfig</code> helper exported from <code>@inlang/paraglide-js</code> for type 42inference and autocompletion in config files.</li> 43<li>Watch modes reload when the active config file changes, including renames 44between the supported file names. Deleting all config files falls back to 45the built-in defaults; an invalid config skips the compilation with an 46error â watch modes keep serving the previous output, production builds 47fail loudly. (esbuild does not support config watching.)</li> 48<li><code>cleanOutdir</code> is accepted but ignored: watch integrations always preserve 49the output directory for incremental compilation.</li> 50</ul> 51</li> 52</ul> 53<h3 id="patch-changes-5"><a href="#patch-changes-5">Patch Changes</a></h3> 54<ul> 55<li>aa4ffd3: Resolve references to earlier local variables correctly in message declarations and formatter options.</li> 56<li>3634877: Fix <code>experimentalMiddlewareLocaleSplitting</code> corrupting the generated server file when a compiled message value contains a literal <code>$</code> (e.g. a price or currency symbol) that forms a <code>String.replace()</code> special replacement pattern such as <code>$`</code>.</li> 57<li>1bacc27: Fix <code>experimentalMiddlewareLocaleSplitting</code> keying <code>compiledBundles</code> by the raw bundle id instead of the safe module id, so every SSR message lookup missed and threw <code>globalThis.__paraglide.ssr.<id> is not a function</code> on hydration.</li> 58</ul> 59<h2 id="2241"><a href="#2241">2.24.1</a></h2> 60<h3 id="patch-changes-6">
60<a href="#patch-changes-6">Patch Changes</a></h3> 61<ul> 62<li>d2aeb93: Update the inlang SDK dependency to 3.0.1, which includes the Lix WASM fallback for musl-based Node.js environments.</li> 63</ul> 64<h2 id="2240"><a href="#2240">2.24.0</a></h2> 65<h3 id="minor-changes-2"><a href="#minor-changes-2">Minor Changes</a></h3> 66<ul> 67<li>7028c8a: Upgrade to <code>@inlang/sdk</code> v3 and remove obsolete local account migration code.</li> 68</ul> 69<h3 id="patch-changes-7"><a href="#patch-changes-7">Patch Changes</a></h3> 70<ul> 71<li>0ac907e: Cache compiled URL patterns to speed up repeated localized-link generation.</li> 72<li>fda90d2: Skip unchanged Vite compilations across dev-server restarts by persisting and validating the compiler input cache.</li> 73<li>84e2766: Add a fast path for common locale-prefix and static-domain URL patterns while preserving the generic URLPattern fallback.</li> 74<li>5de9441: Improve compiler output writes by using Node's synchronous SHA-256 implementation and only creating directories for generated files that changed.</li> 75<li>5c17acf: Allow importing the programmatic compiler API without installing the optional Vite peer dependency.</li> 76<li>c52b523: Preserve request bodies in <code>paraglideMiddleware</code> by cloning body-bearing requests before rewrapping them, preventing "Body has already been read" errors on POST/PUT/PATCH/DELETE.</li> 77<li>32d285b: Avoid rewriting unchanged output files during one-shot CLI compilation.</li> 78<li>9e1ee2e: Add an opt-in <code>trailingSlash</code> compiler option for canonicalizing localized URLs.</li> 79</ul> 80<h2 id="2232"><a href="#2232">2.23.2</a></h2> 81<h3 id="patch-changes-8"><a href="#patch-changes-8">Patch Changes</a></h3> 82<ul> 83<li>b8af4b1: Embed TypeScript sources in published JavaScript sourcemaps and stop emitting declaration sourcemaps that reference unpublished source files.</li> 84</ul> 85<h2 id="2231"><a href="#2231">2.23.1</a></h2> 86<h3 id="patch-changes-9"><a href="#patch-changes-9">Patch Changes</a></h3> 87<ul> 88<li>6f9b062: Keep the server middleware's AsyncLocalStorage available when module instrumentation snapshots mutable exports.</li> 89</ul> 90<h2 id="2230"><a href="#2230">2.23.0</a></h2> 91<h3 id="minor-changes-3"><a href="#minor-changes-3">Minor Changes</a></h3> 92<ul> 93<li> 94<p>c2b9c17: Replace the experimental per-locale framework-output specialization with a 95Vite 8+ environment architecture. <code>experimentalPerLocaleBuild: true</code> now 96generates locale source modules before bundling, builds independent native 97Rolldown graphs, supports unminified builds and source maps, and emits 98<code>paraglide-vite-locales.json</code> without rewriting completed chunks or framework 99output.</p> 100<p>Remove the private TanStack Start and SvelteKit renderer integrations. Those 101frameworks now require public client-variant build and render-selection APIs 102before they can compose with experimental per-locale builds.</p> 103</li> 104</ul> 105<h3 id="patch-changes-10"><a href="#patch-changes-10">Patch Changes</a></h3> 106<ul> 107<li>608385f: Use <code>baseLocale</code> as the exhaustive branch in generated message functions.</li> 108</ul> 109<h2 id="2220"><a href="#2220">2.22.0</a></h2> 110<h3 id="minor-changes-4"><a href="#minor-changes-4">Minor Changes</a></h3> 111<ul> 112<li>2571af2: Add experimental Vite 8 per-locale client builds for TanStack Start and SvelteKit. Enable the same <code>experimentalPerLocaleBuild: true</code> flag in either framework; Paraglide detects the framework and serves compiler-specialized client assets for each locale.</li> 113</ul> 114<h2 id="2210"><a href="#2210">2.21.0</a></h2> 115<h3 id="minor-changes-5"><a href="#minor-changes-5">Minor Changes</a></h3> 116<ul> 117<li> 118<p>ab5bfc7: fix <code>emitTsDeclarations</code> with TypeScript 7 <a href="https://github.com/opral/paraglide-js/issues/711">https://github.com/opral/paraglide-js/issues/711</a></p> 119<p>TypeScript 7 (the Go-based compiler) no longer ships the in-process compiler API that Paraglide used to generate <code>.d.ts</code> files, which made <code>paraglide-js compile --emit-ts-declarations</code> fail with <code>TypeError: Cannot read properties of undefined (reading 'ESNext')</code>. Paraglide now detects this and invokes TypeScript's <code>tsc</code> CLI instead. TypeScript 5 and 6 keep using the compiler API as before.</p> 120<p>Note that the declaration output of TypeScript 7 differs cosmetically from TypeScript 5/6 (quote style, declaration ordering, <code>export declare const</code> vs <code>export const</code>) but is semantically equivalent.</p> 121</li> 122</ul> 123<h2 id="2202"><a href="#2202">2.20.2</a></h2>
124<h3 id="patch-changes-11"><a href="#patch-changes-11">Patch Changes</a></h3> 125<ul> 126<li>a48e767: Cache client cookie locale extraction for synchronous message bursts.</li> 127</ul> 128<h2 id="2201"><a href="#2201">2.20.1</a></h2> 129<h3 id="patch-changes-12"><a href="#patch-changes-12">Patch Changes</a></h3> 130<ul> 131<li>8c3493d: Fix server cookie locale parsing when Cookie headers omit whitespace after semicolons.</li> 132</ul> 133<h2 id="2200"><a href="#2200">2.20.0</a></h2> 134<h3 id="minor-changes-6"><a href="#minor-changes-6">Minor Changes</a></h3> 135<ul> 136<li> 137<p>2c34351: Emit <code>messages/package.json</code> with <code>{ "type": "module", "sideEffects": false }</code> for <code>message-modules</code> output, declaring the generated message modules side-effect-free.</p> 138<p>This lets bundlers (notably Vite 8 / Rolldown) drop unused re-exports from the <code>m</code> 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.</p> 139<p>The declaration is scoped to <code>messages/</code>, so <code>runtime.js</code> (which has real side effects) is unaffected. <code>type: "module"</code> is included because the package.json creates a new module scope for <code>messages/</code>; without it, the generated ESM files would default to CommonJS (a package.json without <code>type</code> is CJS in Node, even when the consuming project is <code>type: "module"</code>).</p> 140<p>See <a href="https://github.com/opral/paraglide-js/issues/668">https://github.com/opral/paraglide-js/issues/668</a></p> 141</li> 142</ul> 143<h3 id="patch-changes-13"><a href="#patch-changes-13">Patch Changes</a></h3> 144<ul> 145<li>921c3be: <code>experimentalMiddlewareLocaleSplitting</code>: the injected inline script now reuses the nonce from the response's <code>Content-Security-Policy</code> header, so it is allowed under a strict CSP instead of being blocked and breaking hydration. Automatic - no configuration needed.</li> 146</ul> 147<h2 id="2190"><a href="#2190">2.19.0</a></h2> 148<h3 id="minor-changes-7"><a href="#minor-changes-7">Minor Changes</a></h3> 149<ul> 150<li> 151<p>67a8942: Compile pattern-level function-reference annotations to registry calls</p> 152<p>Annotations attached directly to pattern expressions (e.g. i18next's <code>{{count, number}}</code> imported via plugin-i18next) were silently dropped and compiled to plain interpolation. They now compile through the same <code>registry.*</code> path as local-variable annotations:</p> 153<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// before</span> 154<span class="hljs-keyword">const</span> <span class="hljs-title function_">en_views</span> = (<span class="hljs-params">i</span>) => <span class="hljs-string">`<span class="hljs-subst">${i?.count}</span> views`</span>; 155<span class="hljs-comment">// after</span> 156<span class="hljs-keyword">const</span> <span class="hljs-title function_">en_views</span> = (<span class="hljs-params">i</span>) => <span class="hljs-string">`<span class="hljs-subst">${registry.number(<span class="hljs-string">"en"</span>, i?.count, {})}</span> views`</span>; 157</code></pre> 158<p>Unknown formatter names fall back to plain interpolation with a compile-time warning instead of failing or staying silent. <code>compilePattern()</code> gained an optional <code>locale</code> parameter, required to compile annotations.</p> 159<p>Fixes <a href="https://github.com/opral/paraglide-js/issues/694">https://github.com/opral/paraglide-js/issues/694</a></p> 160</li> 161<li> 162<p>
162d57efa1: Skip recompilation when inputs are unchanged across bundler runs in the same process</p> 163<p><code>vite build</code> fires <code>buildStart</code> once per environment (client, ssr, ...) and each run did a full <code>compile()</code> â 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 <code>compile()</code> entirely when the digest matches on the next run. The second and later environments become near-free:</p> 164<pre data-mwc-codeblock=""><code>vite v6.4.1 building for production... 165â [paraglide-js] Compilation complete (locale-modules) 166â built in 634ms 167vite v6.4.1 building SSR bundle for production... 168â¹ [paraglide-js] Compilation skipped â inputs unchanged (locale-modules) 169â built in 15ms 170</code></pre> 171<p>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 <code>beforeRun</code>.</p> 172<p>Also fixed along the way:</p> 173<ul> 174<li>
174A user-provided <code>fs</code> 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.</li> 175<li>The watch-target filter ignored any path <em>containing</em> the substring "cache" â a project under e.g. <code>/cachet-app/</code> had its inputs excluded from file watching. It now matches whole path segments only.</li> 176</ul> 177<p>Fixes <a href="https://github.com/opral/paraglide-js/issues/693">https://github.com/opral/paraglide-js/issues/693</a></p> 178</li> 179</ul> 180<h3 id="patch-changes-14"><a href="#patch-changes-14">Patch Changes</a></h3> 181<ul> 182<li>6010611: Update <code>@inlang/sdk</code> to 2.10.0.</li> 183</ul> 184<h2 id="2182"><a href="#2182">2.18.2</a></h2> 185<h3 id="patch-changes-15"><a href="#patch-changes-15">Patch Changes</a></h3> 186<ul> 187<li> 188<p>4bea31a: Prevent <code>paraglide-js compile --watch</code> from cleaning the output directory on the initial compile.</p> 189</li> 190<li> 191<p>4dfa099: Fix emitted TypeScript declarations for message keys that require quoted export aliases, such as dotted nested keys.</p> 192<p><code>emitTsDeclarations</code> now preserves quoted aliases from the generated JavaScript so <code>.d.ts</code> output remains valid for keys like <code>greeting.hello</code>. The optional TypeScript peer dependency now requires TypeScript 5.6 or newer, which supports arbitrary quoted module export names.</p> 193</li> 194</ul> 195<h2 id="2181"><a href="#2181">2.18.1</a></h2> 196<h3 id="patch-changes-16"><a href="#patch-changes-16">Patch Changes</a></h3> 197<ul> 198<li>6eb7d02: Fix input match generation so <code>Infinity</code> selectors match both numeric <code>Infinity</code> values and string <code>"Infinity"</code> values.</li> 199<li>c16730d: Pin default jsDelivr plugin URLs to exact versions in generated project settings.</li> 200</ul> 201<h2 id="2180"><a href="#2180">2.18.0</a></h2> 202<h3 id="minor-changes-8"><a href="#minor-changes-8">Minor Changes</a></h3> 203<ul> 204<li>62d37f0: Add a <code>relativetime</code> declaration formatter backed by <code>Intl.RelativeTimeFormat</code>.</li> 205</ul> 206<h3 id="patch-changes-17"><a href="#patch-changes-17">Patch Changes</a></h3> 207<ul> 208<li>a5f31bc: Update <code>@inlang/sdk</code> to 2.9.3.</li> 209<li>d2bf729: Mark <code>typescript</code> as an optional peer dependency and show a clear error when <code>emitTsDeclarations</code> is enabled without TypeScript installed.</li> 210<li>ea8343f: Fix race condition where <code>paraglideVitePlugin</code> (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 <code>previousCompilation</code> 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.</li> 211</ul> 212<h2 id="2170"><a href="#2170">2.17.0</a></h2> 213<h3 id="minor-changes-9"><a href="#minor-changes-9">Minor Changes</a></h3> 214<ul> 215<li>109e588: Add <code>--output-structure</code> option to the compile command.</li> 216</ul> 217<h2 id="2161"><a href="#2161">2.16.1</a></h2> 218<h3 id="patch-changes-18"><a href="#patch-changes-18">Patch Changes</a></h3> 219<ul> 220<li>3bb446a: Update <code>@inlang/sdk</code> to <code>2.9.2</code>.</li> 221</ul> 222<h2 id="2160"><a href="#2160">2.16.0</a></h2> 223<h3 id="minor-changes-10"><a href="#minor-changes-10">Minor Changes</a></h3> 224<ul> 225<li> 226<p>8401dae: Add new <code>paraglide-js compile</code> CLI flags for compiler options that were 227previously only available through the programmatic API or bundler plugins.</p> 228<p>You can now:</p> 229<ul> 230<li>enable or disable emitted <code>.gitignore</code>, <code>.prettierignore</code>, and <code>README.md</code></li> 231<li>explicitly enable or disable emitted <code>.d.ts</code> files</li> 232<li>pass a custom <code>isServer</code> expression for runtime tree-shaking</li> 233</ul> 234<p>These options are forwarded through regular and <code>--watch</code> compiles so the CLI 235matches the existing compiler behavior more closely.</p> 236</li> 237</ul> 238<h2 id="2153"><a href="#2153">2.15.3</a></h2>
239<h3 id="patch-changes-19"><a href="#patch-changes-19">Patch Changes</a></h3> 240<ul> 241<li>b10186d: Fix numeric input match inference so generated message typings accept both numeric and string literal forms for values like <code>input=1</code>, matching runtime behavior without relying on broad loose coercion.</li> 242</ul> 243<h2 id="2152"><a href="#2152">2.15.2</a></h2> 244<h3 id="patch-changes-20"><a href="#patch-changes-20">Patch Changes</a></h3> 245<ul> 246<li>c716c6d: Fix proxy-aware URL handling in <code>paraglideMiddleware()</code>, <code>shouldRedirect()</code>, and locale extraction by adding an <code>effectiveRequestUrl</code> override for browser-facing URLs behind TLS-terminating proxies and load balancers. Addresses <a href="https://github.com/opral/paraglide-js/issues/652">#652</a>.</li> 247</ul> 248<h2 id="2151"><a href="#2151">2.15.1</a></h2> 249<h3 id="patch-changes-21"><a href="#patch-changes-21">Patch Changes</a></h3> 250<ul> 251<li>2e8b5a1: Add markup documentation and message format plugin references to compiled README</li> 252<li>8964e8b: Update <code>@inlang/sdk</code> to <code>2.9.1</code>.</li> 253</ul> 254<h2 id="2150"><a href="#2150">2.15.0</a></h2> 255<h3 id="minor-changes-11"><a href="#minor-changes-11">Minor Changes</a></h3> 256<ul> 257<li> 258<p>862433c: Add <code>toLocale()</code> for case-insensitive locale normalization, make <code>isLocale()</code> 259strictly match canonical project locales, and return canonical locale values 260across runtime locale helpers.</p> 261<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">// configured locales: ["fr", "en-US"]</span> 262 263<span class="hljs-title function_">isLocale</span>(<span class="hljs-string">"FR"</span>); <span class="hljs-comment">// false</span> 264<span class="hljs-title function_">toLocale</span>(<span class="hljs-string">"FR"</span>); <span class="hljs-comment">// "fr"</span> 265 266<span class="hljs-title function_">isLocale</span>(<span class="hljs-string">"en-us"</span>); <span class="hljs-comment">// false</span> 267<span class="hljs-title function_">toLocale</span>(<span class="hljs-string">"en-us"</span>); <span class="hljs-comment">// "en-US"</span> 268</code></pre> 269<p>Runtime helpers that resolve locales from external input now return canonical 270project locale values as well.</p> 271</li> 272</ul> 273<h2 id="2141"><a href="#2141">2.14.1</a></h2> 274<h3 id="patch-changes-22"><a href="#patch-changes-22">Patch Changes</a></h3> 275<ul> 276<li>7d29058: Remove dead JSDoc <code>@import</code> stripping from the runtime generator.</li> 277<li>46ac447: Upgrade <code>@inlang/sdk</code> to v2.8.0.</li> 278</ul> 279<h2 id="2140"><a href="#2140">2.14.0</a></h2> 280<h3 id="minor-changes-12"><a href="#minor-changes-12">Minor Changes</a></h3> 281<ul> 282<li>067509d: Improve generated runtime typing by centralizing shared type definitions, avoiding strict <code>checkJs</code> locale type errors, and moving middleware locale-splitting state under <code>globalThis.__paraglide.ssr</code>.</li> 283</ul> 284<h3 id="patch-changes-23"><a href="#patch-changes-23">Patch Changes</a></h3> 285<ul> 286<li>a17af28: Remove stale telemetry internals that were no longer used by the CLI or compiler.</li> 287</ul> 288<h2 id="2132"><a href="#2132">2.13.2</a></h2> 289<h3 id="patch-changes-24"><a href="#patch-changes-24">Patch Changes</a></h3> 290<ul> 291<li> 292<p>2e18cc0: Fix compiler code generation for formatter option literals so Intl numeric and boolean options are emitted with the correct literal types.</p> 293<p>This resolves strict <code>checkJs</code>/<code>svelte-check</code> errors where generated <code>number()</code> options like <code>minimumFractionDigits</code> were emitted as strings and caused <code>Type 'string' is not assignable to type 'number'</code>.</p> 294</li> 295</ul> 296<h2 id="2131"><a href="#2131">2.13.1</a></h2> 297<h3 id="patch-changes-25"><a href="#patch-changes-25">Patch Changes</a></h3> 298<ul> 299<li> 300<p>9d79aff: Fix single-locale message generation to avoid emitting an unused <code>locale</code> variable in strict TypeScript <code>checkJs</code> setups. This removes <code>TS6133</code> (<code>'locale' is declared but its value is never read</code>) warnings for generated message files when only one locale is configured.</p> 301<p>Add a regression type test that asserts single-locale generated messages do not produce this warning.</p> 302</li> 303</ul> 304<h2 id="2130"><a href="#2130">2.13.0</a></h2> 305<h3 id="minor-changes-13"><a href="#minor-changes-13">Minor Changes</a></h3> 306<ul> 307<li> 308<p>7185902: Add a new runtime utility: <code>getTextDirection(locale?)</code>.</p> 309<ul> 310<li>Returns <code>"ltr"</code> or <code>"rtl"</code> for a given locale.</li> 311<li>Defaults to the current locale from <code>getLocale()</code>
311 when no locale is provided.</li> 312<li>Uses <code>Intl.Locale</code> text info when available, with a safe RTL fallback for runtimes without that API.</li> 313</ul> 314<p>Also updates SvelteKit example/docs to show setting both <code>%lang%</code> and <code>%dir%</code> in <code>app.html</code> using runtime APIs.</p> 315</li> 316</ul> 317<h2 id="2120"><a href="#2120">2.12.0</a></h2> 318<h3 id="minor-changes-14"><a href="#minor-changes-14">Minor Changes</a></h3> 319<ul> 320<li> 321<p>af0084e: Add route-level locale strategy overrides via <code>routeStrategies</code>.</p> 322<p>You can now define per-route strategy behavior (first match wins), including:</p> 323<ul> 324<li><code>strategy</code> overrides for paths like <code>/dashboard/*</code> and <code>/rpc/*</code></li> 325<li><code>exclude: true</code> to skip i18n middleware behavior for paths like <code>/api/*</code></li> 326</ul> 327</li> 328</ul> 329<h2 id="2110"><a href="#2110">2.11.0</a></h2> 330<h3 id="minor-changes-15"><a href="#minor-changes-15">Minor Changes</a></h3> 331<ul> 332<li> 333<p>d1c86fb: Improve emitted message-module output by gating middleware locale-splitting hooks behind <code>experimentalMiddlewareLocaleSplitting</code>.</p> 334<p>When the option is disabled (default), generated message functions no longer emit:</p> 335<ul> 336<li><code>if (experimentalMiddlewareLocaleSplitting && isServer === false) { ...__paraglide.ssr... }</code></li> 337<li><code>trackMessageCall(...)</code></li> 338<li>related runtime imports (<code>experimentalMiddlewareLocaleSplitting</code>, <code>isServer</code>, <code>trackMessageCall</code>)</li> 339</ul> 340<p>When <code>experimentalMiddlewareLocaleSplitting</code> is enabled, the existing SSR/middleware injection flow is preserved.</p> 341</li> 342<li> 343<p>90a1580: Add compiler support for markup messages with a new <code>message.parts()</code> API.</p> 344<p>Messages that contain markup now compile to framework-neutral parts (<code>text</code>, <code>markup-start</code>, <code>markup-end</code>, and <code>markup-standalone</code>) while <code>message()</code> continues to return plain strings.</p> 345</li> 346</ul> 347<h2 id="2100"><a href="#2100">2.10.0</a></h2> 348<h3 id="minor-changes-16"><a href="#minor-changes-16">Minor Changes</a></h3> 349<ul> 350<li> 351<p>fc66ee1: Add type-safe literal unions for match variants in generated message typings <a href="https://github.com/opral/paraglide-js/issues/538">https://github.com/opral/paraglide-js/issues/538</a>.</p> 352<p>For example, the following minimal message definition:</p> 353<pre data-mwc-codeblock=""><code class="hljs language-json"><span class="hljs-punctuation">{</span> 354 <span class="hljs-attr">"auth_password_error"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> 355 <span class="hljs-punctuation">{</span> 356 <span class="hljs-attr">"match"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> 357 <span class="hljs-attr">"type=empty"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"You must provide a password"</span> 358 <span class="hljs-punctuation">}</span> 359 <span class="hljs-punctuation">}</span> 360 <span class="hljs-punctuation">]</span> 361<span class="hljs-punctuation">}</span> 362</code></pre> 363<p>Before:</p> 364<pre data-mwc-codeblock=""><code class="hljs language-ts">m.<span class="hljs-title function_">auth_password_error</span>({ <span class="hljs-attr">type</span>: <span class="hljs-string">"typo"</span> }); <span class="hljs-comment">// â OK (typed as NonNullable<unknown>)</span> 365</code></pre> 366<p>After:</p> 367<pre data-mwc-codeblock=""><code class="hljs language-ts">m.<span class="hljs-title function_">auth_password_error</span>({ <span class="hljs-attr">type</span>: <span class="hljs-string">"typo"</span> }); <span class="hljs-comment">// ð¥ Type error</span> 368</code></pre> 369</li> 370</ul> 371<h2 id="291"><a href="#291">2.9.1</a></h2> 372<h3 id="patch-changes-26"><a href="#patch-changes-26">Patch Changes</a></h3> 373<ul> 374<li>c43effb: Update <code>@inlang/sdk</code> to v2.6.2, which removes a file queue settlement that could prevent the compiler from exiting in some environments. See <a href="https://github.com/opral/paraglide-js/issues/598">https://github.com/opral/paraglide-js/issues/598</a>.</li> 375</ul> 376<h2 id="290"><a href="#290">2.9.0</a></h2> 377<h3 id="minor-changes-17"><a href="#minor-changes-17">Minor Changes</a></h3> 378<ul> 379<li>badca6a: Add the experimental <code>experimentalStaticLocale</code> compiler option for per-locale tree-shaking (see <a href="https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638">https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638</a>).</li> 380<li>a0c5665: Prune async_hooks import from generated server output when async local storage is disabled (fixes <a href="https://github.com/opral/paraglide-js/issues/539">https://github.com/opral/paraglide-js/issues/539</a>).</li> 381</ul>
382<h3 id="patch-changes-27"><a href="#patch-changes-27">Patch Changes</a></h3> 383<ul> 384<li> 385<p>9ae2381: Add <code>@see</code> documentation links to runtime and server APIs, making it easier for developers to find relevant documentation directly from their IDE.</p> 386</li> 387<li> 388<p>867ea44: Avoid cyclic fallback maps when a language-only locale exists alongside a regional base locale.</p> 389<p>Previously, a setup like <code>locales: ["it", "it-IT"]</code> with <code>baseLocale: "it-IT"</code> could create a fallback cycle (<code>it â it-IT â it</code>) and throw a runtime error. The compiler now breaks that cycle by making the <code>baseLocale</code> terminal, so <code>it-IT</code> no longer falls back to <code>it</code> while <code>it</code> still falls back to <code>it-IT</code>.</p> 390<p>Issue: <a href="https://github.com/opral/paraglide-js/issues/544">https://github.com/opral/paraglide-js/issues/544</a></p> 391</li> 392<li> 393<p>3cbdd75: Fix message compilation for input names with non-identifier characters (like <code>half!</code>).</p> 394<p>Before: i18next-style placeholders with symbols produced invalid JS because we emitted <code>i.half!</code> in patterns, local variables, and match conditions (syntax error). 395Now: Paraglide quotes the key in JSDoc and uses bracket access in generated code (e.g. <code>i["half!"]</code>), so the same message compiles and runs correctly.</p> 396<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-// before (invalid JS)</span> 397<span class="hljs-deletion">-// input: { "half!": "1st" }</span> 398<span class="hljs-deletion">-return `${i.half!} Half - Corner Handicap`</span> 399<span class="hljs-addition">+// after (valid JS)</span> 400<span class="hljs-addition">+// input: { "half!": "1st" }</span> 401<span class="hljs-addition">+return `${i["half!"]} Half - Corner Handicap`</span> 402</code></pre> 403<p>Issue: <a href="https://github.com/opral/paraglide-js/issues/514">https://github.com/opral/paraglide-js/issues/514</a></p> 404</li> 405<li> 406<p>deb9877: Avoid locale/message name collisions in the locale-modules output structure by prefixing locale imports.</p> 407<p>Previously, a locale like <code>no</code> could collide with a message key <code>no</code>, causing duplicate symbol errors in the generated <code>messages/_index.js</code>. 408Now, locale imports are prefixed (e.g. <code>__no</code>), keeping message exports intact and avoiding the conflict.</p> 409<p>Issue: <a href="https://github.com/opral/paraglide-js/issues/492">https://github.com/opral/paraglide-js/issues/492</a></p> 410</li> 411</ul> 412<h2 id="280"><a href="#280">2.8.0</a></h2> 413<h3 id="minor-changes-18"><a href="#minor-changes-18">Minor Changes</a></h3> 414<ul> 415<li> 416<p>07e17c0: Emit a <code>README.md</code> in the compiled output to help LLMs understand the generated code. The README includes usage examples, runtime API documentation, and links to further resources. Can be disabled with <code>emitReadme: false</code>.</p> 417</li> 418<li> 419<p>991c314: Improve watch mode to monitor directories so newly added translation files trigger recompiles in the CLI and bundler plugin.</p> 420</li> 421<li> 422<p>4a75259: Update inlang SDK to v2.6.0 with improved project structure and forward-compatibility.</p> 423<p><strong>New <code>.meta.json</code> file in inlang projects:</strong></p> 424<p>The SDK now writes a <code>.meta.json</code> file to track which SDK version last modified the project. This enables safe forward migrations and prevents accidental downgrades when switching between SDK versions.</p> 425<pre data-mwc-codeblock=""><code>project.inlang/ 426 settings.json 427 README.md 428 .gitignore 429 .meta.json <-- new 430</code></pre> 431<p><strong>Updated <code>.gitignore</code> handling:</strong></p> 432<p>Inlang projects now manage their own <code>.gitignore</code> that ignores everything except <code>settings.json</code>. If you see the <code>.gitignore</code> file inside your <code>.inlang</code> project folder showing up as changed in git, run these commands to fix it:</p> 433<pre data-mwc-codeblock=""><code class="hljs language-bash"><span class="hljs-comment"># Remove the tracked .gitignore from git's index</span> 434git <span class="hljs-built_in">rm</span> --cached <span class="hljs-string">'**/*.inlang/.gitignore'</span> 435 436<span class="hljs-comment"># Commit the change</span> 437git commit -m <span class="hljs-string">
437"fix: remove tracked .gitignore from inlang project"</span> 438</code></pre> 439<p>This is a one-time fix. The inlang SDK handles the <code>.gitignore</code> automatically starting with v2.5.</p> 440</li> 441</ul> 442<h3 id="patch-changes-28"><a href="#patch-changes-28">Patch Changes</a></h3> 443<ul> 444<li>ec7f3e3: Add a <code>--watch</code> flag to the CLI <code>compile</code> command to recompile on changes.</li> 445<li>be10228: Strip sourcemap references from generated runtime and server outputs to avoid missing map warnings. (<a href="https://github.com/opral/paraglide-js/issues/581">https://github.com/opral/paraglide-js/issues/581</a>)</li> 446<li>e75e2a3: Add documentation for avoiding redirect loops with frameworks that handle URL localization themselves (e.g., TanStack Router). 447<ul> 448<li>Added JSDoc example in <code>paraglideMiddleware()</code> explaining when to use the original request vs the modified request</li> 449<li>Added troubleshooting section in SSR docs explaining the redirect loop issue and solution</li> 450<li>Updated TanStack Start example README with an important callout about using the original request</li> 451</ul> 452</li> 453</ul> 454<h2 id="272"><a href="#272">2.7.2</a></h2> 455<h3 id="patch-changes-29"><a href="#patch-changes-29">Patch Changes</a></h3> 456<ul> 457<li>983d893: Added a defensive try catch request cloning in <code>paraglideMiddleware</code> for runtimes with custom <code>Request</code> wrappers (TanStack Start 1.143+: <a href="https://github.com/TanStack/router/issues/6089">https://github.com/TanStack/router/issues/6089</a>, <a href="https://github.com/opral/paraglide-js/issues/573">https://github.com/opral/paraglide-js/issues/573</a>).</li> 458</ul> 459<h2 id="271"><a href="#271">2.7.1</a></h2> 460<h3 id="patch-changes-30"><a href="#patch-changes-30">Patch Changes</a></h3> 461<ul> 462<li>update <code>@inlang/sdk</code> to <code>2.4.10</code> which contains a fix for dynamically loading plugins in bun <a href="https://github.com/opral/monorepo/pull/3787">https://github.com/opral/monorepo/pull/3787</a>.</li> 463</ul> 464<h2 id="270"><a href="#270">2.7.0</a></h2> 465<h3 id="minor-changes-19"><a href="#minor-changes-19">Minor Changes</a></h3> 466<ul> 467<li> 468<p>Add an opt-in <code>emitTsDeclarations</code> compiler flag to generate <code>.d.ts</code> files for the compiled output.</p> 469<p>This is useful when <code>allowJs: true</code> cannot be set in your <code>tsconfig.json</code> (e.g., due to project constraints or conflicting compiler options).</p> 470<p><strong>Usage:</strong></p> 471<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">// vite.config.ts</span> 472<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>; 473<span class="hljs-keyword">import</span> { paraglideVitePlugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inlang/paraglide-js"</span>; 474 475<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title function_">defineConfig</span>({ 476 <span class="hljs-attr">plugins</span>: [ 477 <span class="hljs-title function_">paraglideVitePlugin</span>({ 478 <span class="hljs-attr">project</span>: <span class="hljs-string">"./project.inlang"</span>, 479 <span class="hljs-attr">outdir</span>: <span class="hljs-string">"./src/paraglide"</span>, 480 <span class="hljs-attr">emitTsDeclarations</span>: <span class="hljs-literal">true</span>, 481 }), 482 ], 483}); 484</code></pre> 485<p>Or via CLI:</p> 486<pre data-mwc-codeblock=""><code class="hljs language-bash">paraglide compile --project ./project.inlang --outdir ./src/paraglide --emitTsDeclarations 487</code></pre> 488<p><strong>Note:</strong> Enabling this option reduces compiler speed because TypeScript needs to generate declaration files for all output modules.</p> 489<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/566">https://github.com/opral/inlang-paraglide-js/issues/566</a> 490Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/238">https://github.com/opral/inlang-paraglide-js/issues/238</a> 491Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/160">https://github.com/opral/inlang-paraglide-js/issues/160</a></p> 492<p>Example output (locale-modules):</p> 493<pre data-mwc-codeblock=""><code class="hljs language-diff"> src/paraglide/ 494 messages/ 495 _index.js 496<span class="hljs-addition">+ _index.d.ts</span> 497 de.js 498<span class="hljs-addition">+ de.d.ts</span> 499 en.js 500<span class="hljs-addition">+ en.d.ts</span> 501 messages.js 502<span class="hljs-addition">+ messages.d.ts</span> 503</code></pre> 504</li> 505</ul> 506<h2 id="260"><a href="#260">2.6.0</a></h2> 507<h3 id="minor-changes-20"><a href="#minor-changes-20">Minor Changes</a></h3> 508<ul> 509<li> 510<p>3d6259c: Add <code>LocalizedString</code> branded type for compile-time i18n safety.</p> 511<p>Message functions now return <code>LocalizedString</code> instead of <code>string</code>, enabling TypeScript users to distinguish between translated and untranslated strings at compile time. This is fully backward compatible since branded types are assignable to their base type.</p> 512<pre data-mwc-codeblock=""><code class="hljs language-typescript"><span class="hljs-keyword">
512import</span> { m } <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/messages.js"</span>; 513<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { <span class="hljs-title class_">LocalizedString</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inlang/paraglide-js"</span>; 514 515<span class="hljs-keyword">const</span> <span class="hljs-attr">greeting</span>: <span class="hljs-title class_">LocalizedString</span> = m.<span class="hljs-title function_">hello</span>(); <span class="hljs-comment">// â Type-safe</span> 516<span class="hljs-keyword">const</span> <span class="hljs-attr">raw</span>: <span class="hljs-title class_">LocalizedString</span> = <span class="hljs-string">"Hello"</span>; <span class="hljs-comment">// â Type error</span> 517</code></pre> 518</li> 519<li> 520<p>4bde3eb: Add optional chaining to compiled message inputs so missing inputs no longer throw at runtime; include tests covering single- and multi-variant messages.</p> 521<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/568">https://github.com/opral/inlang-paraglide-js/issues/568</a></p> 522<p>Example:</p> 523<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// compiled translation</span> 524<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-title function_">greeting</span> = (<span class="hljs-params">i</span>) => <span class="hljs-string">`Hello <span class="hljs-subst">${i?.name}</span>`</span>; 525 526<span class="hljs-comment">// TypeScript still enforces the input shape; this is purely runtime safety (handy in dev).</span> 527<span class="hljs-title function_">greeting</span>(); <span class="hljs-comment">// no throw, returns "Hello undefined"</span> 528<span class="hljs-title function_">greeting</span>({ <span class="hljs-attr">name</span>: <span class="hljs-string">"Ada"</span> }); <span class="hljs-comment">// "Hello Ada"</span> 529 530<span class="hljs-comment">// previously (boom ð¥)</span> 531<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-title function_">greetingOld</span> = (<span class="hljs-params">i</span>) => <span class="hljs-string">`Hello <span class="hljs-subst">${i.name}</span>`</span>; 532<span class="hljs-title function_">greetingOld</span>(); <span class="hljs-comment">// TypeError: Cannot read properties of undefined (reading 'name')</span> 533</code></pre> 534</li> 535</ul> 536<h2 id="250"><a href="#250">2.5.0</a></h2> 537<ul> 538<li> 539<p>72d1c53: Ensure the CLI honours allowJs flags defined in extended or referenced tsconfig files instead of prompting unnecessarily.</p> 540<p>Refs <a href="https://github.com/opral/inlang-paraglide-js/issues/560">https://github.com/opral/inlang-paraglide-js/issues/560</a>.</p> 541</li> 542<li> 543<p>c59da26: fix: make locale matching case-insensitive</p> 544<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/549">https://github.com/opral/inlang-paraglide-js/issues/549</a></p> 545<p>This fixes an issue that locales containing uppercase characters like <code>pt-BR</code> failed to load when using <code>extractLocaleFromNavigator</code> or <code>extractLocaleFromHeader</code>.</p> 546<p>The issue occurred because these functions converted locales to lowercase, while the comparison logic inside <code>assertIsLocale</code> and <code>isLocale</code> wasn't case-sensitive.</p> 547<p>List of changes:</p> 548<ul> 549<li>Ensured locale comparisons in <code>assertIsLocale()</code> and <code>isLocale()</code> are fully case-insensitive.</li> 550<li>Made <code>assertIsLocale()</code> return the canonical-cased locale from <code>locales</code> instead of the raw input.</li> 551<li>Added new test coverage for case-insensitive behavior in <code>assertIsLocale()</code> and <code>isLocale()</code>.</li> 552</ul> 553</li> 554<li> 555<p>9735b82: Fix fallback assignment generation so locale chains emit dependencies first and avoid "Block-scoped variable used before its declaration" errors. See <a href="https://github.com/opral/inlang-paraglide-js/issues/507">https://github.com/opral/inlang-paraglide-js/issues/507</a> for details.</p> 556</li> 557</ul> 558<h2 id="240"><a href="#240">2.4.0</a></h2> 559<h3 id="minor-changes-21"><a href="#minor-changes-21">Minor Changes</a></h3> 560<ul> 561<li>4111ee6: Add an isomorphic <code>shouldRedirect()</code> helper shared by the middleware and client routers, improve redirect typing, and document the new API in the URL strategy guide.</li> 562</ul>
563<h3 id="patch-changes-31"><a href="#patch-changes-31">Patch Changes</a></h3> 564<ul> 565<li> 566<p>4a48c07: fix: fix eslint incorrectly linting generated files</p> 567<p>closes <a href="https://github.com/opral/inlang-paraglide-js/issues/558">https://github.com/opral/inlang-paraglide-js/issues/558</a></p> 568<p>eslint ignores single-line 'eslint-disable' comments at the start of a file. 569Using a block comment without a closing one instead will prompt eslint to ignore it.</p> 570<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- output[filename] = `// eslint-disable\n${content}`;</span> 571<span class="hljs-addition">+ output[filename] = `/* eslint-disable */\n${content}`;</span> 572</code></pre> 573</li> 574<li> 575<p>4c8921f: Fixes <code>overwriteSetLocale</code> to keep the full <code>(locale, options?)</code> signature when overriding <code>setLocale</code>, preventing TypeScript from rejecting calls that pass <code>{ reload: false }</code>. Adds a regression test ensuring custom handlers receive the options object.</p> 576</li> 577<li> 578<p>Updated dependencies [7791be7]</p> 579<ul> 580<li>@inlang/[email protected]</li> 581</ul> 582</li> 583</ul> 584<h2 id="232"><a href="#232">2.3.2</a></h2> 585<h3 id="patch-changes-32"><a href="#patch-changes-32">Patch Changes</a></h3> 586<ul> 587<li>4ea9e7a: fix: ensure that async custom setLocale funcs resolve with reload: false</li> 588</ul> 589<h2 id="231"><a href="#231">2.3.1</a></h2> 590<h3 id="patch-changes-33"><a href="#patch-changes-33">Patch Changes</a></h3> 591<ul> 592<li>090964b: fix(runtime/set-locale.js): ensure reload waits for async custom setLocale funcs <a href="https://github.com/opral/monorepo/pull/3692">https://github.com/opral/monorepo/pull/3692</a></li> 593</ul> 594<h2 id="230"><a href="#230">2.3.0</a></h2> 595<h3 id="minor-changes-22"><a href="#minor-changes-22">Minor Changes</a></h3> 596<ul> 597<li>bfe8518: Crash the build process (for example during <code>vite build</code>) if paraglide can't compile the project.</li> 598<li>Removed local account loading which suddenly led to crashes for some users.</li> 599</ul> 600<h2 id="220"><a href="#220">2.2.0</a></h2> 601<h3 id="minor-changes-23"><a href="#minor-changes-23">Minor Changes</a></h3> 602<ul> 603<li> 604<p>69ac911: Add support for async custom server strategies with <code>extractLocaleFromRequestAsync</code></p> 605<p>This change introduces a new <code>extractLocaleFromRequestAsync</code> function that supports asynchronous custom server strategies, enabling use cases like fetching user locale preferences from databases.</p> 606<h2 id="whats-changed"><a href="#whats-changed">What's Changed</a></h2> 607<ul> 608<li><strong>New Function</strong>: Added <code>extractLocaleFromRequestAsync</code> that supports async custom server strategies</li> 609<li><strong>Middleware Update</strong>: Server middleware now uses the async version to support async custom strategies</li> 610<li><strong>Breaking Change</strong>: The synchronous <code>extractLocaleFromRequest</code> no longer supports custom server strategies</li> 611<li><strong>Improved Documentation</strong>: Added comprehensive examples and usage guidance</li> 612</ul> 613<h2 id="migration-guide"><a href="#migration-guide">Migration Guide</a></h2> 614<h3 id="for-users-with-custom-server-strategies"><a href="#for-users-with-custom-server-strategies">For users with custom server strategies:</a></h3> 615<p><strong>Before:</strong></p> 616<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// This no longer works in sync version</span> 617<span class="hljs-title function_">defineCustomServerStrategy</span>(<span class="hljs-string">"custom-database"</span>, { 618 <span class="hljs-attr">getLocale</span>: <span class="hljs-title function_">async</span> (request) => { 619 <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-title function_">getUserLocaleFromDatabase</span>(request); 620 }, 621}); 622 623<span class="hljs-keyword">const</span> locale = <span class="hljs-title function_">extractLocaleFromRequest</span>(request); <span class="hljs-comment">// Won't call async custom strategies</span> 624</code></pre> 625<p><strong>After:</strong></p> 626<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// Use the async version for custom strategies</span> 627<span class="hljs-title function_">defineCustomServerStrategy</span>(<span class="hljs-string">"custom-database"</span>, { 628 <span class="hljs-attr">getLocale</span>: <span class="hljs-title function_">async</span> (request) => { 629 <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-title function_">getUserLocaleFromDatabase</span>(request); 630 }, 631}); 632 633<span class="hljs-keyword">const</span> locale = <span class="hljs-keyword">await</span> <span class="hljs-title function_">extractLocaleFromRequestAsync</span>(request); <span class="hljs-comment">// Supports async custom strategies</span> 634</code></pre> 635<h3 id="for-users-calling-extractlocalefromrequest-directly"><a href="#for-users-calling-extractlocalefromrequest-directly">For users calling <code>extractLocaleFromRequest</code> directly:</a></h3> 636<p>If you're using <code>extractLocaleFromRequest</code> directly in your code without custom strategies, no changes are needed. For custom server strategies, switch to <code>extractLocaleFromRequestAsync</code>.</p> 637<p>The server middleware automatically uses the async version, so no changes are needed for standard middleware usage.</p> 638<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/527">https://github.com/opral/inlang-paraglide-js/issues/527</a></p> 639</li> 640</ul>
641<h3 id="patch-changes-34"><a href="#patch-changes-34">Patch Changes</a></h3> 642<ul> 643<li> 644<p>5589e30: (likely) fix: handler is of type <code>unknown</code> ts error <a href="https://github.com/opral/inlang-paraglide-js/issues/529">https://github.com/opral/inlang-paraglide-js/issues/529</a></p> 645</li> 646<li> 647<p>3712f09: Fix cookieDomain default behavior for better server/client cookie compatibility.</p> 648<p>When <code>cookieDomain</code> is undefined or empty, cookies are now set without a domain attribute, scoping them to the exact current domain only (no subdomains). This fixes compatibility issues with server-side cookies that don't include a domain attribute.</p> 649<p><strong>Before</strong>:</p> 650<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// When cookieDomain was undefined, cookies were set as:</span> 651<span class="hljs-variable language_">document</span>.<span class="hljs-property">cookie</span> = 652 <span class="hljs-string">"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; domain=example.com"</span>; 653<span class="hljs-comment">// This made cookies available to subdomains</span> 654</code></pre> 655<p><strong>After</strong>:</p> 656<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// When cookieDomain is undefined, cookies are now set as:</span> 657<span class="hljs-variable language_">document</span>.<span class="hljs-property">cookie</span> = <span class="hljs-string">"PARAGLIDE_LOCALE=en; path=/; max-age=34560000"</span>; 658<span class="hljs-comment">// This scopes cookies to the exact current domain only</span> 659</code></pre> 660<p><strong>Migration</strong>:</p> 661<ul> 662<li>If you want the previous behavior (subdomain sharing), explicitly set <code>cookieDomain</code> in your configuration:</li> 663</ul> 664<pre data-mwc-codeblock=""><code class="hljs language-diff">paraglideWebpackPlugin({ 665 project: './project.inlang', 666 outdir: "./src/paraglide", 667<span class="hljs-addition">+ cookieDomain: 'example.com'</span> 668}) 669</code></pre> 670</li> 671</ul> 672<h2 id="210"><a href="#210">2.1.0</a></h2> 673<h3 id="minor-changes-24"><a href="#minor-changes-24">Minor Changes</a></h3> 674<ul> 675<li> 676<p>4255bd5: Provide functions for getting the preferred language on server and client.</p> 677<p>This defines two new functions for getting the preferred language:</p> 678<ul> 679<li><code>extractLocaleFromHeader</code>: Extracts the locale from the accept-language header on the server.</li> 680<li><code>extractLocaleFromNavigator</code>: Extracts the locale from the navigator.languages array on the client.</li> 681</ul> 682<p>The code was already present in the <code>@inlang/paraglide-js</code> package, but it was not exported. Now it is exported so that 683it can be used in custom strategies.</p> 684</li> 685<li> 686<p>dc287f1: Implement custom strategy concept for locale resolution.</p> 687<p>This introduces a new way to define custom locale resolution strategies alongside built-in strategies. Custom strategies provide a cleaner, more composable approach compared to overwriting <code>getLocale()</code> and <code>setLocale()</code> functions directly.</p> 688<p><strong>New APIs:</strong></p> 689<ul> 690<li><code>defineCustomClientStrategy()</code>: Define custom strategies for client-side locale resolution</li> 691<li><code>defineCustomServerStrategy()</code>: Define custom strategies for server-side locale resolution</li> 692</ul> 693<p><strong>Key features:</strong></p> 694<ul> 695<li>Custom strategies must follow the pattern <code>custom-<name></code> where <code><name></code> contains only alphanumeric characters</li> 696<li>Can be combined with built-in strategies in the strategy array</li> 697<li>Respect strategy order for fallback handling</li> 698<li>Support both client and server environments</li> 699<li>Provide better error isolation and type safety</li> 700</ul> 701<p><strong>Usage example:</strong></p> 702<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-keyword">import</span> { defineCustomClientStrategy } <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/runtime.js"</span>; 703 704<span class="hljs-title function_">defineCustomClientStrategy</span>(<span class="hljs-string">"custom-sessionStorage"</span>, { 705 <span class="hljs-attr">getLocale</span>: <span class="hljs-function">() =></span> <span class="hljs-variable language_">sessionStorage</span>.<span class="hljs-title function_">getItem</span>(<span class="hljs-string">"user-locale"</span>) ?? <span class="hljs-literal">undefined</span>, 706 <span class="hljs-attr">setLocale</span>: <span class="hljs-function">(<span class="hljs-params">locale</span>) =></span> <span class="hljs-variable language_">sessionStorage</span>.<span class="hljs-title function_">setItem</span>(<span class="hljs-string">"user-locale"</span>, locale), 707}); 708</code></pre> 709<p>Then include in your strategy configuration:</p> 710<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-title function_">compile</span>({ 711 <span class="hljs-attr">strategy</span>: [<span class="hljs-string">"custom-sessionStorage"</span>, <span class="hljs-string">"cookie"</span>, <span class="hljs-string">"baseLocale"</span>], 712}); 713</code></pre> 714</li> 715</ul>
716<h3 id="patch-changes-35"><a href="#patch-changes-35">Patch Changes</a></h3> 717<ul> 718<li> 719<p>4c0b997: perf(paraglide): improve bundle size by removing message id fallback for fully translated messages</p> 720</li> 721<li> 722<p>9621803: Add Vary: Accept-Language header when preferredLanguage strategy is used</p> 723<p>Paraglide middleware now automatically sets the <code>Vary: Accept-Language</code> header when performing redirects based on the <code>preferredLanguage</code> strategy. This indicates to clients (CDN cache, crawlers, etc.) that the response will be different depending on the <code>Accept-Language</code> header, ensuring proper caching behavior and SEO compliance.</p> 724<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/522">https://github.com/opral/inlang-paraglide-js/issues/522</a></p> 725</li> 726<li> 727<p>Updated dependencies [22089a2]</p> 728<ul> 729<li>@inlang/[email protected]</li> 730</ul> 731</li> 732</ul> 733<h2 id="2013"><a href="#2013">2.0.13</a></h2> 734<h3 id="patch-changes-36"><a href="#patch-changes-36">Patch Changes</a></h3> 735<ul> 736<li> 737<p>688c7c8: Add support for callbacks in server middleware</p> 738</li> 739<li> 740<p>635861b: <code>extractLocaleFromUrl()</code> now uses a cache for the last value.</p> 741<p>Useful on the client-side where the same URL is being extracted many times for each message on a given page.</p> 742</li> 743</ul> 744<h2 id="2012"><a href="#2012">2.0.12</a></h2> 745<h3 id="patch-changes-37"><a href="#patch-changes-37">Patch Changes</a></h3> 746<ul> 747<li>31337ba: expose <code>createParaglide()</code></li> 748<li>Updated dependencies [56acb22] 749<ul> 750<li>@inlang/[email protected]</li> 751</ul> 752</li> 753</ul> 754<h2 id="2011"><a href="#2011">2.0.11</a></h2> 755<h3 id="patch-changes-38"><a href="#patch-changes-38">Patch Changes</a></h3> 756<ul> 757<li> 758<p>de0439f: Add domain property to cookie options.</p> 759<pre data-mwc-codeblock=""><code class="hljs language-diff">paraglideVitePlugin({ 760 project: './project.inlang', 761 outdir: "./src/paraglide", 762<span class="hljs-addition">+ cookieDomain: 'example.com'</span> 763}), 764</code></pre> 765</li> 766</ul> 767<h2 id="2010"><a href="#2010">2.0.10</a></h2> 768<h3 id="patch-changes-39"><a href="#patch-changes-39">Patch Changes</a></h3> 769<ul> 770<li>d16e853: fix: [2.0.8] Adds extra */ in generated .js files <a href="https://github.com/opral/inlang-paraglide-js/issues/493">https://github.com/opral/inlang-paraglide-js/issues/493</a></li> 771</ul> 772<h2 id="209"><a href="#209">2.0.9</a></h2> 773<h3 id="patch-changes-40"><a href="#patch-changes-40">Patch Changes</a></h3> 774<ul> 775<li>Updated dependencies [bd2c366] 776<ul> 777<li>@inlang/[email protected]</li> 778</ul> 779</li> 780</ul> 781<h2 id="208"><a href="#208">2.0.8</a></h2> 782<h3 id="patch-changes-41"><a href="#patch-changes-41">Patch Changes</a></h3> 783<ul> 784<li> 785<p>5258af0: fix: compiling message bundles with case sensitive ids for the locale module output <a href="https://github.com/opral/inlang-paraglide-js/issues/490">https://github.com/opral/inlang-paraglide-js/issues/490</a></p> 786<p>Case sensitive ids led to duplicate exports in the locale module output. This has been fixed by adjusting the <code>toSafeModuleId()</code> used by the compiler internally to append a number of uppercase characters to de-duplicate the ids.</p> 787<pre data-mwc-codeblock=""><code class="hljs language-diff">toSafeModuleId("helloworld") 788 "helloworld" 789 790toSafeModuleId("helloWorld") 791<span class="hljs-deletion">- "helloworld"</span> 792<span class="hljs-addition">+ "helloworld1"</span> 793</code></pre> 794</li> 795</ul> 796<h2 id="207"><a href="#207">2.0.7</a></h2> 797<h3 id="patch-changes-42"><a href="#patch-changes-42">Patch Changes</a></h3> 798<ul> 799<li>48931f5: make <code>output-structure: locale-modules</code> the default for dev builds <a href="https://github.com/opral/inlang-paraglide-js/issues/486">https://github.com/opral/inlang-paraglide-js/issues/486</a></li> 800<li>Updated dependencies [49a7880] 801<ul> 802<li>@inlang/[email protected]</li> 803</ul> 804</li> 805</ul> 806<h2 id="206"><a href="#206">2.0.6</a></h2> 807<h3 id="patch-changes-43"><a href="#patch-changes-43">Patch Changes</a></h3> 808<ul> 809<li>
8093fa27c0: fix: duplicate (case sensitive) message keys leading to compile error when using <code>output-structure: locale-modules</code>. closes <a href="https://github.com/opral/inlang-paraglide-js/issues/487">https://github.com/opral/inlang-paraglide-js/issues/487</a></li> 810<li>02c2d34: improve: compiler should log warnings when plugins can not be imported</li> 811<li>Updated dependencies [083ff1f] 812<ul> 813<li>@inlang/[email protected]</li> 814</ul> 815</li> 816</ul> 817<h2 id="205"><a href="#205">2.0.5</a></h2> 818<h3 id="patch-changes-44"><a href="#patch-changes-44">Patch Changes</a></h3> 819<ul> 820<li> 821<p>698b9a9: add <code>cookieMaxAge</code> option to compiler and runtime</p> 822<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/483">https://github.com/opral/inlang-paraglide-js/issues/483</a></p> 823<ul> 824<li>Introduced <code>cookieMaxAge</code> option to <code>CompilerOptions</code>, allowing configuration of cookie expiration time.</li> 825<li>Adjusted tests to verify <code>max-age</code> in cookies.</li> 826</ul> 827</li> 828</ul> 829<h2 id="204"><a href="#204">2.0.4</a></h2> 830<h3 id="patch-changes-45"><a href="#patch-changes-45">Patch Changes</a></h3> 831<ul> 832<li>@inlang/[email protected]</li> 833</ul> 834<h2 id="203"><a href="#203">2.0.3</a></h2> 835<h3 id="patch-changes-46"><a href="#patch-changes-46">Patch Changes</a></h3> 836<ul> 837<li>cf404e0: improve: handle duplicate inputs <a href="https://github.com/opral/inlang-paraglide-js/issues/479">https://github.com/opral/inlang-paraglide-js/issues/479</a></li> 838</ul> 839<h2 id="202"><a href="#202">2.0.2</a></h2> 840<h3 id="patch-changes-47"><a href="#patch-changes-47">Patch Changes</a></h3> 841<ul> 842<li>a6c43ea: fix: error handling in paraglideMiddleware breaks SvelteKit features that rely on errors being thrown</li> 843</ul> 844<h2 id="201"><a href="#201">2.0.1</a></h2> 845<h3 id="patch-changes-48"><a href="#patch-changes-48">Patch Changes</a></h3> 846<ul> 847<li>b906c0c: fix: window undefined bug in webpack 848<ul> 849<li>@inlang/[email protected]</li> 850</ul> 851</li> 852</ul> 853<h2 id="paraglide-js-20-ð"><a href="#paraglide-js-20-ð">Paraglide JS 2.0 ð</a></h2> 854<p>Paraglide JS 2.0 had three main goals which have all been achieved:</p> 855<ol> 856<li>Use the new inlang SDK v2 which supports variants <a href="https://github.com/opral/inlang-paraglide-js/issues/201">#201</a>.</li> 857<li>Unify the API across any framework <a href="https://github.com/opral/inlang-paraglide-js/issues/217">#217</a>.</li> 858<li>Support any i18n strategy (cookie, url, domain, session, etc).</li> 859</ol> 860<ul> 861<li>ð <strong>Variants (pluralization) are now supported</strong> <a href="https://paraglidejs.com/variants">docs</a></li> 862<li>ð <strong>No more adapters or providers are needed</strong> (!)</li> 863<li>ð£ï¸ <strong>Any strategy (url, cookie, local storage) is now supported</strong> <a href="https://paraglidejs.com/strategy">docs</a></li> 864</ul> 865<p>In addition, Paraglide JS 2.0 comes with:</p> 866<ul> 867<li>ð <strong>Nested message keys</strong> are now supported (most requested feature!)</li> 868<li>⨠<strong>Auto-imports</strong> when writing <code>m.</code> (no more manual <code>import * as m</code>)</li> 869<li>ð <strong>Arbitrary key names</strong> including emojis via <code>m["ð"]()</code></li> 870<li>ð <strong>Incremental migration</strong> to Paraglide JS is now possible</li> 871<li>ðï¸ <strong>Multi-tenancy support</strong> for domain-based routing</li> 872<li>ð§ <strong>Exposing the compiler API</strong> for advanced workflows</li> 873<li>ð£ï¸ <strong>Configurable routing strategies</strong> (URL, cookie, domain, etc)</li> 874<li>𧪠<strong>Experimental per-locale splitting</strong> for decreasing bundle sizes</li> 875<li>ð <strong>Framework-agnostic server middleware</strong> for SSR (SvelteKit, Next.js, etc)</li> 876</ul> 877<h3 id="highlights"><a href="#highlights">Highlights</a></h3> 878<h4 id="interactive-benchmark"><a href="#interactive-benchmark">Interactive benchmark</a></h4> 879<p>Check out the <a href="https://paraglidejs.com/benchmark">benchmark</a> to see how Paraglide JS compares to other libraries like i18next.</p> 880<p><a href="https://paraglidejs.com/benchmark"><img src="https://cdn.jsdelivr.net/gh/opral/paraglide-js@main/assets/interactive-benchmark.png" alt="Benchmark Visualization"></a></p>
881<h4 id="no-more-adapters-are-needed"><a href="#no-more-adapters-are-needed">No more adapters are needed</a></h4> 882<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- @inlang/paraglide-sveltekit</span> 883<span class="hljs-deletion">- @inlang/paraglide-next</span> 884<span class="hljs-addition">+ // No more adapters are needed</span> 885</code></pre> 886<h4 id="-framework-agnostic-server-middleware"><a href="#-framework-agnostic-server-middleware">ð Framework-Agnostic Server Middleware</a></h4> 887<p>Docs are <a href="https://paraglidejs.com/server-side-rendering">here</a></p> 888<ul> 889<li><strong>New</strong>: Universal <code>paraglideMiddleware()</code> works in any SSR framework</li> 890<li><strong>Built-in</strong>: Automatic locale redirects when user preference detected</li> 891</ul> 892<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">// SvelteKit example - same pattern works for Next.js, Astro, etc.</span> 893<span class="hljs-keyword">import</span> { paraglideMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/server.js"</span>; 894 895<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-title function_">handle</span> = (<span class="hljs-params">{ event, resolve }</span>) => { 896 <span class="hljs-keyword">return</span> <span class="hljs-title function_">paraglideMiddleware</span>(event.<span class="hljs-property">request</span>, <span class="hljs-function">() =></span> <span class="hljs-title function_">resolve</span>(event)); 897}; 898</code></pre> 899<h4 id="ï¸-configurable-routing-strategies"><a href="#ï¸-configurable-routing-strategies">ð£ï¸ Configurable Routing Strategies</a></h4> 900<p>Read more about strategies on the <a href="https://paraglidejs.com/strategy">docs</a>.</p> 901<p>Literally anything is now possible. URL-based, domain-based, path-based, cookie-based, etc.</p> 902<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-title function_">paraglide</span>({ 903 <span class="hljs-attr">strategy</span>: [ 904 <span class="hljs-string">"url"</span>, 905 <span class="hljs-string">"cookie"</span>, 906 <span class="hljs-string">"preferredLanguage"</span>, 907 <span class="hljs-string">"..."</span> 908 ], 909}), 910</code></pre> 911<h4 id="-exposing-the-compiler-api"><a href="#-exposing-the-compiler-api">ð§ Exposing the compiler API</a></h4> 912<ul> 913<li><strong>New</strong>: Direct compiler access for advanced workflows</li> 914<li><strong>Why</strong>: Enable CI/CD pipelines and custom tooling</li> 915<li><strong>Benefit</strong>: Full control over compilation timing/caching</li> 916</ul> 917<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">// New programmatic API</span> 918<span class="hljs-keyword">import</span> { compile } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inlang/paraglide-js"</span>; 919 920<span class="hljs-keyword">await</span> <span class="hljs-title function_">compile</span>({ 921 <span class="hljs-attr">project</span>: <span class="hljs-string">"./project.inlang"</span>, 922 <span class="hljs-attr">outdir</span>: <span class="hljs-string">"./src/paraglide"</span>, 923}); 924</code></pre> 925<h4 id="-arbitrary-key-names"><a href="#-arbitrary-key-names">ð Arbitrary key names</a></h4> 926<ul> 927<li><strong>New</strong>: Arbitrary key names including emojis via `m<a href="">"ð"</a></li> 928<li><strong>Why</strong>: Enable nesting of messages</li> 929<li><strong>Benefit</strong>: More expressive and fun translations</li> 930</ul> 931<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">// Paraglide 1.0</span> 932m.<span class="hljs-title function_">some_message</span>(); <span class="hljs-comment">// â Works</span> 933m.<span class="hljs-property">nested</span>.<span class="hljs-title function_">message</span>(); <span class="hljs-comment">// ð¥ Error</span> 934 935<span class="hljs-comment">// Paraglide 2.0</span> 936m.<span class="hljs-title function_">some_message</span>(); <span class="hljs-comment">// â Works</span> 937m[<span class="hljs-string">"nested.message"</span>](); <span class="hljs-comment">// â Works</span> 938 939<span class="hljs-comment">// Even emojis are supported</span> 940m[<span class="hljs-string">"ð"</span>](); 941</code></pre> 942<h4 id="-incrementally-migrating-to-paraglide-js"><a href="#-incrementally-migrating-to-paraglide-js">ð Incrementally migrating to Paraglide JS</a></h4> 943<p>Paraglide JS 2.0 can load multiple <a href="https://paraglidejs.com/file-formats">translation file formats</a>. As such, you can incrementally migrate to Paraglide JS with existing translation file formats.</p> 944<pre data-mwc-codeblock=""><code class="hljs language-js"><span class="hljs-comment">// In this example, Paraglide JS compiles i18next translation files</span> 945<span class="hljs-comment">// which enables using both i18next and Paraglide JS.</span> 946 947<span class="hljs-keyword">
947import</span> i18next <span class="hljs-keyword">from</span> <span class="hljs-string">"i18next"</span>; 948<span class="hljs-keyword">import</span> { m } <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/messages.js"</span>; 949 950<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(i18next.<span class="hljs-title function_">t</span>(<span class="hljs-string">"greeting"</span>, { <span class="hljs-attr">name</span>: <span class="hljs-string">"World"</span> })); 951<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(m.<span class="hljs-title function_">greeting</span>({ <span class="hljs-attr">name</span>: <span class="hljs-string">"World"</span> })); 952</code></pre> 953<h4 id="ï¸-multi-tenancy-support"><a href="#ï¸-multi-tenancy-support">ðï¸ Multi-tenancy support</a></h4> 954<p>Paraglide JS 2.0 supports multi-tenant applications. Read more about it <a href="https://paraglidejs.com/multi-tenancy">here</a>.</p> 955<pre data-mwc-codeblock=""><code># Domain-based with sub-locale 956customer1.fr/about â French (default) 957customer1.fr/en/about â English version 958 959# Domain-based with root locale 960customer2.com/about â English (default) 961customer2.com/fr/about â French version 962 963# Path-based for any domain 964example.com/en/about â English 965example.com/fr/about â French 966app.example.com/en/about â English 967app.example.com/fr/about â French 968</code></pre> 969<h3 id="migrating-breaking-changes"><a href="#migrating-breaking-changes">Migrating breaking changes</a></h3> 970<p>If problems arise, please refer to the framework-specific getting started guide:</p> 971<ul> 972<li><a href="https://paraglidejs.com/sveltekit">SvelteKit</a></li> 973<li><a href="https://paraglidejs.com/next-js">Next.js</a></li> 974<li><a href="https://paraglidejs.com/astro">Astro</a></li> 975<li><a href="https://paraglidejs.com/vite">Vite</a></li> 976<li><a href="https://paraglidejs.com/react-router">React Router</a></li> 977</ul> 978<h4 id="languagetag-got-renamed-to-locale"><a href="#languagetag-got-renamed-to-locale"><code>LanguageTag</code> got renamed to <code>locale</code></a></h4> 979<p>To align with industry standards, we renamed <code>LanguageTag</code> to <code>locale</code>.</p> 980<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-languageTag()</span> 981<span class="hljs-addition">+getLocale()</span> 982<span class="hljs-deletion">-setLanguageTag()</span> 983<span class="hljs-addition">+setLocale()</span> 984<span class="hljs-deletion">-availableLanguageTags</span> 985<span class="hljs-addition">+locales</span> 986</code></pre> 987<h4 id="remove-adapters-inlangparaglide--from-your-dependencies"><a href="#remove-adapters-inlangparaglide--from-your-dependencies">Remove adapters <code>@inlang/paraglide-*</code> from your dependencies</a></h4> 988<pre data-mwc-codeblock=""><code class="hljs language-diff">// package.json 989{ 990 "dependencies": { 991<span class="hljs-deletion">- "@inlang/paraglide-sveltekit": "^1.0.0",</span> 992<span class="hljs-deletion">- "@inlang/paraglide-next": "^1.0.0",</span> 993<span class="hljs-deletion">- "@inlang/paraglide-astro": "^1.0.0",</span> 994<span class="hljs-deletion">- "@inlang/paraglide-vite": "^1.0.0",</span> 995<span class="hljs-addition">+ "@inlang/paraglide-js": "^2.0.0",</span> 996 } 997} 998``` 999 1000### Replace adapter bundler plugins 1001 1002```diff 1003// vite.config.js 1004<span class="hljs-deletion">-import { paraglide } from "@inlang/paraglide-vite";</span> 1005<span class="hljs-addition">+import { paraglideVitePlugin } from "@inlang/paraglide-js";</span> 1006 1007 1008export default defineConfig({ 1009 plugins: [ 1010<span class="hljs-deletion">- paraglide({</span> 1011<span class="hljs-addition">+ paraglideVitePlugin({</span> 1012 project: "./project.inlang", 1013 outdir: "./src/paraglide", 1014 }), 1015 ], 1016}); 1017 1018</code></pre> 1019<h4 id="remove-paraglide-providers"><a href="#remove-paraglide-providers">Remove Paraglide Providers</a></h4> 1020<p>Paraglide JS 2.0 no longer requires providers.</p> 1021<pre data-mwc-codeblock=""><code class="hljs language-diff">// app.tsx, layout.svelte, etc. 1022<span class="hljs-deletion">-import { ParaglideProvider } from "@inlang/paraglide-{framework}";</span> 1023 1024function App() { 1025 return ( 1026<span class="hljs-deletion">- <ParaglideProvider></span> 1027 <YourApp /> 1028<span class="hljs-deletion">- </ParaglideProvider></span> 1029 ) 1030} 1031</code></pre> 1032<h4 id="shorten-key-names-longer-than-255-characters"><a href="#shorten-key-names-longer-than-255-characters">Shorten key names longer than 255 characters</a></h4> 1033<p>Paraglide JS 2.0 build output now defaults to <a href="https://paraglidejs.com/compiler-options#outputstructure">message-modules</a> to improve tree-shaking. Some filesystem's limitations require key names to be shorter than 255 characters.</p> 1034<p>
1034Upvote <a href="https://github.com/opral/inlang-paraglide-js/issues/423">#423</a> to remove this limitation.</p> 1035<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- m.this_is_a_very_long_key_name_that_should_be_shortened()</span> 1036<span class="hljs-addition">+ m.shortened_key_name()</span> 1037</code></pre> 1038<h4 id="changing-the-locale-requires-a-reload"><a href="#changing-the-locale-requires-a-reload">Changing the locale requires a reload</a></h4> 1039<p>Changing the locale works via <code>setLocale()</code> in any framework now.</p> 1040<p>If you used an adapter in v1 like the SvelteKit one, this behavior is new. The new behaviour leads to a page reload. The reload is a deliberate design decision. Reloading the site eliminates the need for providers, adapters, and API differences between frameworks. Furthermore, optimizations like per-locale splitting is expected to be easier to implement.</p> 1041<p>Read <a href="https://github.com/opral/inlang-paraglide-js/issues/438#issuecomment-2703733096">https://github.com/opral/inlang-paraglide-js/issues/438#issuecomment-2703733096</a> for more information.</p> 1042<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-<a href="/de">Deutsch</a></span> 1043<span class="hljs-addition">+<button onclick="setLocale('de')">Deutsch</button></span> 1044</code></pre> 1045<h4 id="lint-rules-were-deprecated"><a href="#lint-rules-were-deprecated">Lint rules were deprecated</a></h4> 1046<p>Remove lint rules from your project modules.</p> 1047<p>We want to re-introduce lint rules in a better form in the future. Please upvote the <a href="https://github.com/opral/lix-sdk/issues/239">#239 lix validation rules</a> proposal.</p> 1048<pre data-mwc-codeblock=""><code class="hljs language-diff">modules: [ 1049<span class="hljs-deletion">- "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js",</span> 1050<span class="hljs-deletion">- "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js"</span> 1051 ... 1052] 1053 1054</code></pre> 1055<h4 id="localizehref-is-now-required"><a href="#localizehref-is-now-required"><code>localizeHref()</code> is now required</a></h4> 1056<p>Some Paraglide adapters used AST transforms to automatically transform <code><a></code> into localized links. That led to many bugs and edge cases. The AST transforms were removed for v2.</p> 1057<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-<a href="/page"></a></span> 1058<span class="hljs-addition">+<a href={localizeHref("/page")}</span> 1059</code></pre> 1060<h2 id="200-beta31-released-as-200"><a href="#200-beta31-released-as-200">2.0.0-beta.31 (released as 2.0.0)</a></h2> 1061<ul> 1062<li> 1063<p>feat: New API: <code>createParaglide()</code></p> 1064<p>The function allows a no build step or before build step access to Paraglide's compiled APIs.</p> 1065<pre data-mwc-codeblock=""><code class="hljs language-typescript"><span class="hljs-keyword">const</span> project = <span class="hljs-keyword">await</span> fs.<span class="hljs-title function_">readFile</span>(<span class="hljs-string">"./project.inlang"</span>); 1066 1067<span class="hljs-keyword">const</span> paraglide = <span class="hljs-keyword">await</span> <span class="hljs-title function_">createParaglideModule</span>({ 1068 project, 1069 <span class="hljs-attr">compilerOptions</span>: { 1070 <span class="hljs-attr">strategy</span>: [<span class="hljs-string">"url"</span>], 1071 }, 1072}); 1073 1074<span class="hljs-comment">// Use runtime functions</span> 1075paraglide.<span class="hljs-title function_">localizeUrl</span>(<span class="hljs-string">"https://example.com"</span>, { <span class="hljs-attr">locale</span>: <span class="hljs-string">"de"</span> }); 1076 1077<span class="hljs-comment">// Use server middleware</span> 1078app.<span class="hljs-title function_">use</span>(paraglide.<span class="hljs-title function_">paraglideMiddleware</span>()); 1079</code></pre> 1080</li> 1081<li> 1082<p>fix: <code>getLocale</code> returns correct value on SvelteKit server <a href="https://github.com/opral/inlang-paraglide-js/issues/461">#461</a></p> 1083</li> 1084<li> 1085<p>fix: Prevent redirect loops by normalizing URLs with trailing slashes <a href="https://github.com/opral/inlang-paraglide-js/issues/408">#408</a></p> 1086</li> 1087<li> 1088<p>fix: Support for explicit port numbers in URL patterns</p> 1089</li> 1090<li> 1091<p>improve: Better error handling in server middleware</p> 1092</li> 1093</ul> 1094<h2 id="200-beta30"><a href="#200-beta30">2.0.0-beta.30</a></h2> 1095<ul> 1096<li> 1097<p>improve: if no url pattern matches, <code>localizeUrl()</code> and <code>deLocalizeUrl()</code> will return the input url unchanged instead of throwing an error <a href="https://github.com/opral/inlang-paraglide-js/issues/452#issuecomment-2715761308">#452</a></p> 1098</li> 1099<li> 1100<p>improve: make AsyncLocalStorage tree-shakable by moving <code>disableAsyncLocalStorage</code> into the compiler options <a href="https://github.com/opral/inlang-paraglide-js/issues/424#issuecomment-2711453627">#424</a></p> 1101</li> 1102</ul> 1103<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })</span> 1104<span class="hljs-addition">+ serverMiddleware(req, resolve)</span> 1105 1106paraglideVitePlugin({ 1107 // ... 1108<span class="hljs-addition">+ disableAsyncLocalStorage: true</span> 1109}) 1110 1111</code></pre> 1112<ul> 1113<li>improve: allow fall through. enables partially localized patterns and thereby eases adoption.</li> 1114</ul> 1115<h2 id="200-beta29"><a href="#200-beta29">2.0.0-beta.29</a></h2> 1116<ul> 1117<li> 1118<p>fix <a href="https://github.com/opral/inlang-paraglide-js/issues/455">#455 setLocale and getLocale call each other in a loop</a></p> 1119</li> 1120<li> 1121<p>fix <a href="https://github.com/opral/inlang-paraglide-js/issues/454">#454 Adapt config to the new localized param of beta.28</a></p> 1122</li> 1123</ul> 1124<h2 id="200-beta28"><a href="#200-beta28">2.0.0-beta.28</a></h2> 1125<h3 id="breaking-update-to-the-urlpattern-api"><a href="#breaking-update-to-the-urlpattern-api">BREAKING update to the URLPattern API</a></h3> 1126<p><a href="https://github.com/opral/monorepo/pull/3485">https://github.com/opral/monorepo/pull/3485</a></p> 1127<p>The <code>localizedNamedGroups</code> and <code>deLocalizedNamedGroups</code> API has been replaced with a tuple-based <code>localized</code> array to:</p> 1128<ul> 1129<li>enable translated pathnames in any combination</li> 1130<li>make the API more intuitive</li> 1131</ul> 1132<h4 id="migration-guide-1"><a href="#migration-guide-1">Migration Guide:</a></h4> 1133<p><strong>Refer to the updated documentation <a href="https://paraglidejs.com/strategy#url">here</a>.</strong></p> 1134<p>Before</p> 1135<pre data-mwc-codeblock=""><code class="hljs language-json"><span class="hljs-punctuation">{</span> 1136 <span class="hljs-attr">"pattern"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">
1136"https://:domain(.*)/:locale(de|fr)?/:path*"</span><span class="hljs-punctuation">,</span> 1137 <span class="hljs-attr">"deLocalizedNamedGroups"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"locale"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">null</span></span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 1138 <span class="hljs-attr">"localizedNamedGroups"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> 1139 <span class="hljs-attr">"en"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"locale"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">null</span></span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 1140 <span class="hljs-attr">"fr"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"locale"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"fr"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 1141 <span class="hljs-attr">"de"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"locale"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"de"</span> <span class="hljs-punctuation">}</span> 1142 <span class="hljs-punctuation">}</span> 1143<span class="hljs-punctuation">}</span> 1144</code></pre> 1145<p>After</p> 1146<pre data-mwc-codeblock=""><code class="hljs language-json"><span class="hljs-punctuation">{</span> 1147 <span class="hljs-attr">"pattern"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://:domain(.*)/:path*"</span><span class="hljs-punctuation">,</span> 1148 <span class="hljs-attr">"localized"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> 1149 <span class="hljs-punctuation">[</span><span class="hljs-string">"fr"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"https://:domain(.*)/fr/:path*"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> 1150 <span class="hljs-punctuation">[</span><span class="hljs-string">"de"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"https://:domain(.*)/de/:path*"</span><span class="hljs-punctuation">]</span> 1151 <span class="hljs-punctuation">[</span><span class="hljs-string">"en"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"https://:domain(.*)/:path*"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span> 1152 <span class="hljs-punctuation">]</span> 1153<span class="hljs-punctuation">}</span> 1154</code></pre> 1155<h3 id="other-changes"><a href="#other-changes">other changes</a></h3> 1156<ul> 1157<li> 1158<p>improve: fallback to <code>typeof window</code> in vite <a href="https://github.com/opral/inlang-paraglide-js/issues/445">#445</a></p> 1159</li> 1160<li> 1161<p>make <code>setLocale()</code> set all strategies. Setting all strategies aligns with user expectations and ensures that server APIs can receive the cookie of the client, for example. <a href="https://github.com/opral/inlang-paraglide-js/issues/439">#439</a></p> 1162</li> 1163<li> 1164<p>new <code>generateStaticLocalizedUrls()</code> API <a href="https://github.com/opral/inlang-paraglide-js/issues/433">#443</a></p> 1165</li> 1166</ul> 1167<pre data-mwc-codeblock=""><code class="hljs language-diff">const localizedUrls = generateStaticLocalizedUrls([ 1168 "/example", 1169 "/page/blog", 1170 "/123/hello" 1171]) 1172 1173console.log(localizedUrls.map(url => url.pathnames)) 1174>> /de/example 1175>> /fr/example 1176>> ... 1177</code></pre> 1178<h2 id="200-beta27"><a href="#200-beta27">2.0.0-beta.27</a></h2> 1179<ul> 1180<li>fix wrong matching in API requests <a href="https://github.com/opral/inlang-paraglide-js/issues/427">#427</a></li> 1181</ul> 1182<p>Paraglide JS is no longer extracting the locale from API requests for the <code>url</code> strategy because that can lead to unwanted re-directs. To get the right locale in API requests, at least add the <code>baseLocale</code>
1182 strategy to your options.</p> 1183<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-strategy: ["url"]</span> 1184<span class="hljs-addition">+strategy: ["url", "cookie", "baseLocale"]</span> 1185</code></pre> 1186<ul> 1187<li> 1188<p>consolidated <code>message-modules</code> output into a single file <a href="https://github.com/opral/inlang-paraglide-js/issues/434">#434</a> to severaly improve scalability</p> 1189</li> 1190<li> 1191<p><code>experimentalMiddlewareLocaleSplitting</code> option <a href="https://github.com/opral/inlang-paraglide-js/issues/425#issuecomment-2692351073">https://github.com/opral/inlang-paraglide-js/issues/425#issuecomment-2692351073</a></p> 1192</li> 1193<li> 1194<p>fix <a href="https://github.com/opral/inlang-paraglide-js/issues/430">setLocale() triggers re-loads if the same locale is set</a></p> 1195</li> 1196<li> 1197<p>fix <a href="https://github.com/opral/inlang-paraglide-js/issues/442">serverMiddleware() throws when cookie contains invalid locale</a></p> 1198</li> 1199<li> 1200<p>add <code>localStorage</code> strategy <a href="https://github.com/opral/inlang-paraglide-js/issues/431">#431</a></p> 1201</li> 1202<li> 1203<p>fix url strategy with optional locale always resoles base locale <a href="https://github.com/opral/inlang-paraglide-js/issues/436">#436</a></p> 1204</li> 1205</ul> 1206<h2 id="200-beta26"><a href="#200-beta26">2.0.0-beta.26</a></h2> 1207<ul> 1208<li>replace <code>node:crypto</code> with the Web Crypto API <a href="https://github.com/opral/inlang-paraglide-js/issues/424">https://github.com/opral/inlang-paraglide-js/issues/424</a></li> 1209</ul> 1210<h2 id="200-beta25"><a href="#200-beta25">2.0.0-beta.25</a></h2> 1211<ul> 1212<li>added optional localized groups</li> 1213<li>keeps hashes, etc. in the URL when localizing <a href="https://github.com/opral/monorepo/pull/3452">https://github.com/opral/monorepo/pull/3452</a></li> 1214<li>fixes the multi-variant return</li> 1215</ul> 1216<h2 id="200-beta24"><a href="#200-beta24">2.0.0-beta.24</a></h2> 1217<ul> 1218<li>changes the redirect status from <code>302</code> to <code>307</code> <a href="https://github.com/opral/inlang-paraglide-js/issues/416">https://github.com/opral/inlang-paraglide-js/issues/416</a></li> 1219<li>adds a <code>cleanOutdir</code> option which defaults to true <a href="https://github.com/opral/inlang-paraglide-js/issues/420">https://github.com/opral/inlang-paraglide-js/issues/420</a></li> 1220<li>adds a <code>machine-translate</code> command if desired on init</li> 1221</ul> 1222<h2 id="200-beta23"><a href="#200-beta23">2.0.0-beta.23</a></h2> 1223<p>Renames and splits the <code>serverMiddleware()</code> into a dedicated <code>server.js</code> file to avoid bundler issues.</p> 1224<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- import { serverMiddleware } from "./paraglide/runtime.js";</span> 1225<span class="hljs-addition">+ import { paraglideMiddleware } from "./paraglide/server.js";</span> 1226</code></pre> 1227<h2 id="200-beta22"><a href="#200-beta22">2.0.0-beta.22</a></h2> 1228<ul> 1229<li>fix <code>serverMiddleware()</code> only imports async_hooks on the server</li> 1230<li>add <code>serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })</code> to disable async local storage</li> 1231<li>fix <code>serverMiddleware()</code> throws in next js when <code>url</code> strategy is not used <a href="https://github.com/opral/inlang-paraglide-js/issues/411#issuecomment-2683530533">https://github.com/opral/inlang-paraglide-js/issues/411#issuecomment-2683530533</a></li> 1232</ul> 1233<h2 id="200-beta21"><a href="#200-beta21">2.0.0-beta.21</a></h2> 1234<ul> 1235<li>compile arbitrary message keys <a href="https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2680006131">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2680006131</a></li> 1236<li>only polyfills <code>URLPattern</code> if needed <a href="https://github.com/opral/inlang-paraglide-js/issues/381">https://github.com/opral/inlang-paraglide-js/issues/381</a></li> 1237<li>don't include <code>url</code> strategy by default <a href="https://github.com/opral/inlang-paraglide-js/issues/405">https://github.com/opral/inlang-paraglide-js/issues/405</a></li> 1238<li>fixes webpack watch mode <a href="https://github.com/opral/inlang-paraglide-js/issues/406">https://github.com/opral/inlang-paraglide-js/issues/406</a></li> 1239</ul> 1240<h2 id="200-beta20"><a href="#200-beta20">2.0.0-beta.20</a></h2> 1241<ul> 1242<li>automatic re-directs in <code>serverMiddleware()</code> <a href="https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2675823651">
1242https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2675823651</a></li> 1243<li>various bug fixes and improvements</li> 1244</ul> 1245<h2 id="200-beta19"><a href="#200-beta19">2.0.0-beta.19</a></h2> 1246<p>NO MORE ADAPTERS NEEDED.</p> 1247<p>If you have code from an adapter, remove it and follow the examples in the documentation. <a href="https://paraglidejs.com/sveltekit">https://paraglidejs.com/sveltekit</a></p> 1248<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-@inlang/paraglide-sveltekit</span> 1249<span class="hljs-deletion">-@inlang/paraglide-next</span> 1250<span class="hljs-deletion">-@inlang/paraglide-astro</span> 1251</code></pre> 1252<ul> 1253<li> 1254<p>introduced <code>serverMiddleware()</code> <a href="https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2673375348">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2673375348</a></p> 1255</li> 1256<li> 1257<p>rename <code>defineGetLocale()</code> and <code>defineSetLocale()</code> to <code>overwriteGetLocale()</code> and <code>overwriteSetLocale()</code> <a href="https://github.com/opral/inlang-paraglide-js/issues/382">https://github.com/opral/inlang-paraglide-js/issues/382</a></p> 1258</li> 1259<li> 1260<p>enables <code>import { m } from "./paraglide/messages.js"</code> for auto imports <a href="https://github.com/opral/inlang-paraglide-js/issues/345">https://github.com/opral/inlang-paraglide-js/issues/345</a></p> 1261</li> 1262<li> 1263<p>adds the <code>strategy</code> compiler option to the cli <a href="https://github.com/opral/inlang-paraglide-js/issues/316">https://github.com/opral/inlang-paraglide-js/issues/316</a></p> 1264</li> 1265</ul> 1266<h2 id="200-beta18"><a href="#200-beta18">2.0.0-beta.18</a></h2> 1267<p>Added URLPatterns as a replacement for the beta 17 pathnames API.</p> 1268<p>The URLPattern API is extremly powerful. You can express base paths, translated pathnames, domain based localization, and even multi-tenancy.</p> 1269<p>Read the docs <a href="https://paraglidejs.com/strategy#url">here</a> and make PRs to improve the documentation.</p> 1270<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1271<span class="hljs-deletion">- strategy: ["pathname"],</span> 1272<span class="hljs-addition">+ strategy: ["url"],</span> 1273}) 1274</code></pre> 1275<p>The <code>localizePath()</code> API had to be replaced by a new <code>localizeHref()</code> API. Please give feedback on the new API in <a href="https://github.com/opral/inlang-paraglide-js/issues/380">#380</a></p> 1276<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- <a href={localizePath("/about")}>About</a></span> 1277<span class="hljs-addition">+ <a href={localizeHref("/about")}>About</a></span> 1278</code></pre> 1279<h2 id="200-beta17"><a href="#200-beta17">2.0.0-beta.17</a></h2> 1280<p>Add support for <code>pathnames</code> API <a href="https://github.com/opral/inlang-paraglide-js/issues/359">https://github.com/opral/inlang-paraglide-js/issues/359</a></p> 1281<p>You can now create whatever pathname pattern you want. The syntax is provided by <a href="https://github.com/pillarjs/path-to-regexp">https://github.com/pillarjs/path-to-regexp</a>.</p> 1282<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1283 strategy: ["pathname", "cookie", "baseLocale"], 1284<span class="hljs-addition">+ pathnames: {</span> 1285<span class="hljs-addition">+ "{*path}": {</span> 1286<span class="hljs-addition">+ "de": "/de{/*path}",</span> 1287<span class="hljs-addition">+ "en": "/en{/*path}",</span> 1288} 1289} 1290}) 1291</code></pre> 1292<p>Add support for <code>pathnameBase</code> <a href="https://github.com/opral/inlang-paraglide-js/issues/362">https://github.com/opral/inlang-paraglide-js/issues/362</a></p> 1293<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1294 strategy: ["pathname", "cookie", "baseLocale"], 1295<span class="hljs-addition">+ pathnameBase: "/base"</span> 1296}) 1297 1298</code></pre> 1299<h2 id="200-beta16"><a href="#200-beta16">2.0.0-beta.16</a></h2> 1300<p>New <code>strategy</code> API. See <a href="https://github.com/opral/inlang-paraglide-js/issues/346">https://github.com/opral/inlang-paraglide-js/issues/346</a>.</p> 1301<p>You can now define your own stragegy for getting and setting a locale.</p> 1302<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1303<span class="hljs-addition">+ strategy: ["pathname", "cookie", "baseLocale"]</span> 1304}) 1305</code></pre> 1306<h2 id="200-beta14"><a href="#200-beta14">
13062.0.0-beta.14</a></h2> 1307<p>Fixes windows path normalization <a href="https://github.com/opral/monorepo/pull/3374">https://github.com/opral/monorepo/pull/3374</a></p> 1308<h2 id="200-beta13"><a href="#200-beta13">2.0.0-beta.13</a></h2> 1309<ul> 1310<li>flat compiler options</li> 1311</ul> 1312<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1313<span class="hljs-deletion">- compilerOptions: {</span> 1314<span class="hljs-deletion">- emitPrettierIgnore: false,</span> 1315<span class="hljs-deletion">- },</span> 1316<span class="hljs-addition">+ emitPrettierIgnore: false,</span> 1317}) 1318</code></pre> 1319<ul> 1320<li>removed <code>experimentalEmitTs</code>. the overhead of maintaing two syntaxes is too large <a href="https://github.com/opral/inlang-paraglide-js/issues/329">https://github.com/opral/inlang-paraglide-js/issues/329</a></li> 1321</ul> 1322<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1323<span class="hljs-deletion">- experimentalEmitTs: true,</span> 1324}) 1325</code></pre> 1326<h2 id="200-beta11"><a href="#200-beta11">2.0.0-beta.11</a></h2> 1327<ul> 1328<li>improve: compiler awaits ongoing compilations before starting a new one</li> 1329<li>update dependency that fixes <a href="https://github.com/opral/inlang-paraglide-js/issues/320">https://github.com/opral/inlang-paraglide-js/issues/320</a></li> 1330</ul> 1331<h2 id="200-beta10"><a href="#200-beta10">2.0.0-beta.10</a></h2> 1332<ul> 1333<li>remove <code>available</code> prefix from locale APIs alltogether <a href="https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2596202820">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2596202820</a></li> 1334</ul> 1335<h2 id="200-beta9"><a href="#200-beta9">2.0.0-beta.9</a></h2> 1336<ul> 1337<li>Expose compiler on the index</li> 1338</ul> 1339<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-import { compile } from "@inlang/paraglide-js/compiler";</span> 1340<span class="hljs-addition">+import { compile } from "@inlang/paraglide-js";</span> 1341</code></pre> 1342<ul> 1343<li>expose paraglide compile args</li> 1344</ul> 1345<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-addition">+ import { type CompileArgs } from "@inlang/paraglide-js";</span> 1346</code></pre> 1347<h2 id="200-beta8"><a href="#200-beta8">2.0.0-beta.8</a></h2> 1348<ul> 1349<li>rename <code>runtime.locales</code> to <code>runtime.availableLocales</code> to align with v1 API and avoid ambiguity <a href="https://github.com/opral/inlang-paraglide-js/issues/314">https://github.com/opral/inlang-paraglide-js/issues/314</a></li> 1350<li>remove legacy <code>languageTag</code> APIs <a href="https://github.com/opral/inlang-paraglide-js/issues/315">https://github.com/opral/inlang-paraglide-js/issues/315</a></li> 1351</ul> 1352<h2 id="200-beta7"><a href="#200-beta7">2.0.0-beta.7</a></h2> 1353<ul> 1354<li>fixed windows path problems</li> 1355<li>increased performance of the compiler by removing a redundant setTimeout</li> 1356<li>increased performance of the compiler by removing prettier</li> 1357<li><code>experimentalEmitTs</code> flag</li> 1358</ul> 1359<h2 id="200-beta3"><a href="#200-beta3">2.0.0-beta.3</a></h2> 1360<h3 id="patch-changes-49"><a href="#patch-changes-49">Patch Changes</a></h3> 1361<ul> 1362<li>remove <code>fast-glob</code> as dependency in favor of node's built-in <code>fs.glob</code> (a new API in node 22)</li> 1363</ul> 1364<h2 id="200"><a href="#200">2.0.0</a></h2> 1365<h3 id="major-changes"><a href="#major-changes">Major changes</a></h3> 1366<ul> 1367<li>Upgrade to @inlang/sdk v2</li> 1368<li>Support for variants (pluralization, gendering, A/B test, etc.)</li> 1369</ul> 1370<h3 id="minor-changes-25"><a href="#minor-changes-25">Minor Changes</a></h3> 1371<ul> 1372<li> 1373<p>1d62451: remove <code>dedent</code> dependency in CLI</p> 1374</li> 1375<li> 1376<p>5d906bd: refactor: remove posthog-node dependency</p> 1377<p>Posthog node has been replaced for a fetch call. Removing 3 (posthog + 2 transitive dependencies).</p> 1378</li> 1379<li> 1380<p>855a71c: adds <code>experimentalEmitTsDeclarations</code> compiler option <a href="https://github.com/opral/inlang-paraglide-js/issues/288">https://github.com/opral/inlang-paraglide-js/issues/288</a></p> 1381<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1382 // ... 1383 options: { 1384<span class="hljs-addition">+ experimentalEmitTsDeclarations: true</span> 1385 } 1386}) 1387</code></pre> 1388<p>Projects can now select if TypeScript declaration file should be emitted. The need for the <code>allowJs: true</code> option in TypeScript configs becomes redundant at the cost of slower compilation times (<a href="https://github.com/opral/inlang-paraglide-js/issues/238">https://github.com/opral/inlang-paraglide-js/issues/238</a>).</p> 1389</li> 1390<li> 1391<p>346c21b: maintenance: remove path prop from tsconfig</p> 1392<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-"paths": {</span> 1393<span class="hljs-deletion">- "~/*": ["./src/*"]</span> 1394<span class="hljs-deletion">-}</span> 1395</code></pre> 1396<p>So not worth it "nice to have" "but it's better DX" thing. Breaks path resolving in JS. Vitest needed a vite config to resolve the paths because only TS knew how to resolve thep paths. Etc. Etc. Etc.</p> 1397</li> 1398<li> 1399<p>fb06546: adds <code>emitGitIgnore</code> and <code>emitPrettierIgnore</code> compiler options</p> 1400<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/189">https://github.com/opral/inlang-paraglide-js/issues/189</a></p> 1401<pre data-mwc-codeblock=""><code class="hljs language-diff">await compile({ 1402 // ... 1403 options: { 1404<span class="hljs-addition">
1404+ emitPrettierIgnore: false</span> 1405<span class="hljs-addition">+ emitGitIgnore: false</span> 1406 } 1407}) 1408</code></pre> 1409</li> 1410<li> 1411<p>e2b9e24: feat: expose compiler as library</p> 1412<p>closes <a href="https://github.com/opral/inlang-paraglide-js/issues/206">https://github.com/opral/inlang-paraglide-js/issues/206</a></p> 1413<p>The Paraglide compiler is now exposed as a library. This allows you to use and extend the compiler however you need.</p> 1414<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-keyword">import</span> { compile } <span class="hljs-keyword">from</span> <span class="hljs-string">"@inlang/paraglide-js/compiler"</span>; 1415 1416<span class="hljs-keyword">await</span> <span class="hljs-title function_">compile</span>({ 1417 <span class="hljs-attr">path</span>: <span class="hljs-string">"/path/to/project.inlang"</span>, 1418 <span class="hljs-attr">outdir</span>: <span class="hljs-string">"/path/to/output"</span>, 1419}); 1420</code></pre> 1421</li> 1422<li> 1423<p>44ac447: maintenance: remove vite in favor of tsc to build paraglide js lib</p> 1424<p>Closes <a href="https://github.com/opral/inlang-paraglide-js/issues/208">https://github.com/opral/inlang-paraglide-js/issues/208</a></p> 1425<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">- "build": "vite build",</span> 1426<span class="hljs-addition">+ "build": "tsc",</span> 1427</code></pre> 1428<p>Paraglide JS used vite to build the library. This change removes vite in favor of tsc to build the library. This change is made to simplify the build process and to make it easier to maintain the library in the future.</p> 1429</li> 1430</ul> 1431<h2 id="1112"><a href="#1112">1.11.2</a></h2> 1432<h3 id="patch-changes-50"><a href="#patch-changes-50">Patch Changes</a></h3> 1433<ul> 1434<li>59c8b11: Fix Ninja recommendation and adoption if working directory is not the repo root</li> 1435</ul> 1436<h2 id="1111"><a href="#1111">1.11.1</a></h2> 1437<h3 id="patch-changes-51"><a href="#patch-changes-51">Patch Changes</a></h3> 1438<ul> 1439<li> 1440<p>14d80b3: Removed the "Which tech-stack are you using?" prompt from the <code>init</code> command as it was not providing any real value. All it did was link you to the appropriate documentation.</p> 1441<p>From now on we rely on the docuemntation site to guide people to the correct documenation for their framework.</p> 1442<ul> 1443<li>SvelteKit: <a href="https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n">https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n</a></li> 1444<li>NextJs: <a href="https://inlang.com/m/osslbuzt/paraglide-next-i18n">https://inlang.com/m/osslbuzt/paraglide-next-i18n</a></li> 1445<li>Astro: <a href="https://inlang.com/m/iljlwzfs/paraglide-astro-i18n">https://inlang.com/m/iljlwzfs/paraglide-astro-i18n</a></li> 1446<li>SolidStart: <a href="https://inlang.com/m/n860p17j/paraglide-solidstart-i18n">https://inlang.com/m/n860p17j/paraglide-solidstart-i18n</a></li> 1447<li>Vite: <a href="https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-vite">https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-vite</a></li> 1448</ul> 1449</li> 1450</ul> 1451<h2 id="1110"><a href="#1110">1.11.0</a></h2> 1452<h3 id="minor-changes-26"><a href="#minor-changes-26">Minor Changes</a></h3> 1453<ul> 1454<li>e37eabf: - renamed packages <code>@inlang/cross-sell-X</code> to <code>@inlang/recommend-X</code> be more descriptive 1455<ul> 1456<li>refactor recommendation view in Sherlock VS Code extension</li> 1457<li>introduce new <code>shouldRecommend</code> function to <code>@inlang/recommend-sherlock</code> & <code>@inlang/recommend-ninja</code></li> 1458</ul> 1459</li> 1460</ul> 1461<h2 id="1101"><a href="#1101">1.10.1</a></h2> 1462<h3 id="patch-changes-52"><a href="#patch-changes-52">Patch Changes</a></h3> 1463<ul> 1464<li>c5d145d: use types from SDK for error handling</li> 1465</ul> 1466<h2 id="1100"><a href="#1100">1.10.0</a></h2> 1467<h3 id="minor-changes-27"><a href="#minor-changes-27">Minor Changes</a></h3> 1468<ul> 1469<li>33662e6: Gracefully handle errors in the Inlang Project. Only crash on errors that are fatal to paraglide specifically</li> 1470</ul> 1471<h2 id="191"><a href="#191">1.9.1</a></h2> 1472<h3 id="patch-changes-53">
1472<a href="#patch-changes-53">Patch Changes</a></h3> 1473<ul> 1474<li>b8573fa: Improved error-reporting</li> 1475</ul> 1476<h2 id="190"><a href="#190">1.9.0</a></h2> 1477<h3 id="minor-changes-28"><a href="#minor-changes-28">Minor Changes</a></h3> 1478<ul> 1479<li>eb941fe: Prompt about adding the <a href="https://inlang.com/m/3gk8n4n4/app-inlang-ninjaI18nAction">Ninja</a> Github Action for translation-linting during <code>paraglide-js init</code>. Also exposes it over the internal API.</li> 1480</ul> 1481<h3 id="patch-changes-54"><a href="#patch-changes-54">Patch Changes</a></h3> 1482<ul> 1483<li>9566348: Better handling of <code>tsconfig</code> files that <code>extends</code> another config.</li> 1484</ul> 1485<h2 id="180"><a href="#180">1.8.0</a></h2> 1486<h3 id="minor-changes-29"><a href="#minor-changes-29">Minor Changes</a></h3> 1487<ul> 1488<li>21ab0a0: Add an output mode where each message is it's own file. This enables treeshaking in less capable bundlers. Currently this is only available via the programmatic API.</li> 1489</ul> 1490<h3 id="patch-changes-55"><a href="#patch-changes-55">Patch Changes</a></h3> 1491<ul> 1492<li>21ab0a0: performance improvements</li> 1493</ul> 1494<h2 id="173"><a href="#173">1.7.3</a></h2> 1495<h3 id="patch-changes-56"><a href="#patch-changes-56">Patch Changes</a></h3> 1496<ul> 1497<li>32cbe48: Improve <code>bestMatch</code> reliability</li> 1498</ul> 1499<h2 id="172"><a href="#172">1.7.2</a></h2> 1500<h3 id="patch-changes-57"><a href="#patch-changes-57">Patch Changes</a></h3> 1501<ul> 1502<li>6105a50: No longer log "Exiting the Watcher" when stopping the watching process, as it was causing annoying CMD popups on windows</li> 1503</ul> 1504<h2 id="171"><a href="#171">1.7.1</a></h2> 1505<h3 id="patch-changes-58"><a href="#patch-changes-58">Patch Changes</a></h3> 1506<ul> 1507<li>4d24188: <code>paraglide-js init</code> now uses the <code>createNewProject</code> API from <code>@inlang/sdk</code> for creating new projects. This resulits in higher reliability.</li> 1508</ul> 1509<h2 id="170"><a href="#170">1.7.0</a></h2> 1510<h3 id="minor-changes-30"><a href="#minor-changes-30">Minor Changes</a></h3> 1511<ul> 1512<li>0774c1a: Expose CLI programmatically to enable framework-specific init clis</li> 1513</ul> 1514<h2 id="162"><a href="#162">1.6.2</a></h2> 1515<h3 id="patch-changes-59"><a href="#patch-changes-59">Patch Changes</a></h3> 1516<ul> 1517<li>cee4692: Use index accesses instead of <code>.at</code> function for better compatability with legacy browsers</li> 1518<li>4b631aa: Update invalid type-declarations</li> 1519<li>3c7a87c: Fixes a race-condition when creating the messages directory during <code>paraglide-js init</code></li> 1520<li>ab1fe48: When initialising and a single project is available, it no longer suggests and empty string as the project path</li> 1521</ul> 1522<h2 id="161"><a href="#161">1.6.1</a></h2> 1523<h3 id="patch-changes-60"><a href="#patch-changes-60">Patch Changes</a></h3> 1524<ul> 1525<li>fa6aa31: Update internal adapter-utilities</li> 1526<li>dee5aa6: Add <code>--silent</code> option to <code>paraglide-js compile</code> command that will only log errors</li> 1527</ul> 1528<h2 id="160"><a href="#160">1.6.0</a></h2> 1529<h3 id="minor-changes-31"><a href="#minor-changes-31">Minor Changes</a></h3> 1530<ul> 1531<li>462325b: Paraglide now ships with internal utility functions that handle common adapter tasks such as language-negotiation. These aren't public facing, but the version bump is required to make sure adapter-packages resolve the correct version of paragldie.</li> 1532</ul> 1533<h2 id="150"><a href="#150">1.5.0</a></h2> 1534<h3 id="minor-changes-32"><a href="#minor-changes-32">Minor Changes</a></h3> 1535<ul> 1536<li>2428451: <code>paraglide-js init</code> now finds more existing projects</li> 1537</ul> 1538<h2 id="140"><a href="#140">1.4.0</a></h2> 1539<h3 id="minor-changes-33"><a href="#minor-changes-33">Minor Changes</a></h3> 1540<ul> 1541<li>d47b2aa: Generate empty <code>messages/{lang}.js</code> files if no messages are present. This way the "shape" of the generated output is always the same regardless of messages</li> 1542</ul> 1543<h3 id="patch-changes-61"><a href="#patch-changes-61">Patch Changes</a></h3> 1544<ul> 1545<li>192fdec: prompt the user for the <code>outdir</code> during <code>paraglide-js init</code></li> 1546<li>0b7c82e: Inline package-version at build time to be more robust</li> 1547</ul> 1548<h2 id="137"><a href="#137">1.3.7</a></h2>
1549<h3 id="patch-changes-62"><a href="#patch-changes-62">Patch Changes</a></h3> 1550<ul> 1551<li>1cc9cbc: Run compiler after <code>paraglide-js init</code> so that initial files are present</li> 1552<li>5401f95: Add <code>--outdir</code> flag to the generated CLI commands</li> 1553</ul> 1554<h2 id="136"><a href="#136">1.3.6</a></h2> 1555<h3 id="patch-changes-63"><a href="#patch-changes-63">Patch Changes</a></h3> 1556<ul> 1557<li>526b0ba: <code>paraglide-js init</code> now prompts for which languages should be supported</li> 1558<li>26d2ba1: No longer add <code>identical-pattern</code> lint rule by default</li> 1559</ul> 1560<h2 id="135"><a href="#135">1.3.5</a></h2> 1561<h3 id="patch-changes-64"><a href="#patch-changes-64">Patch Changes</a></h3> 1562<ul> 1563<li>7dce581: fix <code>openRepository</code> crash in non-git environments</li> 1564</ul> 1565<h2 id="134"><a href="#134">1.3.4</a></h2> 1566<h3 id="patch-changes-65"><a href="#patch-changes-65">Patch Changes</a></h3> 1567<ul> 1568<li>2a42b6e: bump <code>@lix-js/client</code> dependency</li> 1569</ul> 1570<h2 id="133"><a href="#133">1.3.3</a></h2> 1571<h3 id="patch-changes-66"><a href="#patch-changes-66">Patch Changes</a></h3> 1572<ul> 1573<li>11f0e18: Update dependency</li> 1574<li>10e3c28: fix JSDoc annotations on message aliases</li> 1575</ul> 1576<h2 id="132"><a href="#132">1.3.2</a></h2> 1577<h3 id="patch-changes-67"><a href="#patch-changes-67">Patch Changes</a></h3> 1578<ul> 1579<li>45975c0: Fail gracefully if adding <code>.vscode</code> folder fails</li> 1580</ul> 1581<h2 id="131"><a href="#131">1.3.1</a></h2> 1582<h3 id="patch-changes-68"><a href="#patch-changes-68">Patch Changes</a></h3> 1583<ul> 1584<li>afaaffa: Bundle <code>@inlang/recommend-sherlock</code>. This is used to promot <em>once</em> during <code>paraglide-js init</code> to ask if you want to install the Sherlock vscode extension</li> 1585</ul> 1586<h2 id="130"><a href="#130">1.3.0</a></h2> 1587<h3 id="minor-changes-34"><a href="#minor-changes-34">Minor Changes</a></h3> 1588<ul> 1589<li>4970afc: paraglide deprecate aliases</li> 1590<li>4837297: File locking for concurrent message updates through the load/store plugin api 1591Auto-generated human-IDs and aliases - only with experimental: { aliases: true }</li> 1592</ul> 1593<h3 id="patch-changes-69"><a href="#patch-changes-69">Patch Changes</a></h3> 1594<ul> 1595<li>@inlang/[email protected]</li> 1596</ul> 1597<h2 id="129"><a href="#129">1.2.9</a></h2> 1598<h3 id="patch-changes-70"><a href="#patch-changes-70">Patch Changes</a></h3> 1599<ul> 1600<li>a99e35fee: use <code>@inlang/recommend-sherlock</code> during vscode extension initialization</li> 1601<li>Updated dependencies [a99e35fee] 1602<ul> 1603<li>@inlang/[email protected]</li> 1604</ul> 1605</li> 1606</ul> 1607<h2 id="128"><a href="#128">1.2.8</a></h2> 1608<h3 id="patch-changes-71"><a href="#patch-changes-71">Patch Changes</a></h3> 1609<ul> 1610<li>b0f1e908b: Prompt user for tech-stack when running <code>paraglide-js init</code> & recommend Adapters</li> 1611</ul> 1612<h2 id="127"><a href="#127">1.2.7</a></h2> 1613<h3 id="patch-changes-72"><a href="#patch-changes-72">Patch Changes</a></h3> 1614<ul> 1615<li>f6ec6cdc9: bump <code>@inlang/sdk</code> dependency</li> 1616</ul> 1617<h2 id="126"><a href="#126">1.2.6</a></h2> 1618<h3 id="patch-changes-73"><a href="#patch-changes-73">Patch Changes</a></h3> 1619<ul> 1620<li>960f8fb70: rename the vscode extension to "Sherlock"</li> 1621</ul> 1622<h2 id="125"><a href="#125">1.2.5</a></h2> 1623<h3 id="patch-changes-74"><a href="#patch-changes-74">Patch Changes</a></h3> 1624<ul> 1625<li>00f181ad3: fix broken dependency</li> 1626</ul> 1627<h2 id="124"><a href="#124">1.2.4</a></h2> 1628<h3 id="patch-changes-75"><a href="#patch-changes-75">Patch Changes</a></h3> 1629<ul> 1630<li>Updated dependencies [244442698] 1631<ul> 1632<li>@inlang/[email protected]</li> 1633</ul> 1634</li> 1635</ul> 1636<h2 id="123"><a href="#123">1.2.3</a></h2> 1637<h3 id="patch-changes-76"><a href="#patch-changes-76">Patch Changes</a></h3> 1638<ul> 1639<li>4c26fa70a: bump dependencies</li> 1640</ul> 1641<h2 id="122"><a href="#122">1.2.2</a></h2> 1642<h3 id="patch-changes-77"><a href="#patch-changes-77">Patch Changes</a></h3> 1643<ul> 1644<li>613ef9877: fix: Bump <code>@lix-js/client</code> dependency</li> 1645</ul> 1646<h2 id="121"><a href="#121">1.2.1</a></h2> 1647<h3 id="patch-changes-78"><a href="#patch-changes-78">Patch Changes</a></h3> 1648<ul> 1649<li>74dc1f8c6: Update dependencies</li> 1650<li>4ae6295d0: Detect when <code>paraglide-js init</code> is being run inside the VsCode terminal and skip the VsCode question if so</li> 1651<li>Updated dependencies [74ac11c47] 1652<ul> 1653<li>@inlang/[email protected]</li> 1654</ul> 1655</li> 1656</ul> 1657<h2 id="120"><a href="#120">1.2.0</a></h2> 1658<h3 id="minor-changes-35"><a href="#minor-changes-35">Minor Changes</a></h3> 1659<ul> 1660<li>0f0e8496d: Throw runtime error if <code>
1660languageTag()</code> returns a non-language tag value</li> 1661</ul> 1662<h2 id="111"><a href="#111">1.1.1</a></h2> 1663<h3 id="patch-changes-79"><a href="#patch-changes-79">Patch Changes</a></h3> 1664<ul> 1665<li>7ea9753fb: Improve onboarding message</li> 1666<li>4277232db: fix: better formatting of messageID fallbacks</li> 1667</ul> 1668<h2 id="110"><a href="#110">1.1.0</a></h2> 1669<h3 id="minor-changes-36"><a href="#minor-changes-36">Minor Changes</a></h3> 1670<ul> 1671<li>cd29edb11: bumbing fixed env var dependecy issue affected packages</li> 1672</ul> 1673<h2 id="100"><a href="#100">1.0.0</a></h2> 1674<p>Bump Version to 1.0 as no more breaking changes are expected.</p> 1675<h2 id="100-prerelease26"><a href="#100-prerelease26">1.0.0-prerelease.26</a></h2> 1676<p>Hotfix: Bundle SDK</p> 1677<h2 id="100-prerelease25"><a href="#100-prerelease25">1.0.0-prerelease.25</a></h2> 1678<p>Update dependencies</p> 1679<h2 id="100-prerelease24"><a href="#100-prerelease24">1.0.0-prerelease.24</a></h2> 1680<p>feat: Support language Fallbacks according to BCP 47 specification</p> 1681<h2 id="100-prerelease23"><a href="#100-prerelease23">1.0.0-prerelease.23</a></h2> 1682<p>Update dependencies</p> 1683<h2 id="100-prerelease22"><a href="#100-prerelease22">1.0.0-prerelease.22</a></h2> 1684<p>Update dependencies</p> 1685<h2 id="100-prerelease21"><a href="#100-prerelease21">1.0.0-prerelease.21</a></h2> 1686<p>feat: Handle variables that have invalid JS identifiers as names. 1687fix: Better text escaping in the compiler. 1688fix: Compiler now fails reliably when a message ID is an invalid JS identifier.</p> 1689<h2 id="100-prerelease20"><a href="#100-prerelease20">1.0.0-prerelease.20</a></h2> 1690<p>Paraglide now checks if the messages have actually changed before recompiling. This should improve reliability and performance.</p> 1691<h2 id="100-prerelease19"><a href="#100-prerelease19">1.0.0-prerelease.19</a></h2> 1692<p>fix: Fix inlang/internal#195</p> 1693<h2 id="100-prerelease18"><a href="#100-prerelease18">1.0.0-prerelease.18</a></h2> 1694<p><code>paraglide-js init</code> now adds <code>@inlang/message-lint-rule-valid-js-identifier</code> by default.</p> 1695<h2 id="100-prerelease17"><a href="#100-prerelease17">1.0.0-prerelease.17</a></h2> 1696<p><code>paraglide-js init</code> now adds <code>paraglide-js compile</code> to the postinstall script by default. This sidesteps numerous linting issues when using paraglide in CI environments.</p> 1697<h2 id="100-prerelease16"><a href="#100-prerelease16">1.0.0-prerelease.16</a></h2> 1698<p>Fix <code>paraglide-js compile</code> hanging for a couple seconds after successful compilation</p> 1699<h2 id="100-prerelease15"><a href="#100-prerelease15">1.0.0-prerelease.15</a></h2> 1700<p>Fix crash when using <code>npx @inlang/paraglide-js init</code> and selecting vscode.</p> 1701<h2 id="100-prerelease14"><a href="#100-prerelease14">1.0.0-prerelease.14</a></h2> 1702<p>Added <code>--watch</code> flag to the <code>paraglide-js compile</code> command. This will keep the process alive and recompile whenever messages are changed.</p> 1703<pre data-mwc-codeblock=""><code class="hljs language-bash">paraglide-js compile --project ./project.inlang --watch 1704</code></pre> 1705<h2 id="100-prerelease13"><a href="#100-prerelease13">1.0.0-prerelease.13</a></h2> 1706<p><code>./paraglide/runtime.js</code> now exports a function called <code>isAvailableLanguageTag</code>. This is 1707the recommended way to check if something is a valid language tag, while maintaining 1708type safety.</p> 1709<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-comment">//Pseudo code</span> 1710<span class="hljs-keyword">import</span> { isAvailableLanguageTag } <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/runtime"</span>; 1711 1712<span class="hljs-keyword">if</span> (<span class="hljs-title function_">isAvailableLanguageTag</span>(params.<span class="hljs-property">lang</span>)) { 1713 <span class="hljs-keyword">return</span> <span class="hljs-title function_">renderSite</span>(params.<span class="hljs-property">lang</span>); 1714} <span class="hljs-keyword">else</span> { 1715 <span class="hljs-keyword">return</span> <span class="hljs-number">404</span>; 1716} 1717</code></pre> 1718<h2 id="100-prerelease12"><a href="#100-prerelease12">1.0.0-prerelease.12</a></h2> 1719<p>[Internal Change] 1720Expose the compiler so that bundler plugins can call it programmatically instead of going through the CLI.</p> 1721<h2 id="100-prerelease11"><a href="#100-prerelease11">1.0.0-prerelease.11</a></h2> 1722<p><code>onSetLanguageTag</code> no longer throws when called multiple times. Newer callbacks will over
1722write old ones. 1723Developers still should not call <code>onSetLanguageTag</code> multiple times, this is needed for HMR to work reliably.</p> 1724<p>Big thanks to <a href="https://github.com/KraXen72">@KraXen72</a> for helping us find this bug.</p> 1725<h2 id="100-prerelease10"><a href="#100-prerelease10">1.0.0-prerelease.10</a></h2> 1726<p>Add an optional options argument to message functions, to allow forcing a languageTag regardless of which languageTag is currently set.</p> 1727<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> m <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/messages"</span>; 1728<span class="hljs-keyword">const</span> msg = m.<span class="hljs-title function_">hello</span>({ <span class="hljs-attr">name</span>: <span class="hljs-string">"John"</span> }, { <span class="hljs-attr">languageTag</span>: <span class="hljs-string">"de"</span> }); 1729</code></pre> 1730<h2 id="100-prerelease9"><a href="#100-prerelease9">1.0.0-prerelease.9</a></h2> 1731<p>The <code>paraglide-js init</code> command now uses the <a href="https://inlang.com/m/reootnfj">inlang message format</a> 2.0 which is human readable.</p> 1732<h2 id="100-prerelease8"><a href="#100-prerelease8">1.0.0-prerelease.8</a></h2> 1733<p>IMPROVE: Paraglide now splits messages into different resource files as a step towards splitting messages by language via a bundler plugin.</p> 1734<pre data-mwc-codeblock=""><code class="hljs language-ts"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> en <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/messages/en"</span>; 1735<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> de <span class="hljs-keyword">from</span> <span class="hljs-string">"./paraglide/messages/de"</span>; 1736 1737en.<span class="hljs-title function_">hello</span>(); 1738de.<span class="hljs-title function_">hello</span>(); 1739</code></pre> 1740<h2 id="100-prerelease7"><a href="#100-prerelease7">1.0.0-prerelease.7</a></h2> 1741<p>FIX: type error <a href="https://github.com/opral/monorepo/pull/1610#issuecomment-1801768825">https://github.com/opral/monorepo/pull/1610#issuecomment-1801768825</a></p> 1742<pre data-mwc-codeblock=""><code class="hljs language-diff">export const currentLanguageTag = (params) => { 1743<span class="hljs-addition">+ /** @type {Record<string, string>} */</span> 1744 const variants = { 1745 en: `The current language tag is "${params.languageTag}".`, 1746 de: `Der aktuelle Sprachtag ist "${params.languageTag}".`, 1747 } 1748 return variants[languageTag()] ?? "currentLanguageTag" 1749} 1750</code></pre> 1751<h2 id="100-prerelease6"><a href="#100-prerelease6">1.0.0-prerelease.6</a></h2> 1752<p>BREAKING: Paraglide JS now compiles into source code, see <a href="https://github.com/opral/monorepo/issues/1607">https://github.com/opral/monorepo/issues/1607</a>.</p> 1753<p>What you need to change:</p> 1754<ol> 1755<li>Remove <code>--namespace</code> from the compile command</li> 1756<li>Replace imports from paraglide to point to the directory in ther source code:</li> 1757</ol> 1758<pre data-mwc-codeblock=""><code class="hljs language-diff"><span class="hljs-deletion">-import { setLanguageTag, languageTag } from '@inlang/paraglide-js/sveltekit-example';</span> 1759<span class="hljs-addition">+import { setLanguageTag, languageTag } from '../../paraglide-js/runtime';</span> 1760<span class="hljs-deletion">-import * as m from "@inlang/paraglide-js/sveltekit-example/messages"</span> 1761<span class="hljs-addition">+import * as m from "../../paraglide-js/messages"</span> 1762</code></pre> 1763<h2 id="100-prerelease5"><a href="#100-prerelease5">1.0.0-prerelease.5</a></h2> 1764<p>improve: <code>paraglide-js init</code> now adds the Visual Studio Code extension (Sherlock) if vscode is used</p> 1765<h2 id="100-prerelease4"><a href="#100-prerelease4">1.0.0-prerelease.4</a></h2> 1766<p>add: <code>paraglide-js init</code> command which simplifies the setup process</p> 1767<h2 id="100-prerelease3"><a href="#100-prerelease3">1.0.0-prerelease.3</a></h2> 1768<p>fix: <a href="https://github.com/opral/monorepo/issues/1478">https://github.com/opral/monorepo/issues/1478</a></p> 1769<h2 id="100-prerelease1"><a href="#100-prerelease1">1.0.0-prerelease.1</a></h2> 1770<h3 id="fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports"><a href="#fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports">fix: Jetbrains based editors not detecting <code>@inlang/paraglide-js/{namespace}/messages</code> imports</a></h3> 1771<p>The bug has been fixed by moving <code>./*/messages</code> above the less specifc <code>./*</code> export.</p> 1772<pre data-mwc-codeblock=""><code class="hljs language-json"> <span class="hljs-attr">"exports"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> 1773 <span class="hljs-attr">"./*/messages"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"./dist/compiled-output/*/messages.js"</span><span class="hljs-punctuation">,</span> 1774 <span class="hljs-attr">"./*"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"./dist/compiled-output/*/runtime.js"</span> 1775 <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> 1776</code></pre></div><div class="mt-12"><a href="https://github.com/opral/paraglide-js/blob/main/CHANGELOG.md" target="_blank" rel="noreferrer" class="inline-flex items-center gap-2 text-sm text-slate-500 hover:text-slate-700"><svg aria-hidden="true" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-5m-1.414-9.414a2 2 0 1 1 2.828 2.828L11.828 15H9v-2.828l8.586-8.586Z"></path></svg>Edit this page on GitHub</a></div><div class="mt-12 grid gap-4 border-t border-slate-200 pt-8 sm:grid-cols-2"><a href="/benchmark" class="rounded-lg border border-slate-200 p-4 text-left transition-colors hover:border-slate-300 hover:bg-slate-50"><p class="text-xs font-medium uppercase tracking-wide text-slate-600">Previous</p><p class="mt-1 font-medium text-slate-900">Benchmark</p></a><a href="/sveltekit" class="rounded-lg border border-slate-200 p-4 text-left transition-colors hover:border-slate-300 hover:bg-slate-50 sm:text-right"><p class="text-xs font-medium uppercase tracking-wide text-slate-600">Next</p><p class="mt-1 font-medium text-slate-900">SvelteKit</p></a></div></section><aside class="sticky top-16 hidden h-[calc(100vh-4rem)] w-56 shrink-0 xl:block"><div class="h-full overflow-y-auto pb-8 pl-2 pt-5"><nav aria-label="On this page" class="text-sm text-slate-700"><p class="pb-2 text-xs font-semibold uppercase tracking-wide text-slate-600">On this page</p><div class="flex flex-col"><a href="#inlangparaglide-js" class="border-l-2 py-1 text-left text-sm transition-colors pl-3 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">@inlang/paraglide-js</a><a href="#2254" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.25.4</a>
1776<a href="#patch-changes" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2253" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.25.3</a><a href="#patch-changes-2" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2252" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.25.2</a><a href="#patch-changes-3" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2251" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.25.1</a><a href="#patch-changes-4" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2250" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.25.0</a><a href="#minor-changes" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-5" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2241" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.24.1</a><a href="#patch-changes-6" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2240" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.24.0</a><a href="#minor-changes-2" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-7" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2232" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.23.2</a><a href="#patch-changes-8" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2231" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.23.1</a><a href="#patch-changes-9" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2230" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.23.0</a><a href="#minor-changes-3" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-10" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2220" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.22.0</a><a href="#minor-changes-4" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2210" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.21.0</a><a href="#minor-changes-5" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2202" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.20.2</a>
1776<a href="#patch-changes-11" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2201" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.20.1</a><a href="#patch-changes-12" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2200" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.20.0</a><a href="#minor-changes-6" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-13" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2190" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.19.0</a><a href="#minor-changes-7" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-14" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2182" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.18.2</a><a href="#patch-changes-15" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2181" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.18.1</a><a href="#patch-changes-16" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2180" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.18.0</a><a href="#minor-changes-8" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-17" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2170" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.17.0</a><a href="#minor-changes-9" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2161" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.16.1</a><a href="#patch-changes-18" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2160" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.16.0</a><a href="#minor-changes-10" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2153" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.15.3</a>
1776<a href="#patch-changes-19" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2152" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.15.2</a><a href="#patch-changes-20" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2151" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.15.1</a><a href="#patch-changes-21" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2150" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.15.0</a><a href="#minor-changes-11" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2141" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.14.1</a><a href="#patch-changes-22" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2140" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.14.0</a><a href="#minor-changes-12" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-23" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2132" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.13.2</a><a href="#patch-changes-24" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2131" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.13.1</a><a href="#patch-changes-25" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2130" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.13.0</a><a href="#minor-changes-13" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2120" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.12.0</a><a href="#minor-changes-14" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2110" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.11.0</a><a href="#minor-changes-15" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#2100" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.10.0</a><a href="#minor-changes-16" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#291" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.9.1</a>
1776<a href="#patch-changes-26" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#290" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.9.0</a><a href="#minor-changes-17" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-27" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#280" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.8.0</a><a href="#minor-changes-18" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-28" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#272" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.7.2</a><a href="#patch-changes-29" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#271" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.7.1</a><a href="#patch-changes-30" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#270" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.7.0</a><a href="#minor-changes-19" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#260" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.6.0</a><a href="#minor-changes-20" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#250" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.5.0</a><a href="#240" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.4.0</a><a href="#minor-changes-21" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-31" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#232" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.3.2</a><a href="#patch-changes-32" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#231" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.3.1</a><a href="#patch-changes-33" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#230" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.3.0</a><a href="#minor-changes-22" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#220" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.2.0</a><a href="#minor-changes-23" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#whats-changed" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">What's Changed</a><a href="#migration-guide" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">
1776Migration Guide</a><a href="#for-users-with-custom-server-strategies" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">For users with custom server strategies:</a><a href="#for-users-calling-extractlocalefromrequest-directly" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">For users calling extractLocaleFromRequest directly:</a><a href="#patch-changes-34" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#210" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.1.0</a><a href="#minor-changes-24" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-35" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2013" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.13</a><a href="#patch-changes-36" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2012" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.12</a><a href="#patch-changes-37" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2011" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.11</a><a href="#patch-changes-38" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#2010" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.10</a><a href="#patch-changes-39" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#209" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.9</a><a href="#patch-changes-40" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#208" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.8</a><a href="#patch-changes-41" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#207" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.7</a><a href="#patch-changes-42" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#206" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.6</a><a href="#patch-changes-43" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#205" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.5</a>
1776<a href="#patch-changes-44" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#204" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.4</a><a href="#patch-changes-45" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#203" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.3</a><a href="#patch-changes-46" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#202" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.2</a><a href="#patch-changes-47" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#201" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.1</a><a href="#patch-changes-48" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#paraglide-js-20-ð" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Paraglide JS 2.0 ð</a><a href="#highlights" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Highlights</a><a href="#migrating-breaking-changes" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Migrating breaking changes</a><a href="#200-beta31-released-as-200" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.31 (released as 2.0.0)</a><a href="#200-beta30" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.30</a><a href="#200-beta29" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.29</a><a href="#200-beta28" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.28</a><a href="#breaking-update-to-the-urlpattern-api" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">BREAKING update to the URLPattern API</a><a href="#other-changes" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">other changes</a><a href="#200-beta27" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.27</a><a href="#200-beta26" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.26</a><a href="#200-beta25" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.25</a><a href="#200-beta24" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.24</a><a href="#200-beta23" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.23</a><a href="#200-beta22" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.22</a><a href="#200-beta21" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.21</a><a href="#200-beta20" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.20</a><a href="#200-beta19" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">
17762.0.0-beta.19</a><a href="#200-beta18" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.18</a><a href="#200-beta17" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.17</a><a href="#200-beta16" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.16</a><a href="#200-beta14" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.14</a><a href="#200-beta13" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.13</a><a href="#200-beta11" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.11</a><a href="#200-beta10" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.10</a><a href="#200-beta9" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.9</a><a href="#200-beta8" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.8</a><a href="#200-beta7" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.7</a><a href="#200-beta3" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0-beta.3</a><a href="#patch-changes-49" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#200" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">2.0.0</a><a href="#major-changes" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Major changes</a><a href="#minor-changes-25" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#1112" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.11.2</a><a href="#patch-changes-50" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#1111" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.11.1</a><a href="#patch-changes-51" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#1110" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.11.0</a><a href="#minor-changes-26" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#1101" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.10.1</a><a href="#patch-changes-52" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#1100" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.10.0</a><a href="#minor-changes-27" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#191" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.9.1</a>
1776<a href="#patch-changes-53" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#190" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.9.0</a><a href="#minor-changes-28" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-54" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#180" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.8.0</a><a href="#minor-changes-29" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-55" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#173" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.7.3</a><a href="#patch-changes-56" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#172" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.7.2</a><a href="#patch-changes-57" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#171" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.7.1</a><a href="#patch-changes-58" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#170" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.7.0</a><a href="#minor-changes-30" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#162" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.6.2</a><a href="#patch-changes-59" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#161" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.6.1</a><a href="#patch-changes-60" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#160" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.6.0</a><a href="#minor-changes-31" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#150" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.5.0</a><a href="#minor-changes-32" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#140" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.4.0</a><a href="#minor-changes-33" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a>
1776<a href="#patch-changes-61" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#137" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.7</a><a href="#patch-changes-62" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#136" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.6</a><a href="#patch-changes-63" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#135" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.5</a><a href="#patch-changes-64" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#134" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.4</a><a href="#patch-changes-65" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#133" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.3</a><a href="#patch-changes-66" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#132" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.2</a><a href="#patch-changes-67" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#131" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.1</a><a href="#patch-changes-68" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#130" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.3.0</a><a href="#minor-changes-34" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#patch-changes-69" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#129" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.9</a><a href="#patch-changes-70" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#128" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.8</a><a href="#patch-changes-71" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#127" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.7</a>
1776<a href="#patch-changes-72" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#126" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.6</a><a href="#patch-changes-73" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#125" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.5</a><a href="#patch-changes-74" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#124" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.4</a><a href="#patch-changes-75" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#123" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.3</a><a href="#patch-changes-76" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#122" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.2</a><a href="#patch-changes-77" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#121" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.1</a><a href="#patch-changes-78" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#120" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.2.0</a><a href="#minor-changes-35" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#111" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.1.1</a><a href="#patch-changes-79" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Patch Changes</a><a href="#110" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.1.0</a><a href="#minor-changes-36" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">Minor Changes</a><a href="#100" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0</a><a href="#100-prerelease26" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.26</a><a href="#100-prerelease25" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.25</a><a href="#100-prerelease24" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.24</a><a href="#100-prerelease23" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.23</a><a href="#100-prerelease22" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.22</a><a href="#100-prerelease21" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.21</a><a href="#100-prerelease20" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.20</a><a href="#100-prerelease19" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.19</a><a href="#100-prerelease18" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.18</a><a href="#100-prerelease17" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.17</a><a href="#100-prerelease16" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.16</a><a href="#100-prerelease15" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.15</a><a href="#100-prerelease14" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.14</a><a href="#100-prerelease13" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.13</a><a href="#100-prerelease12" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.12</a><a href="#100-prerelease11" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.11</a><a href="#100-prerelease10" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.10</a><a href="#100-prerelease9" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.9</a><a href="#100-prerelease8" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.8</a><a href="#100-prerelease7" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.7</a><a href="#100-prerelease6" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.6</a><a href="#100-prerelease5" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.5</a><a href="#100-prerelease4" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.4</a><a href="#100-prerelease3" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.3</a><a href="#100-prerelease1" class="border-l-2 py-1 text-left text-sm transition-colors pl-4 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">1.0.0-prerelease.1</a><a href="#fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports" class="border-l-2 py-1 text-left text-sm transition-colors pl-6 border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-900">fix: Jetbrains based editors not detecting @inlang/paraglide-js/{namespace}/messages imports</a></div></nav></div></aside></div></div></div>
1776<script></script>
1776<script>(function restoreScroll({ 1777 storageKey: storageKey2, 1778 key, 1779 behavior, 1780 shouldScrollRestoration, 1781 scrollToTopSelectors, 1782 location 1783}) { 1784 let byKey; 1785 try { 1786 byKey = JSON.parse(sessionStorage.getItem(storageKey2) || "{}"); 1787 } catch (error) { 1788 console.error(error); 1789 return; 1790 } 1791 const resolvedKey = key || window.history.state?.__TSR_key; 1792 const elementEntries = byKey[resolvedKey]; 1793 ignoreScroll = true; 1794 scroll: { 1795 if (shouldScrollRestoration && elementEntries && Object.keys(elementEntries).length > 0) { 1796 for (const elementSelector in elementEntries) { 1797 const entry = elementEntries[elementSelector]; 1798 if (elementSelector === "window") { 1799 window.scrollTo({ 1800 top: entry.scrollY, 1801 left: entry.scrollX, 1802 behavior 1803 }); 1804 } else if (elementSelector) { 1805 const element = document.querySelector(elementSelector); 1806 if (element) { 1807 element.scrollLeft = entry.scrollX; 1808 element.scrollTop = entry.scrollY; 1809 } 1810 } 1811 } 1812 break scroll; 1813 } 1814 const hash = (location ?? window.location).hash.split("#", 2)[1]; 1815 if (hash) { 1816 const hashScrollIntoViewOptions = window.history.state?.__hashScrollIntoViewOptions ?? true; 1817 if (hashScrollIntoViewOptions) { 1818 const el = document.getElementById(hash); 1819 if (el) { 1820 el.scrollIntoView(hashScrollIntoViewOptions); 1821 } 1822 } 1823 break scroll; 1824 } 1825 const scrollOptions = { top: 0, left: 0, behavior }; 1826 window.scrollTo(scrollOptions); 1827 if (scrollToTopSelectors) { 1828 for (const selector of scrollToTopSelectors) { 1829 if (selector === "window") continue; 1830 const element = typeof selector === "function" ? selector() : document.querySelector(selector); 1831 if (element) element.scrollTo(scrollOptions); 1832 } 1833 } 1834 } 1835 ignoreScroll = false; 1836})({"storageKey":"tsr-scroll-restoration-v1_3","shouldScrollRestoration":true});document.currentScript.remove()</script>
1836<!--/$--></main><footer class="border-t border-slate-200 bg-slate-50"><div class="mx-auto flex max-w-7xl flex-col gap-4 px-6 py-10 text-sm text-slate-600 md:flex-row md:items-center md:justify-between"><p>Paraglide JS is MIT licensed and maintained by inlang.</p><div class="flex flex-wrap gap-4"><a href="https://github.com/opral/paraglide-js" target="_blank" rel="noreferrer" class="hover:text-slate-950">GitHub</a><a href="https://www.npmjs.com/package/@inlang/paraglide-js" target="_blank" rel="noreferrer" class="hover:text-slate-950">npm</a><a href="https://discord.gg/gdMPPWy57R" target="_blank" rel="noreferrer" class="hover:text-slate-950">Discord</a><a href="https://inlang.com" target="_blank" rel="noreferrer" class="hover:text-slate-950">inlang</a></div></div></footer>
1836<script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]}; 1837;$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["/assets/main-DR-gCXHy.js"],assets:$R[5]=[$R[6]={tag:"script",attrs:$R[7]={type:"module",async:!0},children:"import('/assets/main-DR-gCXHy.js')"}]},"/$":$R[8]={preloads:$R[9]=["/assets/_-CRSJLm-T.js","/assets/DocsPage-C2ewJmmV.js","/assets/markdown-interactive-e-Kzm-7q.js"]}}},matches:$R[10]=[$R[11]={i:"__root__/",u:1789610477685,s:"success",ssr:!0},$R[12]={i:"/$/changelog",u:1789610477917,s:"success",l:$R[13]={markdown:"\x3Ch1 id=\"inlangparaglide-js\">\x3Ca href=\"#inlangparaglide-js\">@inlang/paraglide-js\x3C/a>\x3C/h1>\n\x3Ch2 id=\"2254\">\x3Ca href=\"#2254\">2.25.4\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes\">\x3Ca href=\"#patch-changes\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>afe6fdc: Fix default URL routing dropping trailing slashes when localizing or delocalizing paths. When \x3Ccode>trailingSlash\x3C/code> is omitted, \x3Ccode>/about/\x3C/code> now becomes \x3Ccode>/en/about/\x3C/code> and \x3Ccode>/en/about/\x3C/code> delocalizes to \x3Ccode>/about/\x3C/code>, matching equivalent explicit URL patterns. Paths without trailing slashes and localized root behavior remain unchanged. Set \x3Ccode>trailingSlash: \"never\"\x3C/code> to explicitly generate slashless URLs; \x3Ccode>\"always\"\x3C/code> continues to enforce trailing slashes.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2253\">\x3Ca href=\"#2253\">2.25.3\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-2\">\x3Ca href=\"#patch-changes-2\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>e1e6e61: Upgrade the inlang SDK to 3.0.6 with Lix 0.17.0.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2252\">\x3Ca href=\"#2252\">2.25.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-3\">\x3Ca href=\"#patch-changes-3\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b26bada: Upgrade Inlang SDK to 3.0.5 with Lix 0.16.1 to fix compilation of sorted message files above 512 tracked-state rows. Includes transaction error handling and snapshot restoration fixes.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2251\">\x3Ca href=\"#2251\">2.25.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-4\">\x3Ca href=\"#patch-changes-4\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>845e819: Upgrade the Inlang SDK to 3.0.4, including Lix 0.15.1 fixes for transaction-local message and variant reads.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2250\">\x3Ca href=\"#2250\">2.25.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes\">\x3Ca href=\"#minor-changes\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>f719e1f: Expose \x3Ccode>cleanOutdir\x3C/code>, \x3Ccode>experimentalStaticLocale\x3C/code>, and \x3Ccode>disableAsyncLocalStorage\x3C/code> as \x3Ccode>paraglide-js compile\x3C/code> CLI flags.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>5ed1745: Add support for a \x3Ccode>paraglide.config.js\x3C/code> (or \x3Ccode>.mjs\x3C/code>, \x3Ccode>.ts\x3C/code>, \x3Ccode>.cjs\x3C/code>)\nconfiguration file inside the inlang project directory.\x3C/p>\n\x3Cp>The CLI and all bundler plugins now pick up compiler options from\n\x3Ccode><project>/paraglide.config.*\x3C/code>. The project directory comes from \x3Ccode>--project\x3C/code>\nor the plugin's \x3Ccode>project\x3C/code> option and defaults to the conventional\n\x3Ccode>./project.inlang\x3C/code> â which means every bundler plugin can now be\ninstantiated without arguments. Since the config lives inside the project it\nconfigures, it cannot set \x3Ccode>project\x3C/code> itself. Explicit flags and plugin\noptions win over the config file, which wins over the built-in defaults.\nExisting setups keep working unchanged.\x3C/p>\n\x3Cp>Also included:\x3C/p>\n\x3Cul>\n\x3Cli>A new \x3Ccode>defineConfig\x3C/code> helper exported from \x3Ccode>@inlang/paraglide-js\x3C/code> for type\ninference and autocompletion in config files.\x3C/li>\n\x3Cli>Watch modes reload when the active config file changes, including renames\nbetween the supported file names. Deleting all config files falls back to\nthe built-in defaults;
1837 an invalid config skips the compilation with an\nerror â watch modes keep serving the previous output, production builds\nfail loudly. (esbuild does not support config watching.)\x3C/li>\n\x3Cli>\x3Ccode>cleanOutdir\x3C/code> is accepted but ignored: watch integrations always preserve\nthe output directory for incremental compilation.\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-5\">\x3Ca href=\"#patch-changes-5\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>aa4ffd3: Resolve references to earlier local variables correctly in message declarations and formatter options.\x3C/li>\n\x3Cli>3634877: Fix \x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code> corrupting the generated server file when a compiled message value contains a literal \x3Ccode>$\x3C/code> (e.g. a price or currency symbol) that forms a \x3Ccode>String.replace()\x3C/code> special replacement pattern such as \x3Ccode>$`\x3C/code>.\x3C/li>\n\x3Cli>1bacc27: Fix \x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code> keying \x3Ccode>compiledBundles\x3C/code> by the raw bundle id instead of the safe module id, so every SSR message lookup missed and threw \x3Ccode>globalThis.__paraglide.ssr.<id> is not a function\x3C/code> on hydration.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2241\">\x3Ca href=\"#2241\">2.24.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-6\">\x3Ca href=\"#patch-changes-6\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>d2aeb93: Update the inlang SDK dependency to 3.0.1, which includes the Lix WASM fallback for musl-based Node.js environments.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2240\">\x3Ca href=\"#2240\">2.24.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-2\">\x3Ca href=\"#minor-changes-2\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>7028c8a: Upgrade to \x3Ccode>@inlang/sdk\x3C/code> v3 and remove obsolete local account migration code.\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-7\">\x3Ca href=\"#patch-changes-7\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>0ac907e: Cache compiled URL patterns to speed up repeated localized-link generation.\x3C/li>\n\x3Cli>fda90d2: Skip unchanged Vite compilations across dev-server restarts by persisting and validating the compiler input cache.\x3C/li>\n\x3Cli>84e2766: Add a fast path for common locale-prefix and static-domain URL patterns while preserving the generic URLPattern fallback.\x3C/li>\n\x3Cli>5de9441: Improve compiler output writes by using Node's synchronous SHA-256 implementation and only creating directories for generated files that changed.\x3C/li>\n\x3Cli>5c17acf: Allow importing the programmatic compiler API without installing the optional Vite peer dependency.\x3C/li>\n\x3Cli>c52b523: Preserve request bodies in \x3Ccode>paraglideMiddleware\x3C/code> by cloning body-bearing requests before rewrapping them, preventing \"Body has already been read\" errors on POST/PUT/PATCH/DELETE.\x3C/li>\n\x3Cli>32d285b: Avoid rewriting unchanged output files during one-shot CLI compilation.\x3C/li>\n\x3Cli>9e1ee2e: Add an opt-in \x3Ccode>trailingSlash\x3C/code> compiler option for canonicalizing localized URLs.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2232\">\x3Ca href=\"#2232\">2.23.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-8\">\x3Ca href=\"#patch-changes-8\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b8af4b1: Embed TypeScript sources in published JavaScript sourcemaps and stop emitting declaration sourcemaps that reference unpublished source files.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2231\">\x3Ca href=\"#2231\">2.23.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-9\">\x3Ca href=\"#patch-changes-9\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>6f9b062: Keep the server middleware's AsyncLocalStorage available when module instrumentation snapshots mutable exports.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2230\">\x3Ca href=\"#2230\">2.23.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-3\">\x3Ca href=\"#minor-changes-3\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>c2b9c17: Replace the experimental per-locale framework-output specialization with a\nVite 8+ environment architecture. \x3Ccode>experimentalPerLocaleBuild: true\x3C/code> now\ngenerates locale source modules before bundling, builds independent native\nRolldown graphs, supports unminified builds and source maps, and emits\n\x3Ccode>paraglide-vite-locales.json\x3C/code> without rewriting completed chunks or framework\noutput.\x3C/p>\n\x3Cp>Remove the private TanStack Start and SvelteKit renderer integrations. Those\nframeworks now require public client-variant build and render-selection APIs\nbefore they can compose with experimental per-locale builds.\x3C/p>\n\x3C/li>\n\x3C/ul>
1837\n\x3Ch3 id=\"patch-changes-10\">\x3Ca href=\"#patch-changes-10\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>608385f: Use \x3Ccode>baseLocale\x3C/code> as the exhaustive branch in generated message functions.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2220\">\x3Ca href=\"#2220\">2.22.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-4\">\x3Ca href=\"#minor-changes-4\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>2571af2: Add experimental Vite 8 per-locale client builds for TanStack Start and SvelteKit. Enable the same \x3Ccode>experimentalPerLocaleBuild: true\x3C/code> flag in either framework; Paraglide detects the framework and serves compiler-specialized client assets for each locale.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2210\">\x3Ca href=\"#2210\">2.21.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-5\">\x3Ca href=\"#minor-changes-5\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>ab5bfc7: fix \x3Ccode>emitTsDeclarations\x3C/code> with TypeScript 7 \x3Ca href=\"https://github.com/opral/paraglide-js/issues/711\">https://github.com/opral/paraglide-js/issues/711\x3C/a>\x3C/p>\n\x3Cp>TypeScript 7 (the Go-based compiler) no longer ships the in-process compiler API that Paraglide used to generate \x3Ccode>.d.ts\x3C/code> files, which made \x3Ccode>paraglide-js compile --emit-ts-declarations\x3C/code> fail with \x3Ccode>TypeError: Cannot read properties of undefined (reading 'ESNext')\x3C/code>. Paraglide now detects this and invokes TypeScript's \x3Ccode>tsc\x3C/code> CLI instead. TypeScript 5 and 6 keep using the compiler API as before.\x3C/p>\n\x3Cp>Note that the declaration output of TypeScript 7 differs cosmetically from TypeScript 5/6 (quote style, declaration ordering, \x3Ccode>export declare const\x3C/code> vs \x3Ccode>export const\x3C/code>) but is semantically equivalent.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2202\">\x3Ca href=\"#2202\">2.20.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-11\">\x3Ca href=\"#patch-changes-11\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>a48e767: Cache client cookie locale extraction for synchronous message bursts.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2201\">\x3Ca href=\"#2201\">2.20.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-12\">\x3Ca href=\"#patch-changes-12\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>8c3493d: Fix server cookie locale parsing when Cookie headers omit whitespace after semicolons.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2200\">\x3Ca href=\"#2200\">2.20.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-6\">\x3Ca href=\"#minor-changes-6\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>2c34351: Emit \x3Ccode>messages/package.json\x3C/code> with \x3Ccode>{ \"type\": \"module\", \"sideEffects\": false }\x3C/code> for \x3Ccode>message-modules\x3C/code> output, declaring the generated message modules side-effect-free.\x3C/p>\n\x3Cp>This lets bundlers (notably Vite 8 / Rolldown) drop unused re-exports from the \x3Ccode>m\x3C/code> 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.\x3C/p>\n\x3Cp>The declaration is scoped to \x3Ccode>messages/\x3C/code>, so \x3Ccode>runtime.js\x3C/code> (which has real side effects) is unaffected. \x3Ccode>type: \"module\"\x3C/code> is included because the package.json creates a new module scope for \x3Ccode>messages/\x3C/code>; without it, the generated ESM files would default to CommonJS (a package.json without \x3Ccode>type\x3C/code> is CJS in Node, even when the consuming project is \x3Ccode>type: \"module\"\x3C/code>).\x3C/p>\n\x3Cp>See \x3Ca href=\"https://github.com/opral/paraglide-js/issues/668\">https://github.com/opral/paraglide-js/issues/668\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-13\">\x3Ca href=\"#patch-changes-13\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>921c3be: \x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code>: the injected inline script now reuses the nonce from the response's \x3Ccode>Content-Security-Policy\x3C/code> header, so it is allowed under a strict CSP instead of being blocked and breaking hydration. Automatic - no configuration needed.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2190\">\x3Ca href=\"#2190\">2.19.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-7\">\x3Ca href=\"#minor-changes-7\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>67a8942: Compile pattern-level function-reference annotations to registry calls\x3C/p>\n\x3Cp>Annotations attached directly to pattern expressions (e.g. i18next's \x3Ccode>{{count, number}}\x3C/code> imported via plugin-i18next) were silently dropped and compiled to plain interpolation. They now compile through the same \x3Ccode>registry.*\x3C/code> path as local-variable annotations:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">
1837// before\x3C/span>\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-title function_\">en_views\x3C/span> = (\x3Cspan class=\"hljs-params\">i\x3C/span>) => \x3Cspan class=\"hljs-string\">`\x3Cspan class=\"hljs-subst\">${i?.count}\x3C/span> views`\x3C/span>;\n\x3Cspan class=\"hljs-comment\">// after\x3C/span>\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-title function_\">en_views\x3C/span> = (\x3Cspan class=\"hljs-params\">i\x3C/span>) => \x3Cspan class=\"hljs-string\">`\x3Cspan class=\"hljs-subst\">${registry.number(\x3Cspan class=\"hljs-string\">\"en\"\x3C/span>, i?.count, {})}\x3C/span> views`\x3C/span>;\n\x3C/code>\x3C/pre>\n\x3Cp>Unknown formatter names fall back to plain interpolation with a compile-time warning instead of failing or staying silent. \x3Ccode>compilePattern()\x3C/code> gained an optional \x3Ccode>locale\x3C/code> parameter, required to compile annotations.\x3C/p>\n\x3Cp>Fixes \x3Ca href=\"https://github.com/opral/paraglide-js/issues/694\">https://github.com/opral/paraglide-js/issues/694\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>
1837d57efa1: Skip recompilation when inputs are unchanged across bundler runs in the same process\x3C/p>\n\x3Cp>\x3Ccode>vite build\x3C/code> fires \x3Ccode>buildStart\x3C/code> once per environment (client, ssr, ...) and each run did a full \x3Ccode>compile()\x3C/code> â 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 \x3Ccode>compile()\x3C/code> entirely when the digest matches on the next run. The second and later environments become near-free:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode>vite v6.4.1 building for production...\nâ [paraglide-js] Compilation complete (locale-modules)\nâ built in 634ms\nvite v6.4.1 building SSR bundle for production...\nâ¹ [paraglide-js] Compilation skipped â inputs unchanged (locale-modules)\nâ built in 15ms\n\x3C/code>\x3C/pre>\n\x3Cp>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 \x3Ccode>beforeRun\x3C/code>.\x3C/p>\n\x3Cp>Also fixed along the way:\x3C/p>\n\x3Cul>\n\x3Cli>
1837A user-provided \x3Ccode>fs\x3C/code> 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.\x3C/li>\n\x3Cli>The watch-target filter ignored any path \x3Cem>containing\x3C/em> the substring \"cache\" â a project under e.g. \x3Ccode>/cachet-app/\x3C/code> had its inputs excluded from file watching. It now matches whole path segments only.\x3C/li>\n\x3C/ul>\n\x3Cp>Fixes \x3Ca href=\"https://github.com/opral/paraglide-js/issues/693\">https://github.com/opral/paraglide-js/issues/693\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-14\">\x3Ca href=\"#patch-changes-14\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>6010611: Update \x3Ccode>@inlang/sdk\x3C/code> to 2.10.0.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2182\">\x3Ca href=\"#2182\">2.18.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-15\">\x3Ca href=\"#patch-changes-15\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>4bea31a: Prevent \x3Ccode>paraglide-js compile --watch\x3C/code> from cleaning the output directory on the initial compile.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>4dfa099: Fix emitted TypeScript declarations for message keys that require quoted export aliases, such as dotted nested keys.\x3C/p>\n\x3Cp>\x3Ccode>emitTsDeclarations\x3C/code> now preserves quoted aliases from the generated JavaScript so \x3Ccode>.d.ts\x3C/code> output remains valid for keys like \x3Ccode>greeting.hello\x3C/code>. The optional TypeScript peer dependency now requires TypeScript 5.6 or newer, which supports arbitrary quoted module export names.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2181\">\x3Ca href=\"#2181\">2.18.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-16\">\x3Ca href=\"#patch-changes-16\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>6eb7d02: Fix input match generation so \x3Ccode>Infinity\x3C/code> selectors match both numeric \x3Ccode>Infinity\x3C/code> values and string \x3Ccode>\"Infinity\"\x3C/code> values.\x3C/li>\n\x3Cli>c16730d: Pin default jsDelivr plugin URLs to exact versions in generated project settings.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2180\">\x3Ca href=\"#2180\">2.18.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-8\">\x3Ca href=\"#minor-changes-8\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>62d37f0: Add a \x3Ccode>relativetime\x3C/code> declaration formatter backed by \x3Ccode>Intl.RelativeTimeFormat\x3C/code>.\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-17\">\x3Ca href=\"#patch-changes-17\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>a5f31bc: Update \x3Ccode>@inlang/sdk\x3C/code> to 2.9.3.\x3C/li>\n\x3Cli>d2bf729: Mark \x3Ccode>typescript\x3C/code> as an optional peer dependency and show a clear error when \x3Ccode>emitTsDeclarations\x3C/code> is enabled without TypeScript installed.\x3C/li>\n\x3Cli>ea8343f: Fix race condition where \x3Ccode>paraglideVitePlugin\x3C/code> (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 \x3Ccode>previousCompilation\x3C/code> 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.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2170\">\x3Ca href=\"#2170\">2.17.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-9\">\x3Ca href=\"#minor-changes-9\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>109e588: Add \x3Ccode>--output-structure\x3C/code> option to the compile command.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2161\">\x3Ca href=\"#2161\">2.16.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-18\">\x3Ca href=\"#patch-changes-18\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>3bb446a: Update \x3Ccode>@inlang/sdk\x3C/code> to \x3Ccode>2.9.2\x3C/code>.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2160\">\x3Ca href=\"#2160\">2.16.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-10\">\x3Ca href=\"#minor-changes-10\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>8401dae: Add new \x3Ccode>paraglide-js compile\x3C/code> CLI flags for compiler options that were\npreviously only available through the programmatic API or bundler plugins.\x3C/p>\n\x3Cp>You can now:\x3C/p>\n\x3Cul>\n\x3Cli>enable or disable emitted \x3Ccode>.gitignore\x3C/code>, \x3Ccode>.prettierignore\x3C/code>, and \x3Ccode>README.md\x3C/code>\x3C/li>\n\x3Cli>explicitly enable or disable emitted \x3Ccode>.d.ts\x3C/code> files\x3C/li>\n\x3Cli>pass a custom \x3Ccode>isServer\x3C/code> expression for runtime tree-shaking\x3C/li>\n\x3C/ul>\n\x3Cp>These options are forwarded through regular and \x3Ccode>--watch\x3C/code> compiles so the CLI\nmatches the existing compiler behavior more closely.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2153\">\x3Ca href=\"#2153\">2.15.3\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-19\">\x3Ca href=\"#patch-changes-19\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b10186d: Fix numeric input match inference so generated message typings accept both numeric and string literal forms for values like \x3Ccode>input=1\x3C/code>, matching runtime behavior without relying on broad loose coercion.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2152\">\x3Ca href=\"#2152\">2.15.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-20\">\x3Ca href=\"#patch-changes-20\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>c716c6d: Fix proxy-aware URL handling in \x3Ccode>paraglideMiddleware()\x3C/code>, \x3Ccode>shouldRedirect()\x3C/code>, and locale extraction by adding an \x3Ccode>effectiveRequestUrl\x3C/code> override for browser-facing URLs behind TLS-terminating proxies and load balancers. Addresses \x3Ca href=\"https://github.com/opral/paraglide-js/issues/652\">#652\x3C/a>.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2151\">\x3Ca href=\"#2151\">2.15.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-21\">\x3Ca href=\"#patch-changes-21\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>2e8b5a1: Add markup documentation and message format plugin references to compiled README\x3C/li>\n\x3Cli>8964e8b: Update \x3Ccode>@inlang/sdk\x3C/code> to \x3Ccode>2.9.1\x3C/code>.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2150\">\x3Ca href=\"#2150\">2.15.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-11\">\x3Ca href=\"#minor-changes-11\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>862433c: Add \x3Ccode>toLocale()\x3C/code> for case-insensitive locale normalization, make \x3Ccode>isLocale()\x3C/code>\nstrictly match canonical project locales, and return canonical locale values\nacross runtime locale helpers.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">// configured locales: [\"fr\", \"en-US\"]\x3C/span>\n\n\x3Cspan class=\"hljs-title function_\">isLocale\x3C/span>(\x3Cspan class=\"hljs-string\">\"FR\"\x3C/span>); \x3Cspan class=\"hljs-comment\">// false\x3C/span>\n\x3Cspan class=\"hljs-title function_\">toLocale\x3C/span>(\x3Cspan class=\"hljs-string\">\"FR\"\x3C/span>); \x3Cspan class=\"hljs-comment\">// \"fr\"\x3C/span>\n\n\x3Cspan class=\"hljs-title function_\">isLocale\x3C/span>(\x3Cspan class=\"hljs-string\">\"en-us\"\x3C/span>); \x3Cspan class=\"hljs-comment\">// false\x3C/span>\n\x3Cspan class=\"hljs-title function_\">toLocale\x3C/span>(\x3Cspan class=\"hljs-string\">\"en-us\"\x3C/span>); \x3Cspan class=\"hljs-comment\">// \"en-US\"\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>Runtime helpers that resolve locales from external input now return canonical\nproject locale values as well.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2141\">\x3Ca href=\"#2141\">2.14.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-22\">\x3Ca href=\"#patch-changes-22\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>7d29058: Remove dead JSDoc \x3Ccode>@import\x3C/code> stripping from the runtime generator.\x3C/li>\n\x3Cli>46ac447: Upgrade \x3Ccode>@inlang/sdk\x3C/code> to v2.8.0.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2140\">\x3Ca href=\"#2140\">2.14.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-12\">\x3Ca href=\"#minor-changes-12\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>067509d: Improve generated runtime typing by centralizing shared type definitions, avoiding strict \x3Ccode>checkJs\x3C/code> locale type errors, and moving middleware locale-splitting state under \x3Ccode>globalThis.__paraglide.ssr\x3C/code>.\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-23\">\x3Ca href=\"#patch-changes-23\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>a17af28: Remove stale telemetry internals that were no longer used by the CLI or compiler.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2132\">\x3Ca href=\"#2132\">2.13.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-24\">\x3Ca href=\"#patch-changes-24\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>2e18cc0: Fix compiler code generation for formatter option literals so Intl numeric and boolean options are emitted with the correct literal types.\x3C/p>\n\x3Cp>This resolves strict \x3Ccode>checkJs\x3C/code>/\x3Ccode>svelte-check\x3C/code> errors where generated \x3Ccode>number()\x3C/code> options like \x3Ccode>minimumFractionDigits\x3C/code> were emitted as strings and caused \x3Ccode>Type 'string' is not assignable to type 'number'\x3C/code>.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2131\">\x3Ca href=\"#2131\">2.13.1\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-25\">\x3Ca href=\"#patch-changes-25\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>9d79aff: Fix single-locale message generation to avoid emitting an unused \x3Ccode>locale\x3C/code> variable in strict TypeScript \x3Ccode>checkJs\x3C/code> setups. This removes \x3Ccode>TS6133\x3C/code> (\x3Ccode>'locale' is declared but its value is never read\x3C/code>) warnings for generated message files when only one locale is configured.\x3C/p>\n\x3Cp>Add a regression type test that asserts single-locale generated messages do not produce this warning.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2130\">\x3Ca href=\"#2130\">2.13.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-13\">\x3Ca href=\"#minor-changes-13\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>7185902: Add a new runtime utility: \x3Ccode>getTextDirection(locale?)\x3C/code>.\x3C/p>\n\x3Cul>\n\x3Cli>Returns \x3Ccode>\"ltr\"\x3C/code> or \x3Ccode>\"rtl\"\x3C/code> for a given locale.\x3C/li>\n\x3Cli>Defaults to the current locale from \x3Ccode>getLocale()\x3C/code> when no locale is provided.\x3C/li>\n\x3Cli>Uses \x3Ccode>Intl.Locale\x3C/code> text info when available, with a safe RTL fallback for runtimes without that API.\x3C/li>\n\x3C/ul>\n\x3Cp>Also updates SvelteKit example/docs to show setting both \x3Ccode>%lang%\x3C/code> and \x3Ccode>%dir%\x3C/code> in \x3Ccode>app.html\x3C/code> using runtime APIs.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2120\">\x3Ca href=\"#2120\">2.12.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-14\">\x3Ca href=\"#minor-changes-14\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>af0084e: Add route-level locale strategy overrides via \x3Ccode>routeStrategies\x3C/code>.\x3C/p>\n\x3Cp>You can now define per-route strategy behavior (first match wins), including:\x3C/p>\n\x3Cul>\n\x3Cli>\x3Ccode>strategy\x3C/code> overrides for paths like \x3Ccode>/dashboard/*\x3C/code> and \x3Ccode>/rpc/*\x3C/code>\x3C/li>\n\x3Cli>\x3Ccode>exclude: true\x3C/code> to skip i18n middleware behavior for paths like \x3Ccode>/api/*\x3C/code>\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2110\">\x3Ca href=\"#2110\">2.11.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-15\">\x3Ca href=\"#minor-changes-15\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>d1c86fb: Improve emitted message-module output by gating middleware locale-splitting hooks behind \x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code>.\x3C/p>\n\x3Cp>When the option is disabled (default), generated message functions no longer emit:\x3C/p>\n\x3Cul>\n\x3Cli>\x3Ccode>if (experimentalMiddlewareLocaleSplitting && isServer === false) { ...__paraglide.ssr... }\x3C/code>\x3C/li>\n\x3Cli>\x3Ccode>trackMessageCall(...)\x3C/code>\x3C/li>\n\x3Cli>related runtime imports (\x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code>, \x3Ccode>isServer\x3C/code>, \x3Ccode>trackMessageCall\x3C/code>)\x3C/li>\n\x3C/ul>\n\x3Cp>When \x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code> is enabled, the existing SSR/middleware injection flow is preserved.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>90a1580: Add compiler support for markup messages with a new \x3Ccode>message.parts()\x3C/code> API.\x3C/p>\n\x3Cp>Messages that contain markup now compile to framework-neutral parts (\x3Ccode>text\x3C/code>, \x3Ccode>markup-start\x3C/code>, \x3Ccode>markup-end\x3C/code>, and \x3Ccode>markup-standalone\x3C/code>) while \x3Ccode>message()\x3C/code> continues to return plain strings.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2100\">\x3Ca href=\"#2100\">2.10.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-16\">\x3Ca href=\"#minor-changes-16\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>fc66ee1: Add type-safe literal unions for match variants in generated message typings \x3Ca href=\"https://github.com/opral/paraglide-js/issues/538\">https://github.com/opral/paraglide-js/issues/538\x3C/a>.\x3C/p>\n\x3Cp>For example, the following minimal message definition:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-json\">\x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\x3Cspan class=\"hljs-attr\">\"auth_password_error\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">
1837[\x3C/span>\n\t\t\x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\t\t\x3Cspan class=\"hljs-attr\">\"match\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\t\t\t\x3Cspan class=\"hljs-attr\">\"type=empty\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"You must provide a password\"\x3C/span>\n\t\t\t\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\t\t\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\t\x3Cspan class=\"hljs-punctuation\">]\x3C/span>\n\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>Before:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">m.\x3Cspan class=\"hljs-title function_\">auth_password_error\x3C/span>({ \x3Cspan class=\"hljs-attr\">type\x3C/span>: \x3Cspan class=\"hljs-string\">\"typo\"\x3C/span> }); \x3Cspan class=\"hljs-comment\">// â
OK (typed as NonNullable<unknown>)\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>After:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">m.\x3Cspan class=\"hljs-title function_\">auth_password_error\x3C/span>({ \x3Cspan class=\"hljs-attr\">type\x3C/span>: \x3Cspan class=\"hljs-string\">\"typo\"\x3C/span> }); \x3Cspan class=\"hljs-comment\">// ð¥ Type error\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"291\">\x3Ca href=\"#291\">2.9.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-26\">\x3Ca href=\"#patch-changes-26\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>c43effb: Update \x3Ccode>@inlang/sdk\x3C/code> to v2.6.2, which removes a file queue settlement that could prevent the compiler from exiting in some environments. See \x3Ca href=\"https://github.com/opral/paraglide-js/issues/598\">https://github.com/opral/paraglide-js/issues/598\x3C/a>.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"290\">\x3Ca href=\"#290\">2.9.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-17\">\x3Ca href=\"#minor-changes-17\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>badca6a: Add the experimental \x3Ccode>experimentalStaticLocale\x3C/code> compiler option for per-locale tree-shaking (see \x3Ca href=\"https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638\">https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638\x3C/a>).\x3C/li>\n\x3Cli>a0c5665: Prune async_hooks import from generated server output when async local storage is disabled (fixes \x3Ca href=\"https://github.com/opral/paraglide-js/issues/539\">https://github.com/opral/paraglide-js/issues/539\x3C/a>).\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-27\">\x3Ca href=\"#patch-changes-27\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>9ae2381: Add \x3Ccode>@see\x3C/code> documentation links to runtime and server APIs, making it easier for developers to find relevant documentation directly from their IDE.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>867ea44: Avoid cyclic fallback maps when a language-only locale exists alongside a regional base locale.\x3C/p>\n\x3Cp>Previously, a setup like \x3Ccode>locales: [\"it\", \"it-IT\"]\x3C/code> with \x3Ccode>baseLocale: \"it-IT\"\x3C/code> could create a fallback cycle (\x3Ccode>it â it-IT â it\x3C/code>) and throw a runtime error. The compiler now breaks that cycle by making the \x3Ccode>baseLocale\x3C/code> terminal, so \x3Ccode>it-IT\x3C/code> no longer falls back to \x3Ccode>it\x3C/code> while \x3Ccode>it\x3C/code> still falls back to \x3Ccode>it-IT\x3C/code>.\x3C/p>\n\x3Cp>Issue: \x3Ca href=\"https://github.com/opral/paraglide-js/issues/544\">https://github.com/opral/paraglide-js/issues/544\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>3cbdd75: Fix message compilation for input names with non-identifier characters (like \x3Ccode>half!\x3C/code>).\x3C/p>\n\x3Cp>Before: i18next-style placeholders with symbols produced invalid JS because we emitted \x3Ccode>i.half!\x3C/code> in patterns, local variables, and match conditions (syntax error).\nNow: Paraglide quotes the key in JSDoc and uses bracket access in generated code (e.g. \x3Ccode>i[\"half!\"]\x3C/code>), so the same message compiles and runs correctly.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-// before (invalid JS)\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-// input: { \"half!\": \"1st\" }\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-return `${i.half!} Half - Corner Handicap`\x3C/span>\n\x3Cspan class=\"hljs-addition\">+// after (valid JS)\x3C/span>\n\x3Cspan class=\"hljs-addition\">+// input: { \"half!\": \"1st\" }\x3C/span>\n\x3Cspan class=\"hljs-addition\">+return `${i[\"half!\"]} Half - Corner Handicap`\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>Issue: \x3Ca href=\"https://github.com/opral/paraglide-js/issues/514\">https://github.com/opral/paraglide-js/issues/514\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>deb9877: Avoid locale/message name collisions in the locale-modules output structure by prefixing locale imports.\x3C/p>\n\x3Cp>Previously, a locale like \x3Ccode>no\x3C/code>
1837 could collide with a message key \x3Ccode>no\x3C/code>, causing duplicate symbol errors in the generated \x3Ccode>messages/_index.js\x3C/code>.\nNow, locale imports are prefixed (e.g. \x3Ccode>__no\x3C/code>), keeping message exports intact and avoiding the conflict.\x3C/p>\n\x3Cp>Issue: \x3Ca href=\"https://github.com/opral/paraglide-js/issues/492\">https://github.com/opral/paraglide-js/issues/492\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"280\">\x3Ca href=\"#280\">2.8.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-18\">\x3Ca href=\"#minor-changes-18\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>07e17c0: Emit a \x3Ccode>README.md\x3C/code> in the compiled output to help LLMs understand the generated code. The README includes usage examples, runtime API documentation, and links to further resources. Can be disabled with \x3Ccode>emitReadme: false\x3C/code>.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>991c314: Improve watch mode to monitor directories so newly added translation files trigger recompiles in the CLI and bundler plugin.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>4a75259: Update inlang SDK to v2.6.0 with improved project structure and forward-compatibility.\x3C/p>\n\x3Cp>\x3Cstrong>New \x3Ccode>.meta.json\x3C/code> file in inlang projects:\x3C/strong>\x3C/p>\n\x3Cp>The SDK now writes a \x3Ccode>.meta.json\x3C/code> file to track which SDK version last modified the project. This enables safe forward migrations and prevents accidental downgrades when switching between SDK versions.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode>project.inlang/\n settings.json\n README.md\n .gitignore\n .meta.json <-- new\n\x3C/code>\x3C/pre>\n\x3Cp>\x3Cstrong>Updated \x3Ccode>.gitignore\x3C/code> handling:\x3C/strong>\x3C/p>\n\x3Cp>Inlang projects now manage their own \x3Ccode>.gitignore\x3C/code> that ignores everything except \x3Ccode>settings.json\x3C/code>. If you see the \x3Ccode>.gitignore\x3C/code> file inside your \x3Ccode>.inlang\x3C/code> project folder showing up as changed in git, run these commands to fix it:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-bash\">\x3Cspan class=\"hljs-comment\"># Remove the tracked .gitignore from git's index\x3C/span>\ngit \x3Cspan class=\"hljs-built_in\">rm\x3C/span> --cached \x3Cspan class=\"hljs-string\">'**/*.inlang/.gitignore'\x3C/span>\n\n\x3Cspan class=\"hljs-comment\"># Commit the change\x3C/span>\ngit commit -m \x3Cspan class=\"hljs-string\">\"fix: remove tracked .gitignore from inlang project\"\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>This is a one-time fix. The inlang SDK handles the \x3Ccode>.gitignore\x3C/code> automatically starting with v2.5.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-28\">\x3Ca href=\"#patch-changes-28\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>ec7f3e3: Add a \x3Ccode>--watch\x3C/code> flag to the CLI \x3Ccode>compile\x3C/code> command to recompile on changes.\x3C/li>\n\x3Cli>be10228: Strip sourcemap references from generated runtime and server outputs to avoid missing map warnings. (\x3Ca href=\"https://github.com/opral/paraglide-js/issues/581\">https://github.com/opral/paraglide-js/issues/581\x3C/a>)\x3C/li>\n\x3Cli>e75e2a3: Add documentation for avoiding redirect loops with frameworks that handle URL localization themselves (e.g., TanStack Router).\n\x3Cul>\n\x3Cli>Added JSDoc example in \x3Ccode>paraglideMiddleware()\x3C/code> explaining when to use the original request vs the modified request\x3C/li>\n\x3Cli>Added troubleshooting section in SSR docs explaining the redirect loop issue and solution\x3C/li>\n\x3Cli>Updated TanStack Start example README with an important callout about using the original request\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"272\">\x3Ca href=\"#272\">2.7.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-29\">\x3Ca href=\"#patch-changes-29\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>983d893: Added a defensive try catch request cloning in \x3Ccode>paraglideMiddleware\x3C/code> for runtimes with custom \x3Ccode>Request\x3C/code> wrappers (TanStack Start 1.143+: \x3Ca href=\"https://github.com/TanStack/router/issues/6089\">https://github.com/TanStack/router/issues/6089\x3C/a>, \x3Ca href=\"https://github.com/opral/paraglide-js/issues/573\">https://github.com/opral/paraglide-js/issues/573\x3C/a>).\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"271\">\x3Ca href=\"#271\">2.7.1\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-30\">\x3Ca href=\"#patch-changes-30\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>update \x3Ccode>@inlang/sdk\x3C/code> to \x3Ccode>2.4.10\x3C/code> which contains a fix for dynamically loading plugins in bun \x3Ca href=\"https://github.com/opral/monorepo/pull/3787\">https://github.com/opral/monorepo/pull/3787\x3C/a>.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"270\">\x3Ca href=\"#270\">2.7.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-19\">\x3Ca href=\"#minor-changes-19\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>Add an opt-in \x3Ccode>emitTsDeclarations\x3C/code> compiler flag to generate \x3Ccode>.d.ts\x3C/code> files for the compiled output.\x3C/p>\n\x3Cp>This is useful when \x3Ccode>allowJs: true\x3C/code> cannot be set in your \x3Ccode>tsconfig.json\x3C/code> (e.g., due to project constraints or conflicting compiler options).\x3C/p>\n\x3Cp>\x3Cstrong>Usage:\x3C/strong>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">// vite.config.ts\x3C/span>\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { defineConfig } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"vite\"\x3C/span>;\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { paraglideVitePlugin } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"@inlang/paraglide-js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">export\x3C/span> \x3Cspan class=\"hljs-keyword\">default\x3C/span> \x3Cspan class=\"hljs-title function_\">defineConfig\x3C/span>({\n\t\x3Cspan class=\"hljs-attr\">plugins\x3C/span>: [\n\t\t\x3Cspan class=\"hljs-title function_\">paraglideVitePlugin\x3C/span>({\n\t\t\t\x3Cspan class=\"hljs-attr\">project\x3C/span>: \x3Cspan class=\"hljs-string\">\"./project.inlang\"\x3C/span>,\n\t\t\t\x3Cspan class=\"hljs-attr\">outdir\x3C/span>: \x3Cspan class=\"hljs-string\">\"./src/paraglide\"\x3C/span>,\n\t\t\t\x3Cspan class=\"hljs-attr\">emitTsDeclarations\x3C/span>: \x3Cspan class=\"hljs-literal\">true\x3C/span>,\n\t\t}),\n\t],\n});\n\x3C/code>\x3C/pre>\n\x3Cp>Or via CLI:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-bash\">paraglide compile --project ./project.inlang --outdir ./src/paraglide --emitTsDeclarations\n\x3C/code>\x3C/pre>\n\x3Cp>\x3Cstrong>Note:\x3C/strong> Enabling this option reduces compiler speed because TypeScript needs to generate declaration files for all output modules.\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/566\">https://github.com/opral/inlang-paraglide-js/issues/566\x3C/a>\nCloses \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/238\">https://github.com/opral/inlang-paraglide-js/issues/238\x3C/a>\nCloses \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/160\">https://github.com/opral/inlang-paraglide-js/issues/160\x3C/a>\x3C/p>\n\x3Cp>Example output (locale-modules):\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\"> src/paraglide/\n messages/\n _index.js\n\x3Cspan class=\"hljs-addition\">+ _index.d.ts\x3C/span>\n de.js\n\x3Cspan class=\"hljs-addition\">+ de.d.ts\x3C/span>\n en.js\n\x3Cspan class=\"hljs-addition\">+ en.d.ts\x3C/span>\n messages.js\n\x3Cspan class=\"hljs-addition\">+ messages.d.ts\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"260\">\x3Ca href=\"#260\">2.6.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-20\">\x3Ca href=\"#minor-changes-20\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>3d6259c: Add \x3Ccode>LocalizedString\x3C/code> branded type for compile-time i18n safety.\x3C/p>\n\x3Cp>Message functions now return \x3Ccode>LocalizedString\x3C/code> instead of \x3Ccode>string\x3C/code>, enabling TypeScript users to distinguish between translated and untranslated strings at compile time. This is fully backward compatible since branded types are assignable to their base type.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-typescript\">\x3Cspan class=\"hljs-keyword\">import\x3C/span> { m } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/messages.js\"\x3C/span>;\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> \x3Cspan class=\"hljs-keyword\">type\x3C/span> { \x3Cspan class=\"hljs-title class_\">
1837LocalizedString\x3C/span> } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"@inlang/paraglide-js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-attr\">greeting\x3C/span>: \x3Cspan class=\"hljs-title class_\">LocalizedString\x3C/span> = m.\x3Cspan class=\"hljs-title function_\">hello\x3C/span>(); \x3Cspan class=\"hljs-comment\">// â Type-safe\x3C/span>\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-attr\">raw\x3C/span>: \x3Cspan class=\"hljs-title class_\">LocalizedString\x3C/span> = \x3Cspan class=\"hljs-string\">\"Hello\"\x3C/span>; \x3Cspan class=\"hljs-comment\">// â Type error\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3Cli>\n\x3Cp>4bde3eb: Add optional chaining to compiled message inputs so missing inputs no longer throw at runtime; include tests covering single- and multi-variant messages.\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/568\">https://github.com/opral/inlang-paraglide-js/issues/568\x3C/a>\x3C/p>\n\x3Cp>Example:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// compiled translation\x3C/span>\n\x3Cspan class=\"hljs-keyword\">export\x3C/span> \x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-title function_\">greeting\x3C/span> = (\x3Cspan class=\"hljs-params\">i\x3C/span>) => \x3Cspan class=\"hljs-string\">`Hello \x3Cspan class=\"hljs-subst\">${i?.name}\x3C/span>`\x3C/span>;\n\n\x3Cspan class=\"hljs-comment\">// TypeScript still enforces the input shape; this is purely runtime safety (handy in dev).\x3C/span>\n\x3Cspan class=\"hljs-title function_\">greeting\x3C/span>(); \x3Cspan class=\"hljs-comment\">// no throw, returns \"Hello undefined\"\x3C/span>\n\x3Cspan class=\"hljs-title function_\">greeting\x3C/span>({ \x3Cspan class=\"hljs-attr\">name\x3C/span>: \x3Cspan class=\"hljs-string\">\"Ada\"\x3C/span> }); \x3Cspan class=\"hljs-comment\">// \"Hello Ada\"\x3C/span>\n\n\x3Cspan class=\"hljs-comment\">// previously (boom ð¥)\x3C/span>\n\x3Cspan class=\"hljs-keyword\">export\x3C/span> \x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-title function_\">greetingOld\x3C/span> = (\x3Cspan class=\"hljs-params\">i\x3C/span>) => \x3Cspan class=\"hljs-string\">`Hello \x3Cspan class=\"hljs-subst\">${i.name}\x3C/span>`\x3C/span>;\n\x3Cspan class=\"hljs-title function_\">greetingOld\x3C/span>(); \x3Cspan class=\"hljs-comment\">// TypeError: Cannot read properties of undefined (reading 'name')\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"250\">\x3Ca href=\"#250\">2.5.0\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>\n\x3Cp>72d1c53: Ensure the CLI honours allowJs flags defined in extended or referenced tsconfig files instead of prompting unnecessarily.\x3C/p>\n\x3Cp>Refs \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/560\">https://github.com/opral/inlang-paraglide-js/issues/560\x3C/a>.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>c59da26: fix: make locale matching case-insensitive\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/549\">https://github.com/opral/inlang-paraglide-js/issues/549\x3C/a>\x3C/p>\n\x3Cp>This fixes an issue that locales containing uppercase characters like \x3Ccode>pt-BR\x3C/code> failed to load when using \x3Ccode>extractLocaleFromNavigator\x3C/code> or \x3Ccode>extractLocaleFromHeader\x3C/code>.\x3C/p>\n\x3Cp>The issue occurred because these functions converted locales to lowercase, while the comparison logic inside \x3Ccode>assertIsLocale\x3C/code> and \x3Ccode>isLocale\x3C/code> wasn't case-sensitive.\x3C/p>\n\x3Cp>List of changes:\x3C/p>\n\x3Cul>\n\x3Cli>Ensured locale comparisons in \x3Ccode>assertIsLocale()\x3C/code> and \x3Ccode>isLocale()\x3C/code> are fully case-insensitive.\x3C/li>\n\x3Cli>Made \x3Ccode>assertIsLocale()\x3C/code> return the canonical-cased locale from \x3Ccode>locales\x3C/code> instead of the raw input.\x3C/li>\n\x3Cli>Added new test coverage for case-insensitive behavior in \x3Ccode>assertIsLocale()\x3C/code> and \x3Ccode>isLocale()\x3C/code>.\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3Cli>\n\x3Cp>9735b82: Fix fallback assignment generation so locale chains emit dependencies first and avoid \"Block-scoped variable used before its declaration\" errors. See \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/507\">https://github.com/opral/inlang-paraglide-js/issues/507\x3C/a> for details.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"240\">\x3Ca href=\"#240\">2.4.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-21\">\x3Ca href=\"#minor-changes-21\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>4111ee6: Add an isomorphic \x3Ccode>shouldRedirect()\x3C/code> helper shared by the middleware and client routers, improve redirect typing, and document the new API in the URL strategy guide.\x3C/li>\n\x3C/ul>
1837\n\x3Ch3 id=\"patch-changes-31\">\x3Ca href=\"#patch-changes-31\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>4a48c07: fix: fix eslint incorrectly linting generated files\x3C/p>\n\x3Cp>closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/558\">https://github.com/opral/inlang-paraglide-js/issues/558\x3C/a>\x3C/p>\n\x3Cp>eslint ignores single-line 'eslint-disable' comments at the start of a file.\nUsing a block comment without a closing one instead will prompt eslint to ignore it.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-\toutput[filename] = `// eslint-disable\\n${content}`;\x3C/span>\n\x3Cspan class=\"hljs-addition\">+\toutput[filename] = `/* eslint-disable */\\n${content}`;\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3Cli>\n\x3Cp>4c8921f: Fixes \x3Ccode>overwriteSetLocale\x3C/code> to keep the full \x3Ccode>(locale, options?)\x3C/code> signature when overriding \x3Ccode>setLocale\x3C/code>, preventing TypeScript from rejecting calls that pass \x3Ccode>{ reload: false }\x3C/code>. Adds a regression test ensuring custom handlers receive the options object.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>Updated dependencies [7791be7]\x3C/p>\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"232\">\x3Ca href=\"#232\">2.3.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-32\">\x3Ca href=\"#patch-changes-32\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>4ea9e7a: fix: ensure that async custom setLocale funcs resolve with reload: false\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"231\">\x3Ca href=\"#231\">2.3.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-33\">\x3Ca href=\"#patch-changes-33\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>090964b: fix(runtime/set-locale.js): ensure reload waits for async custom setLocale funcs \x3Ca href=\"https://github.com/opral/monorepo/pull/3692\">https://github.com/opral/monorepo/pull/3692\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"230\">\x3Ca href=\"#230\">2.3.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-22\">\x3Ca href=\"#minor-changes-22\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>bfe8518: Crash the build process (for example during \x3Ccode>vite build\x3C/code>) if paraglide can't compile the project.\x3C/li>\n\x3Cli>Removed local account loading which suddenly led to crashes for some users.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"220\">\x3Ca href=\"#220\">2.2.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-23\">\x3Ca href=\"#minor-changes-23\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>69ac911: Add support for async custom server strategies with \x3Ccode>extractLocaleFromRequestAsync\x3C/code>\x3C/p>\n\x3Cp>This change introduces a new \x3Ccode>extractLocaleFromRequestAsync\x3C/code> function that supports asynchronous custom server strategies, enabling use cases like fetching user locale preferences from databases.\x3C/p>\n\x3Ch2 id=\"whats-changed\">\x3Ca href=\"#whats-changed\">What's Changed\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>\x3Cstrong>New Function\x3C/strong>: Added \x3Ccode>extractLocaleFromRequestAsync\x3C/code> that supports async custom server strategies\x3C/li>\n\x3Cli>\x3Cstrong>Middleware Update\x3C/strong>: Server middleware now uses the async version to support async custom strategies\x3C/li>\n\x3Cli>\x3Cstrong>Breaking Change\x3C/strong>: The synchronous \x3Ccode>extractLocaleFromRequest\x3C/code> no longer supports custom server strategies\x3C/li>\n\x3Cli>\x3Cstrong>Improved Documentation\x3C/strong>: Added comprehensive examples and usage guidance\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"migration-guide\">\x3Ca href=\"#migration-guide\">
1837Migration Guide\x3C/a>\x3C/h2>\n\x3Ch3 id=\"for-users-with-custom-server-strategies\">\x3Ca href=\"#for-users-with-custom-server-strategies\">For users with custom server strategies:\x3C/a>\x3C/h3>\n\x3Cp>\x3Cstrong>Before:\x3C/strong>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// This no longer works in sync version\x3C/span>\n\x3Cspan class=\"hljs-title function_\">defineCustomServerStrategy\x3C/span>(\x3Cspan class=\"hljs-string\">\"custom-database\"\x3C/span>, {\n\t\x3Cspan class=\"hljs-attr\">getLocale\x3C/span>: \x3Cspan class=\"hljs-title function_\">async\x3C/span> (request) => {\n\t\t\x3Cspan class=\"hljs-keyword\">return\x3C/span> \x3Cspan class=\"hljs-keyword\">await\x3C/span> \x3Cspan class=\"hljs-title function_\">getUserLocaleFromDatabase\x3C/span>(request);\n\t},\n});\n\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> locale = \x3Cspan class=\"hljs-title function_\">extractLocaleFromRequest\x3C/span>(request); \x3Cspan class=\"hljs-comment\">// Won't call async custom strategies\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>\x3Cstrong>After:\x3C/strong>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// Use the async version for custom strategies\x3C/span>\n\x3Cspan class=\"hljs-title function_\">defineCustomServerStrategy\x3C/span>(\x3Cspan class=\"hljs-string\">\"custom-database\"\x3C/span>, {\n\t\x3Cspan class=\"hljs-attr\">getLocale\x3C/span>: \x3Cspan class=\"hljs-title function_\">async\x3C/span> (request) => {\n\t\t\x3Cspan class=\"hljs-keyword\">return\x3C/span> \x3Cspan class=\"hljs-keyword\">
1837await\x3C/span> \x3Cspan class=\"hljs-title function_\">getUserLocaleFromDatabase\x3C/span>(request);\n\t},\n});\n\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> locale = \x3Cspan class=\"hljs-keyword\">await\x3C/span> \x3Cspan class=\"hljs-title function_\">extractLocaleFromRequestAsync\x3C/span>(request); \x3Cspan class=\"hljs-comment\">// Supports async custom strategies\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch3 id=\"for-users-calling-extractlocalefromrequest-directly\">\x3Ca href=\"#for-users-calling-extractlocalefromrequest-directly\">For users calling \x3Ccode>extractLocaleFromRequest\x3C/code> directly:\x3C/a>\x3C/h3>\n\x3Cp>If you're using \x3Ccode>extractLocaleFromRequest\x3C/code> directly in your code without custom strategies, no changes are needed. For custom server strategies, switch to \x3Ccode>extractLocaleFromRequestAsync\x3C/code>.\x3C/p>\n\x3Cp>The server middleware automatically uses the async version, so no changes are needed for standard middleware usage.\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/527\">https://github.com/opral/inlang-paraglide-js/issues/527\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-34\">\x3Ca href=\"#patch-changes-34\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>5589e30: (likely) fix: handler is of type \x3Ccode>unknown\x3C/code> ts error \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/529\">https://github.com/opral/inlang-paraglide-js/issues/529\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>3712f09: Fix cookieDomain default behavior for better server/client cookie compatibility.\x3C/p>\n\x3Cp>When \x3Ccode>cookieDomain\x3C/code> is undefined or empty, cookies are now set without a domain attribute, scoping them to the exact current domain only (no subdomains). This fixes compatibility issues with server-side cookies that don't include a domain attribute.\x3C/p>\n\x3Cp>\x3Cstrong>Before\x3C/strong>:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// When cookieDomain was undefined, cookies were set as:\x3C/span>\n\x3Cspan class=\"hljs-variable language_\">document\x3C/span>.\x3Cspan class=\"hljs-property\">cookie\x3C/span> =\n\t\x3Cspan class=\"hljs-string\">\"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; domain=example.com\"\x3C/span>;\n\x3Cspan class=\"hljs-comment\">// This made cookies available to subdomains\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>\x3Cstrong>After\x3C/strong>:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// When cookieDomain is undefined, cookies are now set as:\x3C/span>\n\x3Cspan class=\"hljs-variable language_\">document\x3C/span>.\x3Cspan class=\"hljs-property\">cookie\x3C/span> = \x3Cspan class=\"hljs-string\">\"PARAGLIDE_LOCALE=en; path=/; max-age=34560000\"\x3C/span>;\n\x3Cspan class=\"hljs-comment\">// This scopes cookies to the exact current domain only\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>\x3Cstrong>Migration\x3C/strong>:\x3C/p>\n\x3Cul>\n\x3Cli>If you want the previous behavior (subdomain sharing), explicitly set \x3Ccode>cookieDomain\x3C/code> in your configuration:\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">paraglideWebpackPlugin({\n project: './project.inlang',\n outdir: \"./src/paraglide\",\n\x3Cspan class=\"hljs-addition\">+ cookieDomain: 'example.com'\x3C/span>\n})\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"210\">\x3Ca href=\"#210\">2.1.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-24\">\x3Ca href=\"#minor-changes-24\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>4255bd5: Provide functions for getting the preferred language on server and client.\x3C/p>\n\x3Cp>This defines two new functions for getting the preferred language:\x3C/p>\n\x3Cul>\n\x3Cli>\x3Ccode>extractLocaleFromHeader\x3C/code>: Extracts the locale from the accept-language header on the server.\x3C/li>\n\x3Cli>\x3Ccode>extractLocaleFromNavigator\x3C/code>: Extracts the locale from the navigator.languages array on the client.\x3C/li>\n\x3C/ul>\n\x3Cp>The code was already present in the \x3Ccode>@inlang/paraglide-js\x3C/code> package, but it was not exported. Now it is exported so that\nit can be used in custom strategies.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>dc287f1: Implement custom strategy concept for locale resolution.\x3C/p>\n\x3Cp>This introduces a new way to define custom locale resolution strategies alongside built-in strategies. Custom strategies provide a cleaner, more composable approach compared to overwriting \x3Ccode>getLocale()\x3C/code> and \x3Ccode>setLocale()\x3C/code> functions directly.\x3C/p>\n\x3Cp>\x3Cstrong>New APIs:\x3C/strong>\x3C/p>\n\x3Cul>\n\x3Cli>\x3Ccode>defineCustomClientStrategy()\x3C/code>: Define custom strategies for client-side locale resolution\x3C/li>\n\x3Cli>\x3Ccode>defineCustomServerStrategy()\x3C/code>: Define custom strategies for server-side locale resolution\x3C/li>\n\x3C/ul>\n\x3Cp>\x3Cstrong>Key features:\x3C/strong>\x3C/p>\n\x3Cul>\n\x3Cli>Custom strategies must follow the pattern \x3Ccode>custom-<name>\x3C/code> where \x3Ccode><name>\x3C/code> contains only alphanumeric characters\x3C/li>\n\x3Cli>Can be combined with built-in strategies in the strategy array\x3C/li>\n\x3Cli>Respect strategy order for fallback handling\x3C/li>\n\x3Cli>Support both client and server environments\x3C/li>\n\x3Cli>Provide better error isolation and type safety\x3C/li>\n\x3C/ul>\n\x3Cp>\x3Cstrong>Usage example:\x3C/strong>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-keyword\">import\x3C/span> { defineCustomClientStrategy } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/runtime.js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-title function_\">defineCustomClientStrategy\x3C/span>(\x3Cspan class=\"hljs-string\">\"custom-sessionStorage\"\x3C/span>, {\n\t\x3Cspan class=\"hljs-attr\">
1837getLocale\x3C/span>: \x3Cspan class=\"hljs-function\">() =>\x3C/span> \x3Cspan class=\"hljs-variable language_\">sessionStorage\x3C/span>.\x3Cspan class=\"hljs-title function_\">getItem\x3C/span>(\x3Cspan class=\"hljs-string\">\"user-locale\"\x3C/span>) ?? \x3Cspan class=\"hljs-literal\">undefined\x3C/span>,\n\t\x3Cspan class=\"hljs-attr\">setLocale\x3C/span>: \x3Cspan class=\"hljs-function\">(\x3Cspan class=\"hljs-params\">locale\x3C/span>) =>\x3C/span> \x3Cspan class=\"hljs-variable language_\">sessionStorage\x3C/span>.\x3Cspan class=\"hljs-title function_\">setItem\x3C/span>(\x3Cspan class=\"hljs-string\">\"user-locale\"\x3C/span>, locale),\n});\n\x3C/code>\x3C/pre>\n\x3Cp>Then include in your strategy configuration:\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-title function_\">compile\x3C/span>({\n\t\x3Cspan class=\"hljs-attr\">strategy\x3C/span>: [\x3Cspan class=\"hljs-string\">\"custom-sessionStorage\"\x3C/span>, \x3Cspan class=\"hljs-string\">\"cookie\"\x3C/span>, \x3Cspan class=\"hljs-string\">\"baseLocale\"\x3C/span>],\n});\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-35\">\x3Ca href=\"#patch-changes-35\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>4c0b997: perf(paraglide): improve bundle size by removing message id fallback for fully translated messages\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>9621803: Add Vary: Accept-Language header when preferredLanguage strategy is used\x3C/p>\n\x3Cp>Paraglide middleware now automatically sets the \x3Ccode>Vary: Accept-Language\x3C/code> header when performing redirects based on the \x3Ccode>preferredLanguage\x3C/code> strategy. This indicates to clients (CDN cache, crawlers, etc.) that the response will be different depending on the \x3Ccode>Accept-Language\x3C/code> header, ensuring proper caching behavior and SEO compliance.\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/522\">https://github.com/opral/inlang-paraglide-js/issues/522\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>Updated dependencies [22089a2]\x3C/p>\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2013\">\x3Ca href=\"#2013\">2.0.13\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-36\">\x3Ca href=\"#patch-changes-36\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>688c7c8: Add support for callbacks in server middleware\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>635861b: \x3Ccode>extractLocaleFromUrl()\x3C/code> now uses a cache for the last value.\x3C/p>\n\x3Cp>Useful on the client-side where the same URL is being extracted many times for each message on a given page.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2012\">\x3Ca href=\"#2012\">2.0.12\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-37\">\x3Ca href=\"#patch-changes-37\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>31337ba: expose \x3Ccode>createParaglide()\x3C/code>\x3C/li>\n\x3Cli>Updated dependencies [56acb22]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2011\">\x3Ca href=\"#2011\">2.0.11\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-38\">\x3Ca href=\"#patch-changes-38\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>de0439f: Add domain property to cookie options.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">paraglideVitePlugin({\n project: './project.inlang',\n outdir: \"./src/paraglide\",\n\x3Cspan class=\"hljs-addition\">+ cookieDomain: 'example.com'\x3C/span>\n}),\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"2010\">\x3Ca href=\"#2010\">2.0.10\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-39\">\x3Ca href=\"#patch-changes-39\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>d16e853: fix: [2.0.8] Adds extra */ in generated .js files \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/493\">https://github.com/opral/inlang-paraglide-js/issues/493\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"209\">\x3Ca href=\"#209\">2.0.9\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-40\">\x3Ca href=\"#patch-changes-40\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>Updated dependencies [bd2c366]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"208\">\x3Ca href=\"#208\">2.0.8\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-41\">\x3Ca href=\"#patch-changes-41\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>5258af0: fix: compiling message bundles with case sensitive ids for the locale module output \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/490\">https://github.com/opral/inlang-paraglide-js/issues/490\x3C/a>\x3C/p>\n\x3Cp>Case sensitive ids led to duplicate exports in the locale module output. This has been fixed by adjusting the \x3Ccode>toSafeModuleId()\x3C/code> used by the compiler internally to append a number of uppercase characters to de-duplicate the ids.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">toSafeModuleId(\"helloworld\")\n \"helloworld\"\n\ntoSafeModuleId(\"helloWorld\")\n\x3Cspan class=\"hljs-deletion\">- \"helloworld\"\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"helloworld1\"\x3C/span>\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"207\">\x3Ca href=\"#207\">2.0.7\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-42\">\x3Ca href=\"#patch-changes-42\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>48931f5: make \x3Ccode>output-structure: locale-modules\x3C/code> the default for dev builds \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/486\">https://github.com/opral/inlang-paraglide-js/issues/486\x3C/a>\x3C/li>\n\x3Cli>Updated dependencies [49a7880]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"206\">\x3Ca href=\"#206\">2.0.6\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-43\">\x3Ca href=\"#patch-changes-43\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>
18373fa27c0: fix: duplicate (case sensitive) message keys leading to compile error when using \x3Ccode>output-structure: locale-modules\x3C/code>. closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/487\">https://github.com/opral/inlang-paraglide-js/issues/487\x3C/a>\x3C/li>\n\x3Cli>02c2d34: improve: compiler should log warnings when plugins can not be imported\x3C/li>\n\x3Cli>Updated dependencies [083ff1f]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"205\">\x3Ca href=\"#205\">2.0.5\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-44\">\x3Ca href=\"#patch-changes-44\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>698b9a9: add \x3Ccode>cookieMaxAge\x3C/code> option to compiler and runtime\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/483\">https://github.com/opral/inlang-paraglide-js/issues/483\x3C/a>\x3C/p>\n\x3Cul>\n\x3Cli>Introduced \x3Ccode>cookieMaxAge\x3C/code> option to \x3Ccode>CompilerOptions\x3C/code>, allowing configuration of cookie expiration time.\x3C/li>\n\x3Cli>Adjusted tests to verify \x3Ccode>max-age\x3C/code> in cookies.\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"204\">\x3Ca href=\"#204\">2.0.4\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-45\">\x3Ca href=\"#patch-changes-45\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"203\">\x3Ca href=\"#203\">2.0.3\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-46\">\x3Ca href=\"#patch-changes-46\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>cf404e0: improve: handle duplicate inputs \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/479\">https://github.com/opral/inlang-paraglide-js/issues/479\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"202\">\x3Ca href=\"#202\">2.0.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-47\">\x3Ca href=\"#patch-changes-47\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>a6c43ea: fix: error handling in paraglideMiddleware breaks SvelteKit features that rely on errors being thrown\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"201\">\x3Ca href=\"#201\">2.0.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-48\">\x3Ca href=\"#patch-changes-48\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b906c0c: fix: window undefined bug in webpack\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"paraglide-js-20-ð\">\x3Ca href=\"#paraglide-js-20-ð\">Paraglide JS 2.0 ð\x3C/a>\x3C/h2>\n\x3Cp>Paraglide JS 2.0 had three main goals which have all been achieved:\x3C/p>\n\x3Col>\n\x3Cli>Use the new inlang SDK v2 which supports variants \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/201\">#201\x3C/a>.\x3C/li>\n\x3Cli>Unify the API across any framework \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/217\">#217\x3C/a>.\x3C/li>\n\x3Cli>Support any i18n strategy (cookie, url, domain, session, etc).\x3C/li>\n\x3C/ol>\n\x3Cul>\n\x3Cli>ð \x3Cstrong>Variants (pluralization) are now supported\x3C/strong> \x3Ca href=\"https://paraglidejs.com/variants\">docs\x3C/a>\x3C/li>\n\x3Cli>ð \x3Cstrong>No more adapters or providers are needed\x3C/strong> (!)\x3C/li>\n\x3Cli>ð£ï¸ \x3Cstrong>Any strategy (url, cookie, local storage) is now supported\x3C/strong> \x3Ca href=\"https://paraglidejs.com/strategy\">docs\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Cp>In addition, Paraglide JS 2.0 comes with:\x3C/p>\n\x3Cul>\n\x3Cli>ð \x3Cstrong>Nested message keys\x3C/strong> are now supported (most requested feature!)\x3C/li>\n\x3Cli>⨠\x3Cstrong>Auto-imports\x3C/strong> when writing \x3Ccode>m.\x3C/code> (no more manual \x3Ccode>import * as m\x3C/code>)\x3C/li>\n\x3Cli>ð \x3Cstrong>Arbitrary key names\x3C/strong> including emojis via \x3Ccode>m[\"ð\"]()\x3C/code>\x3C/li>\n\x3Cli>ð \x3Cstrong>Incremental migration\x3C/strong> to Paraglide JS is now possible\x3C/li>\n\x3Cli>ðï¸ \x3Cstrong>Multi-tenancy support\x3C/strong> for domain-based routing\x3C/li>\n\x3Cli>ð§ \x3Cstrong>Exposing the compiler API\x3C/strong> for advanced workflows\x3C/li>\n\x3Cli>ð£ï¸ \x3Cstrong>Configurable routing strategies\x3C/strong> (URL, cookie, domain, etc)\x3C/li>\n\x3Cli>𧪠\x3Cstrong>Experimental per-locale splitting\x3C/strong> for decreasing bundle sizes\x3C/li>\n\x3Cli>ð \x3Cstrong>Framework-agnostic server middleware\x3C/strong> for SSR (SvelteKit, Next.js, etc)\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"highlights\">\x3Ca href=\"#highlights\">Highlights\x3C/a>\x3C/h3>\n\x3Ch4 id=\"interactive-benchmark\">\x3Ca href=\"#interactive-benchmark\">Interactive benchmark\x3C/a>\x3C/h4>\n\x3Cp>Check out the \x3Ca href=\"https://paraglidejs.com/benchmark\">benchmark\x3C/a> to see how Paraglide JS compares to other libraries like i18next.\x3C/p>\n\x3Cp>\x3Ca href=\"https://paraglidejs.com/benchmark\">\x3Cimg src=\"https://cdn.jsdelivr.net/gh/opral/paraglide-js@main/assets/interactive-benchmark.png\" alt=\"Benchmark Visualization\">\x3C/a>\x3C/p>
1837\n\x3Ch4 id=\"no-more-adapters-are-needed\">\x3Ca href=\"#no-more-adapters-are-needed\">No more adapters are needed\x3C/a>\x3C/h4>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- @inlang/paraglide-sveltekit\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- @inlang/paraglide-next\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ // No more adapters are needed\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"-framework-agnostic-server-middleware\">\x3Ca href=\"#-framework-agnostic-server-middleware\">ð Framework-Agnostic Server Middleware\x3C/a>\x3C/h4>\n\x3Cp>Docs are \x3Ca href=\"https://paraglidejs.com/server-side-rendering\">here\x3C/a>\x3C/p>\n\x3Cul>\n\x3Cli>\x3Cstrong>New\x3C/strong>: Universal \x3Ccode>paraglideMiddleware()\x3C/code> works in any SSR framework\x3C/li>\n\x3Cli>\x3Cstrong>Built-in\x3C/strong>: Automatic locale redirects when user preference detected\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">// SvelteKit example - same pattern works for Next.js, Astro, etc.\x3C/span>\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { paraglideMiddleware } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/server.js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">export\x3C/span> \x3Cspan class=\"hljs-keyword\">const\x3C/span> \x3Cspan class=\"hljs-title function_\">handle\x3C/span> = (\x3Cspan class=\"hljs-params\">{ event, resolve }\x3C/span>) => {\n\t\x3Cspan class=\"hljs-keyword\">return\x3C/span> \x3Cspan class=\"hljs-title function_\">paraglideMiddleware\x3C/span>(event.\x3Cspan class=\"hljs-property\">request\x3C/span>, \x3Cspan class=\"hljs-function\">() =>\x3C/span> \x3Cspan class=\"hljs-title function_\">resolve\x3C/span>(event));\n};\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"ï¸-configurable-routing-strategies\">\x3Ca href=\"#ï¸-configurable-routing-strategies\">ð£ï¸ Configurable Routing Strategies\x3C/a>\x3C/h4>\n\x3Cp>Read more about strategies on the \x3Ca href=\"https://paraglidejs.com/strategy\">docs\x3C/a>.\x3C/p>\n\x3Cp>Literally anything is now possible. URL-based, domain-based, path-based, cookie-based, etc.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-title function_\">paraglide\x3C/span>({\n\t\x3Cspan class=\"hljs-attr\">strategy\x3C/span>: [\n \x3Cspan class=\"hljs-string\">\"url\"\x3C/span>,\n \x3Cspan class=\"hljs-string\">\"cookie\"\x3C/span>,\n \x3Cspan class=\"hljs-string\">\"preferredLanguage\"\x3C/span>,\n \x3Cspan class=\"hljs-string\">\"...\"\x3C/span>\n ],\n}),\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"-exposing-the-compiler-api\">\x3Ca href=\"#-exposing-the-compiler-api\">ð§ Exposing the compiler API\x3C/a>\x3C/h4>\n\x3Cul>\n\x3Cli>\x3Cstrong>New\x3C/strong>: Direct compiler access for advanced workflows\x3C/li>\n\x3Cli>\x3Cstrong>Why\x3C/strong>: Enable CI/CD pipelines and custom tooling\x3C/li>\n\x3Cli>\x3Cstrong>Benefit\x3C/strong>: Full control over compilation timing/caching\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">// New programmatic API\x3C/span>\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { compile } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"@inlang/paraglide-js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">
1837await\x3C/span> \x3Cspan class=\"hljs-title function_\">compile\x3C/span>({\n\t\x3Cspan class=\"hljs-attr\">project\x3C/span>: \x3Cspan class=\"hljs-string\">\"./project.inlang\"\x3C/span>,\n\t\x3Cspan class=\"hljs-attr\">outdir\x3C/span>: \x3Cspan class=\"hljs-string\">\"./src/paraglide\"\x3C/span>,\n});\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"-arbitrary-key-names\">\x3Ca href=\"#-arbitrary-key-names\">ð Arbitrary key names\x3C/a>\x3C/h4>\n\x3Cul>\n\x3Cli>\x3Cstrong>New\x3C/strong>: Arbitrary key names including emojis via `m\x3Ca href=\"\">\"ð\"\x3C/a>\x3C/li>\n\x3Cli>\x3Cstrong>Why\x3C/strong>: Enable nesting of messages\x3C/li>\n\x3Cli>\x3Cstrong>Benefit\x3C/strong>: More expressive and fun translations\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">// Paraglide 1.0\x3C/span>\nm.\x3Cspan class=\"hljs-title function_\">some_message\x3C/span>(); \x3Cspan class=\"hljs-comment\">// â
Works\x3C/span>\nm.\x3Cspan class=\"hljs-property\">nested\x3C/span>.\x3Cspan class=\"hljs-title function_\">message\x3C/span>(); \x3Cspan class=\"hljs-comment\">// ð¥ Error\x3C/span>\n\n\x3Cspan class=\"hljs-comment\">// Paraglide 2.0\x3C/span>\nm.\x3Cspan class=\"hljs-title function_\">some_message\x3C/span>(); \x3Cspan class=\"hljs-comment\">// â
Works\x3C/span>\nm[\x3Cspan class=\"hljs-string\">\"nested.message\"\x3C/span>](); \x3Cspan class=\"hljs-comment\">// â
Works\x3C/span>\n\n\x3Cspan class=\"hljs-comment\">// Even emojis are supported\x3C/span>\nm[\x3Cspan class=\"hljs-string\">\"ð\"\x3C/span>]();\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"-incrementally-migrating-to-paraglide-js\">\x3Ca href=\"#-incrementally-migrating-to-paraglide-js\">ð Incrementally migrating to Paraglide JS\x3C/a>\x3C/h4>\n\x3Cp>Paraglide JS 2.0 can load multiple \x3Ca href=\"https://paraglidejs.com/file-formats\">translation file formats\x3C/a>. As such, you can incrementally migrate to Paraglide JS with existing translation file formats.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-js\">\x3Cspan class=\"hljs-comment\">// In this example, Paraglide JS compiles i18next translation files\x3C/span>\n\x3Cspan class=\"hljs-comment\">// which enables using both i18next and Paraglide JS.\x3C/span>\n\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> i18next \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"i18next\"\x3C/span>;\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { m } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/messages.js\"\x3C/span>;\n\n\x3Cspan class=\"hljs-variable language_\">console\x3C/span>.\x3Cspan class=\"hljs-title function_\">
1837log\x3C/span>(i18next.\x3Cspan class=\"hljs-title function_\">t\x3C/span>(\x3Cspan class=\"hljs-string\">\"greeting\"\x3C/span>, { \x3Cspan class=\"hljs-attr\">name\x3C/span>: \x3Cspan class=\"hljs-string\">\"World\"\x3C/span> }));\n\x3Cspan class=\"hljs-variable language_\">console\x3C/span>.\x3Cspan class=\"hljs-title function_\">log\x3C/span>(m.\x3Cspan class=\"hljs-title function_\">greeting\x3C/span>({ \x3Cspan class=\"hljs-attr\">name\x3C/span>: \x3Cspan class=\"hljs-string\">\"World\"\x3C/span> }));\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"ï¸-multi-tenancy-support\">\x3Ca href=\"#ï¸-multi-tenancy-support\">ðï¸ Multi-tenancy support\x3C/a>\x3C/h4>\n\x3Cp>Paraglide JS 2.0 supports multi-tenant applications. Read more about it \x3Ca href=\"https://paraglidejs.com/multi-tenancy\">here\x3C/a>.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode># Domain-based with sub-locale\ncustomer1.fr/about â French (default)\ncustomer1.fr/en/about â English version\n\n# Domain-based with root locale\ncustomer2.com/about â English (default)\ncustomer2.com/fr/about â French version\n\n# Path-based for any domain\nexample.com/en/about â English\nexample.com/fr/about â French\napp.example.com/en/about â English\napp.example.com/fr/about â French\n\x3C/code>\x3C/pre>\n\x3Ch3 id=\"migrating-breaking-changes\">\x3Ca href=\"#migrating-breaking-changes\">Migrating breaking changes\x3C/a>\x3C/h3>\n\x3Cp>If problems arise, please refer to the framework-specific getting started guide:\x3C/p>\n\x3Cul>\n\x3Cli>\x3Ca href=\"https://paraglidejs.com/sveltekit\">SvelteKit\x3C/a>\x3C/li>\n\x3Cli>\x3Ca href=\"https://paraglidejs.com/next-js\">Next.js\x3C/a>\x3C/li>\n\x3Cli>\x3Ca href=\"https://paraglidejs.com/astro\">Astro\x3C/a>\x3C/li>\n\x3Cli>\x3Ca href=\"https://paraglidejs.com/vite\">Vite\x3C/a>\x3C/li>\n\x3Cli>\x3Ca href=\"https://paraglidejs.com/react-router\">React Router\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch4 id=\"languagetag-got-renamed-to-locale\">\x3Ca href=\"#languagetag-got-renamed-to-locale\">\x3Ccode>LanguageTag\x3C/code> got renamed to \x3Ccode>locale\x3C/code>\x3C/a>\x3C/h4>\n\x3Cp>To align with industry standards, we renamed \x3Ccode>LanguageTag\x3C/code> to \x3Ccode>locale\x3C/code>.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-languageTag()\x3C/span>\n\x3Cspan class=\"hljs-addition\">+getLocale()\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-setLanguageTag()\x3C/span>\n\x3Cspan class=\"hljs-addition\">+setLocale()\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-availableLanguageTags\x3C/span>\n\x3Cspan class=\"hljs-addition\">+locales\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"remove-adapters-inlangparaglide--from-your-dependencies\">\x3Ca href=\"#remove-adapters-inlangparaglide--from-your-dependencies\">Remove adapters \x3Ccode>@inlang/paraglide-*\x3C/code> from your dependencies\x3C/a>\x3C/h4>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">// package.json\n{\n \"dependencies\": {\n\x3Cspan class=\"hljs-deletion\">- \"@inlang/paraglide-sveltekit\": \"^1.0.0\",\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- \"@inlang/paraglide-next\": \"^1.0.0\",\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- \"@inlang/paraglide-astro\": \"^1.0.0\",\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- \"@inlang/paraglide-vite\": \"^1.0.0\",\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"@inlang/paraglide-js\": \"^2.0.0\",\x3C/span>\n }\n}\n```\n\n### Replace adapter bundler plugins\n\n```diff\n// vite.config.js\n\x3Cspan class=\"hljs-deletion\">-import { paraglide } from \"@inlang/paraglide-vite\";\x3C/span>\n\x3Cspan class=\"hljs-addition\">+import { paraglideVitePlugin } from \"@inlang/paraglide-js\";\x3C/span>\n\n\nexport default defineConfig({\n\tplugins: [\n\x3Cspan class=\"hljs-deletion\">-\t\tparaglide({\x3C/span>\n\x3Cspan class=\"hljs-addition\">+\t\tparaglideVitePlugin({\x3C/span>\n\t\t\tproject: \"./project.inlang\",\n\t\t\toutdir: \"./src/paraglide\",\n\t\t}),\n\t],\n});\n\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"remove-paraglide-providers\">\x3Ca href=\"#remove-paraglide-providers\">Remove Paraglide Providers\x3C/a>\x3C/h4>\n\x3Cp>Paraglide JS 2.0 no longer requires providers.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">// app.tsx, layout.svelte, etc.\n\x3Cspan class=\"hljs-deletion\">-import { ParaglideProvider } from \"@inlang/paraglide-{framework}\";
1837\x3C/span>\n\nfunction App() {\n return (\n\x3Cspan class=\"hljs-deletion\">- <ParaglideProvider>\x3C/span>\n <YourApp />\n\x3Cspan class=\"hljs-deletion\">- </ParaglideProvider>\x3C/span>\n )\n}\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"shorten-key-names-longer-than-255-characters\">\x3Ca href=\"#shorten-key-names-longer-than-255-characters\">Shorten key names longer than 255 characters\x3C/a>\x3C/h4>\n\x3Cp>Paraglide JS 2.0 build output now defaults to \x3Ca href=\"https://paraglidejs.com/compiler-options#outputstructure\">message-modules\x3C/a> to improve tree-shaking. Some filesystem's limitations require key names to be shorter than 255 characters.\x3C/p>\n\x3Cp>Upvote \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/423\">#423\x3C/a> to remove this limitation.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- m.this_is_a_very_long_key_name_that_should_be_shortened()\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ m.shortened_key_name()\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"changing-the-locale-requires-a-reload\">\x3Ca href=\"#changing-the-locale-requires-a-reload\">Changing the locale requires a reload\x3C/a>\x3C/h4>\n\x3Cp>Changing the locale works via \x3Ccode>setLocale()\x3C/code> in any framework now.\x3C/p>\n\x3Cp>If you used an adapter in v1 like the SvelteKit one, this behavior is new. The new behaviour leads to a page reload. The reload is a deliberate design decision. Reloading the site eliminates the need for providers, adapters, and API differences between frameworks. Furthermore, optimizations like per-locale splitting is expected to be easier to implement.\x3C/p>\n\x3Cp>Read \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/438#issuecomment-2703733096\">https://github.com/opral/inlang-paraglide-js/issues/438#issuecomment-2703733096\x3C/a> for more information.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-<a href=\"/de\">Deutsch</a>\x3C/span>\n\x3Cspan class=\"hljs-addition\">+<button onclick=\"setLocale('de')\">Deutsch</button>\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"lint-rules-were-deprecated\">\x3Ca href=\"#lint-rules-were-deprecated\">Lint rules were deprecated\x3C/a>\x3C/h4>\n\x3Cp>Remove lint rules from your project modules.\x3C/p>\n\x3Cp>We want to re-introduce lint rules in a better form in the future. Please upvote the \x3Ca href=\"https://github.com/opral/lix-sdk/issues/239\">#239 lix validation rules\x3C/a> proposal.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">modules: [\n\x3Cspan class=\"hljs-deletion\">- \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js\",\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-\t \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js\"\x3C/span>\n ...\n]\n\n\x3C/code>\x3C/pre>\n\x3Ch4 id=\"localizehref-is-now-required\">\x3Ca href=\"#localizehref-is-now-required\">\x3Ccode>localizeHref()\x3C/code> is now required\x3C/a>\x3C/h4>\n\x3Cp>Some Paraglide adapters used AST transforms to automatically transform \x3Ccode><a>\x3C/code> into localized links. That led to many bugs and edge cases. The AST transforms were removed for v2.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-<a href=\"/page\"></a>\x3C/span>\n\x3Cspan class=\"hljs-addition\">+<a href={localizeHref(\"/page\")}\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta31-released-as-200\">\x3Ca href=\"#200-beta31-released-as-200\">2.0.0-beta.31 (released as 2.0.0)\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>\n\x3Cp>feat: New API: \x3Ccode>createParaglide()\x3C/code>\x3C/p>\n\x3Cp>The function allows a no build step or before build step access to Paraglide's compiled APIs.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-typescript\">\x3Cspan class=\"hljs-keyword\">const\x3C/span> project = \x3Cspan class=\"hljs-keyword\">
1837await\x3C/span> fs.\x3Cspan class=\"hljs-title function_\">readFile\x3C/span>(\x3Cspan class=\"hljs-string\">\"./project.inlang\"\x3C/span>);\n\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> paraglide = \x3Cspan class=\"hljs-keyword\">await\x3C/span> \x3Cspan class=\"hljs-title function_\">createParaglideModule\x3C/span>({\n\tproject,\n\t\x3Cspan class=\"hljs-attr\">compilerOptions\x3C/span>: {\n\t\t\x3Cspan class=\"hljs-attr\">strategy\x3C/span>: [\x3Cspan class=\"hljs-string\">\"url\"\x3C/span>],\n\t},\n});\n\n\x3Cspan class=\"hljs-comment\">// Use runtime functions\x3C/span>\nparaglide.\x3Cspan class=\"hljs-title function_\">localizeUrl\x3C/span>(\x3Cspan class=\"hljs-string\">\"https://example.com\"\x3C/span>, { \x3Cspan class=\"hljs-attr\">locale\x3C/span>: \x3Cspan class=\"hljs-string\">\"de\"\x3C/span> });\n\n\x3Cspan class=\"hljs-comment\">// Use server middleware\x3C/span>\napp.\x3Cspan class=\"hljs-title function_\">use\x3C/span>(paraglide.\x3Cspan class=\"hljs-title function_\">paraglideMiddleware\x3C/span>());\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix: \x3Ccode>getLocale\x3C/code> returns correct value on SvelteKit server \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/461\">#461\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix: Prevent redirect loops by normalizing URLs with trailing slashes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/408\">#408\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix: Support for explicit port numbers in URL patterns\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>improve: Better error handling in server middleware\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta30\">\x3Ca href=\"#200-beta30\">2.0.0-beta.30\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>\n\x3Cp>improve: if no url pattern matches, \x3Ccode>localizeUrl()\x3C/code> and \x3Ccode>deLocalizeUrl()\x3C/code> will return the input url unchanged instead of throwing an error \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/452#issuecomment-2715761308\">#452\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>improve: make AsyncLocalStorage tree-shakable by moving \x3Ccode>disableAsyncLocalStorage\x3C/code> into the compiler options \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/424#issuecomment-2711453627\">#424\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ serverMiddleware(req, resolve)\x3C/span>\n\nparaglideVitePlugin({\n // ...\n\x3Cspan class=\"hljs-addition\">+ disableAsyncLocalStorage: true\x3C/span>\n})\n\n\x3C/code>\x3C/pre>\n\x3Cul>\n\x3Cli>improve: allow fall through. enables partially localized patterns and thereby eases adoption.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta29\">\x3Ca href=\"#200-beta29\">2.0.0-beta.29\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>\n\x3Cp>fix \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/455\">#455 setLocale and getLocale call each other in a loop\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/454\">#454 Adapt config to the new localized param of beta.28\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta28\">\x3Ca href=\"#200-beta28\">2.0.0-beta.28\x3C/a>\x3C/h2>\n\x3Ch3 id=\"breaking-update-to-the-urlpattern-api\">\x3Ca href=\"#breaking-update-to-the-urlpattern-api\">BREAKING update to the URLPattern API\x3C/a>\x3C/h3>\n\x3Cp>\x3Ca href=\"https://github.com/opral/monorepo/pull/3485\">https://github.com/opral/monorepo/pull/3485\x3C/a>\x3C/p>\n\x3Cp>The \x3Ccode>localizedNamedGroups\x3C/code> and \x3Ccode>deLocalizedNamedGroups\x3C/code> API has been replaced with a tuple-based \x3Ccode>localized\x3C/code> array to:\x3C/p>\n\x3Cul>\n\x3Cli>enable translated pathnames in any combination\x3C/li>\n\x3Cli>make the API more intuitive\x3C/li>\n\x3C/ul>\n\x3Ch4 id=\"migration-guide-1\">\x3Ca href=\"#migration-guide-1\">Migration Guide:\x3C/a>\x3C/h4>\n\x3Cp>\x3Cstrong>Refer to the updated documentation \x3Ca href=\"https://paraglidejs.com/strategy#url\">here\x3C/a>.\x3C/strong>\x3C/p>\n\x3Cp>Before\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-json\">\x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\x3Cspan class=\"hljs-attr\">\"pattern\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">
1837\"https://:domain(.*)/:locale(de|fr)?/:path*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\t\x3Cspan class=\"hljs-attr\">\"deLocalizedNamedGroups\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span> \x3Cspan class=\"hljs-attr\">\"locale\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-literal\">\x3Cspan class=\"hljs-keyword\">null\x3C/span>\x3C/span> \x3Cspan class=\"hljs-punctuation\">}\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\t\x3Cspan class=\"hljs-attr\">\"localizedNamedGroups\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\t\x3Cspan class=\"hljs-attr\">\"en\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span> \x3Cspan class=\"hljs-attr\">\"locale\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-literal\">\x3Cspan class=\"hljs-keyword\">null\x3C/span>\x3C/span> \x3Cspan class=\"hljs-punctuation\">}\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\t\t\x3Cspan class=\"hljs-attr\">\"fr\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span> \x3Cspan class=\"hljs-attr\">\"locale\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"fr\"\x3C/span> \x3Cspan class=\"hljs-punctuation\">}\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\t\t\x3Cspan class=\"hljs-attr\">\"de\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span> \x3Cspan class=\"hljs-attr\">\"locale\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"de\"\x3C/span> \x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\t\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>After\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-json\">\x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n \x3Cspan class=\"hljs-attr\">\"pattern\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"https://:domain(.*)/:path*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n \x3Cspan class=\"hljs-attr\">\"localized\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">[\x3C/span>\n \x3Cspan class=\"hljs-punctuation\">[\x3C/span>\x3Cspan class=\"hljs-string\">\"fr\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span> \x3Cspan class=\"hljs-string\">\"https://:domain(.*)/fr/:path*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">]\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n \x3Cspan class=\"hljs-punctuation\">[\x3C/span>\x3Cspan class=\"hljs-string\">\"de\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span> \x3Cspan class=\"hljs-string\">\"https://:domain(.*)/de/:path*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">]\x3C/span>\n \x3Cspan class=\"hljs-punctuation\">[\x3C/span>\x3Cspan class=\"hljs-string\">\"en\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span> \x3Cspan class=\"hljs-string\">\"https://:domain(.*)/:path*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">]\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n \x3Cspan class=\"hljs-punctuation\">]\x3C/span>\n\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch3 id=\"other-changes\">\x3Ca href=\"#other-changes\">other changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>improve: fallback to \x3Ccode>typeof window\x3C/code> in vite \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/445\">#445\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>make \x3Ccode>setLocale()\x3C/code> set all strategies. Setting all strategies aligns with user expectations and ensures that server APIs can receive the cookie of the client, for example. \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/439\">#439\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>new \x3Ccode>generateStaticLocalizedUrls()\x3C/code> API \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/433\">#443\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">const localizedUrls = generateStaticLocalizedUrls([\n \"/example\",\n \"/page/blog\",\n \"/123/hello\"\n])\n\nconsole.log(localizedUrls.map(url => url.pathnames))\n>> /de/example\n>> /fr/example\n>> ...\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta27\">\x3Ca href=\"#200-beta27\">2.0.0-beta.27\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>fix wrong matching in API requests \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/427\">#427\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Cp>Paraglide JS is no longer extracting the locale from API requests for the \x3Ccode>url\x3C/code> strategy because that can lead to unwanted re-directs. To get the right locale in API requests, at least add the \x3Ccode>baseLocale\x3C/code> strategy to your options.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-strategy: [\"url\"]\x3C/span>\n\x3Cspan class=\"hljs-addition\">+strategy: [\"url\", \"cookie\", \"baseLocale\"]\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cul>\n\x3Cli>\n\x3Cp>consolidated \x3Ccode>message-modules\x3C/code> output into a single file \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/434\">#434\x3C/a> to severaly improve scalability\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>\x3Ccode>experimentalMiddlewareLocaleSplitting\x3C/code> option \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/425#issuecomment-2692351073\">https://github.com/opral/inlang-paraglide-js/issues/425#issuecomment-2692351073\x3C/
1837a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/430\">setLocale() triggers re-loads if the same locale is set\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/442\">serverMiddleware() throws when cookie contains invalid locale\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>add \x3Ccode>localStorage\x3C/code> strategy \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/431\">#431\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fix url strategy with optional locale always resoles base locale \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/436\">#436\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta26\">\x3Ca href=\"#200-beta26\">2.0.0-beta.26\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>replace \x3Ccode>node:crypto\x3C/code> with the Web Crypto API \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/424\">https://github.com/opral/inlang-paraglide-js/issues/424\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta25\">\x3Ca href=\"#200-beta25\">2.0.0-beta.25\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>added optional localized groups\x3C/li>\n\x3Cli>keeps hashes, etc. in the URL when localizing \x3Ca href=\"https://github.com/opral/monorepo/pull/3452\">https://github.com/opral/monorepo/pull/3452\x3C/a>\x3C/li>\n\x3Cli>fixes the multi-variant return\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta24\">\x3Ca href=\"#200-beta24\">2.0.0-beta.24\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>changes the redirect status from \x3Ccode>302\x3C/code> to \x3Ccode>307\x3C/code> \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/416\">https://github.com/opral/inlang-paraglide-js/issues/416\x3C/a>\x3C/li>\n\x3Cli>adds a \x3Ccode>cleanOutdir\x3C/code> option which defaults to true \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/420\">https://github.com/opral/inlang-paraglide-js/issues/420\x3C/a>\x3C/li>\n\x3Cli>adds a \x3Ccode>machine-translate\x3C/code> command if desired on init\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta23\">\x3Ca href=\"#200-beta23\">2.0.0-beta.23\x3C/a>\x3C/h2>\n\x3Cp>Renames and splits the \x3Ccode>serverMiddleware()\x3C/code> into a dedicated \x3Ccode>server.js\x3C/code> file to avoid bundler issues.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- import { serverMiddleware } from \"./paraglide/runtime.js\";\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ import { paraglideMiddleware } from \"./paraglide/server.js\";\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta22\">\x3Ca href=\"#200-beta22\">2.0.0-beta.22\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>fix \x3Ccode>serverMiddleware()\x3C/code> only imports async_hooks on the server\x3C/li>\n\x3Cli>add \x3Ccode>serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })\x3C/code> to disable async local storage\x3C/li>\n\x3Cli>fix \x3Ccode>serverMiddleware()\x3C/code> throws in next js when \x3Ccode>url\x3C/code> strategy is not used \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/411#issuecomment-2683530533\">https://github.com/opral/inlang-paraglide-js/issues/411#issuecomment-2683530533\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta21\">\x3Ca href=\"#200-beta21\">2.0.0-beta.21\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>compile arbitrary message keys \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2680006131\">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2680006131\x3C/a>\x3C/li>\n\x3Cli>only polyfills \x3Ccode>URLPattern\x3C/code> if needed \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/381\">https://github.com/opral/inlang-paraglide-js/issues/381\x3C/a>\x3C/li>\n\x3Cli>don't include \x3Ccode>url\x3C/code> strategy by default \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/405\">https://github.com/opral/inlang-paraglide-js/issues/405\x3C/a>\x3C/li>\n\x3Cli>fixes webpack watch mode \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/406\">https://github.com/opral/inlang-paraglide-js/issues/406\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta20\">\x3Ca href=\"#200-beta20\">2.0.0-beta.20\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>automatic re-directs in \x3Ccode>serverMiddleware()\x3C/code> \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2675823651\">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2675823651\x3C/a>\x3C/li>\n\x3Cli>various bug fixes and improvements\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta19\">\x3Ca href=\"#200-beta19\">
18372.0.0-beta.19\x3C/a>\x3C/h2>\n\x3Cp>NO MORE ADAPTERS NEEDED.\x3C/p>\n\x3Cp>If you have code from an adapter, remove it and follow the examples in the documentation. \x3Ca href=\"https://paraglidejs.com/sveltekit\">https://paraglidejs.com/sveltekit\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-@inlang/paraglide-sveltekit\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-@inlang/paraglide-next\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-@inlang/paraglide-astro\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cul>\n\x3Cli>\n\x3Cp>introduced \x3Ccode>serverMiddleware()\x3C/code> \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2673375348\">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2673375348\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>rename \x3Ccode>defineGetLocale()\x3C/code> and \x3Ccode>defineSetLocale()\x3C/code> to \x3Ccode>overwriteGetLocale()\x3C/code> and \x3Ccode>overwriteSetLocale()\x3C/code> \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/382\">https://github.com/opral/inlang-paraglide-js/issues/382\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>enables \x3Ccode>import { m } from \"./paraglide/messages.js\"\x3C/code> for auto imports \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/345\">https://github.com/opral/inlang-paraglide-js/issues/345\x3C/a>\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>adds the \x3Ccode>strategy\x3C/code> compiler option to the cli \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/316\">https://github.com/opral/inlang-paraglide-js/issues/316\x3C/a>\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta18\">\x3Ca href=\"#200-beta18\">2.0.0-beta.18\x3C/a>\x3C/h2>\n\x3Cp>Added URLPatterns as a replacement for the beta 17 pathnames API.\x3C/p>\n\x3Cp>The URLPattern API is extremly powerful. You can express base paths, translated pathnames, domain based localization, and even multi-tenancy.\x3C/p>\n\x3Cp>Read the docs \x3Ca href=\"https://paraglidejs.com/strategy#url\">here\x3C/a> and make PRs to improve the documentation.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n\x3Cspan class=\"hljs-deletion\">- strategy: [\"pathname\"],\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ strategy: [\"url\"],\x3C/span>\n})\n\x3C/code>\x3C/pre>\n\x3Cp>The \x3Ccode>localizePath()\x3C/code> API had to be replaced by a new \x3Ccode>localizeHref()\x3C/code> API. Please give feedback on the new API in \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/380\">#380\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- <a href={localizePath(\"/about\")}>About</a>\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ <a href={localizeHref(\"/about\")}>About</a>\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta17\">\x3Ca href=\"#200-beta17\">2.0.0-beta.17\x3C/a>\x3C/h2>\n\x3Cp>Add support for \x3Ccode>pathnames\x3C/code> API \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/359\">https://github.com/opral/inlang-paraglide-js/issues/359\x3C/a>\x3C/p>\n\x3Cp>You can now create whatever pathname pattern you want. The syntax is provided by \x3Ca href=\"https://github.com/pillarjs/path-to-regexp\">https://github.com/pillarjs/path-to-regexp\x3C/a>.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n strategy: [\"pathname\", \"cookie\", \"baseLocale\"],\n\x3Cspan class=\"hljs-addition\">+ pathnames: {\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"{*path}\": {\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"de\": \"/de{/*path}\",\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"en\": \"/en{/*path}\",\x3C/span>\n}\n}\n})\n\x3C/code>\x3C/pre>\n\x3Cp>Add support for \x3Ccode>pathnameBase\x3C/code> \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/362\">https://github.com/opral/inlang-paraglide-js/issues/362\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n strategy: [\"pathname\", \"cookie\", \"baseLocale\"],\n\x3Cspan class=\"hljs-addition\">+ pathnameBase: \"/base\"\x3C/span>\n})\n\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta16\">\x3Ca href=\"#200-beta16\">
18372.0.0-beta.16\x3C/a>\x3C/h2>\n\x3Cp>New \x3Ccode>strategy\x3C/code> API. See \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/346\">https://github.com/opral/inlang-paraglide-js/issues/346\x3C/a>.\x3C/p>\n\x3Cp>You can now define your own stragegy for getting and setting a locale.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n\x3Cspan class=\"hljs-addition\">+ strategy: [\"pathname\", \"cookie\", \"baseLocale\"]\x3C/span>\n})\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta14\">\x3Ca href=\"#200-beta14\">2.0.0-beta.14\x3C/a>\x3C/h2>\n\x3Cp>Fixes windows path normalization \x3Ca href=\"https://github.com/opral/monorepo/pull/3374\">https://github.com/opral/monorepo/pull/3374\x3C/a>\x3C/p>\n\x3Ch2 id=\"200-beta13\">\x3Ca href=\"#200-beta13\">2.0.0-beta.13\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>flat compiler options\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n\x3Cspan class=\"hljs-deletion\">- compilerOptions: {\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- emitPrettierIgnore: false,\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- },\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ emitPrettierIgnore: false,\x3C/span>\n})\n\x3C/code>\x3C/pre>\n\x3Cul>\n\x3Cli>removed \x3Ccode>experimentalEmitTs\x3C/code>. the overhead of maintaing two syntaxes is too large \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/329\">https://github.com/opral/inlang-paraglide-js/issues/329\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n\x3Cspan class=\"hljs-deletion\">- experimentalEmitTs: true,\x3C/span>\n})\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta11\">\x3Ca href=\"#200-beta11\">2.0.0-beta.11\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>improve: compiler awaits ongoing compilations before starting a new one\x3C/li>\n\x3Cli>update dependency that fixes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/320\">https://github.com/opral/inlang-paraglide-js/issues/320\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta10\">\x3Ca href=\"#200-beta10\">2.0.0-beta.10\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>remove \x3Ccode>available\x3C/code> prefix from locale APIs alltogether \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2596202820\">https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2596202820\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta9\">\x3Ca href=\"#200-beta9\">2.0.0-beta.9\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>Expose compiler on the index\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-import { compile } from \"@inlang/paraglide-js/compiler\";\x3C/span>\n\x3Cspan class=\"hljs-addition\">+import { compile } from \"@inlang/paraglide-js\";\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cul>\n\x3Cli>expose paraglide compile args\x3C/li>\n\x3C/ul>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-addition\">+ import { type CompileArgs } from \"@inlang/paraglide-js\";\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"200-beta8\">\x3Ca href=\"#200-beta8\">2.0.0-beta.8\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>rename \x3Ccode>runtime.locales\x3C/code> to \x3Ccode>runtime.availableLocales\x3C/code> to align with v1 API and avoid ambiguity \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/314\">https://github.com/opral/inlang-paraglide-js/issues/314\x3C/a>\x3C/li>\n\x3Cli>remove legacy \x3Ccode>languageTag\x3C/code> APIs \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/315\">https://github.com/opral/inlang-paraglide-js/issues/315\x3C/a>\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta7\">\x3Ca href=\"#200-beta7\">2.0.0-beta.7\x3C/a>\x3C/h2>\n\x3Cul>\n\x3Cli>fixed windows path problems\x3C/li>\n\x3Cli>increased performance of the compiler by removing a redundant setTimeout\x3C/li>\n\x3Cli>increased performance of the compiler by removing prettier\x3C/li>\n\x3Cli>\x3Ccode>experimentalEmitTs\x3C/code> flag\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200-beta3\">\x3Ca href=\"#200-beta3\">2.0.0-beta.3\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-49\">\x3Ca href=\"#patch-changes-49\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>remove \x3Ccode>fast-glob\x3C/code> as dependency in favor of node's built-in \x3Ccode>fs.glob\x3C/code> (a new API in node 22)\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"200\">\x3Ca href=\"#200\">2.0.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"major-changes\">\x3Ca href=\"#major-changes\">Major changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>Upgrade to @inlang/sdk v2\x3C/li>\n\x3Cli>Support for variants (pluralization, gendering, A/B test, etc.)\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"minor-changes-25\">\x3Ca href=\"#minor-changes-25\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>1d62451: remove \x3Ccode>dedent\x3C/code> dependency in CLI\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>5d906bd: refactor: remove posthog-node dependency\x3C/p>\n\x3Cp>Posthog node has been replaced for a fetch call. Removing 3 (posthog + 2 transitive dependencies).\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>855a71c: adds \x3Ccode>experimentalEmitTsDeclarations\x3C/code> compiler option \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/288\">https://github.com/opral/inlang-paraglide-js/issues/288\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n // ...\n options: {\n\x3Cspan class=\"hljs-addition\">+ experimentalEmitTsDeclarations: true\x3C/span>\n }\n})\n\x3C/code>\x3C/pre>\n\x3Cp>Projects can now select if TypeScript declaration file should be emitted. The need for the \x3Ccode>allowJs: true\x3C/code> option in TypeScript configs becomes redundant at the cost of slower compilation times (\x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/238\">https://github.com/opral/inlang-paraglide-js/issues/238\x3C/a>).\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>346c21b: maintenance: remove path prop from tsconfig\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-\"paths\": {\x3C/span>\n\x3Cspan class=\"hljs-deletion\">- \"~/*\": [\"./src/*\"]\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-}\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>So not worth it \"nice to have\" \"but it's better DX\" thing. Breaks path resolving in JS. Vitest needed a vite config to resolve the paths because only TS knew how to resolve thep paths. Etc. Etc. Etc.\x3C/p>\n\x3C/li>\n\x3Cli>\n\x3Cp>fb06546: adds \x3Ccode>emitGitIgnore\x3C/code> and \x3Ccode>emitPrettierIgnore\x3C/code> compiler options\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/189\">https://github.com/opral/inlang-paraglide-js/issues/189\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">await compile({\n // ...\n options: {\n\x3Cspan class=\"hljs-addition\">+ emitPrettierIgnore: false\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ emitGitIgnore: false\x3C/span>\n }\n})\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3Cli>\n\x3Cp>e2b9e24: feat: expose compiler as library\x3C/p>\n\x3Cp>closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/206\">https://github.com/opral/inlang-paraglide-js/issues/206\x3C/a>\x3C/p>\n\x3Cp>The Paraglide compiler is now exposed as a library. This allows you to use and extend the compiler however you need.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-keyword\">import\x3C/span> { compile } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"@inlang/paraglide-js/compiler\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">
1837await\x3C/span> \x3Cspan class=\"hljs-title function_\">compile\x3C/span>({\n\t\x3Cspan class=\"hljs-attr\">path\x3C/span>: \x3Cspan class=\"hljs-string\">\"/path/to/project.inlang\"\x3C/span>,\n\t\x3Cspan class=\"hljs-attr\">outdir\x3C/span>: \x3Cspan class=\"hljs-string\">\"/path/to/output\"\x3C/span>,\n});\n\x3C/code>\x3C/pre>\n\x3C/li>\n\x3Cli>\n\x3Cp>44ac447: maintenance: remove vite in favor of tsc to build paraglide js lib\x3C/p>\n\x3Cp>Closes \x3Ca href=\"https://github.com/opral/inlang-paraglide-js/issues/208\">https://github.com/opral/inlang-paraglide-js/issues/208\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">- \"build\": \"vite build\",\x3C/span>\n\x3Cspan class=\"hljs-addition\">+ \"build\": \"tsc\",\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Cp>Paraglide JS used vite to build the library. This change removes vite in favor of tsc to build the library. This change is made to simplify the build process and to make it easier to maintain the library in the future.\x3C/p>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"1112\">\x3Ca href=\"#1112\">1.11.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-50\">\x3Ca href=\"#patch-changes-50\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>59c8b11: Fix Ninja recommendation and adoption if working directory is not the repo root\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"1111\">\x3Ca href=\"#1111\">1.11.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-51\">\x3Ca href=\"#patch-changes-51\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>\n\x3Cp>14d80b3: Removed the \"Which tech-stack are you using?\" prompt from the \x3Ccode>init\x3C/code> command as it was not providing any real value. All it did was link you to the appropriate documentation.\x3C/p>\n\x3Cp>From now on we rely on the docuemntation site to guide people to the correct documenation for their framework.\x3C/p>\n\x3Cul>\n\x3Cli>SvelteKit: \x3Ca href=\"https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n\">https://inlang.com/m/dxnzrydw/paraglide-sveltekit-i18n\x3C/a>\x3C/li>\n\x3Cli>NextJs: \x3Ca href=\"https://inlang.com/m/osslbuzt/paraglide-next-i18n\">https://inlang.com/m/osslbuzt/paraglide-next-i18n\x3C/a>\x3C/li>\n\x3Cli>Astro: \x3Ca href=\"https://inlang.com/m/iljlwzfs/paraglide-astro-i18n\">https://inlang.com/m/iljlwzfs/paraglide-astro-i18n\x3C/a>\x3C/li>\n\x3Cli>SolidStart: \x3Ca href=\"https://inlang.com/m/n860p17j/paraglide-solidstart-i18n\">https://inlang.com/m/n860p17j/paraglide-solidstart-i18n\x3C/a>\x3C/li>\n\x3Cli>Vite: \x3Ca href=\"https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-vite\">https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-vite\x3C/a>\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"1110\">\x3Ca href=\"#1110\">1.11.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-26\">\x3Ca href=\"#minor-changes-26\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>e37eabf: - renamed packages \x3Ccode>@inlang/cross-sell-X\x3C/code> to \x3Ccode>@inlang/recommend-X\x3C/code> be more descriptive\n\x3Cul>\n\x3Cli>refactor recommendation view in Sherlock VS Code extension\x3C/li>\n\x3Cli>introduce new \x3Ccode>shouldRecommend\x3C/code> function to \x3Ccode>@inlang/recommend-sherlock\x3C/code> & \x3Ccode>@inlang/recommend-ninja\x3C/code>\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"1101\">\x3Ca href=\"#1101\">1.10.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-52\">\x3Ca href=\"#patch-changes-52\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>c5d145d: use types from SDK for error handling\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"1100\">\x3Ca href=\"#1100\">1.10.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-27\">\x3Ca href=\"#minor-changes-27\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>33662e6: Gracefully handle errors in the Inlang Project. Only crash on errors that are fatal to paraglide specifically\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"191\">\x3Ca href=\"#191\">1.9.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-53\">\x3Ca href=\"#patch-changes-53\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b8573fa: Improved error-reporting\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"190\">\x3Ca href=\"#190\">1.9.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-28\">\x3Ca href=\"#minor-changes-28\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>eb941fe: Prompt about adding the \x3Ca href=\"https://inlang.com/m/3gk8n4n4/app-inlang-ninjaI18nAction\">Ninja\x3C/a> Github Action for translation-linting during \x3Ccode>paraglide-js init\x3C/code>. Also exposes it over the internal API.\x3C/li>\n\x3C/ul>
1837\n\x3Ch3 id=\"patch-changes-54\">\x3Ca href=\"#patch-changes-54\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>9566348: Better handling of \x3Ccode>tsconfig\x3C/code> files that \x3Ccode>extends\x3C/code> another config.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"180\">\x3Ca href=\"#180\">1.8.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-29\">\x3Ca href=\"#minor-changes-29\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>21ab0a0: Add an output mode where each message is it's own file. This enables treeshaking in less capable bundlers. Currently this is only available via the programmatic API.\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-55\">\x3Ca href=\"#patch-changes-55\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>21ab0a0: performance improvements\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"173\">\x3Ca href=\"#173\">1.7.3\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-56\">\x3Ca href=\"#patch-changes-56\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>32cbe48: Improve \x3Ccode>bestMatch\x3C/code> reliability\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"172\">\x3Ca href=\"#172\">1.7.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-57\">\x3Ca href=\"#patch-changes-57\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>6105a50: No longer log \"Exiting the Watcher\" when stopping the watching process, as it was causing annoying CMD popups on windows\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"171\">\x3Ca href=\"#171\">1.7.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-58\">\x3Ca href=\"#patch-changes-58\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>4d24188: \x3Ccode>paraglide-js init\x3C/code> now uses the \x3Ccode>createNewProject\x3C/code> API from \x3Ccode>@inlang/sdk\x3C/code> for creating new projects. This resulits in higher reliability.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"170\">\x3Ca href=\"#170\">1.7.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-30\">\x3Ca href=\"#minor-changes-30\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>0774c1a: Expose CLI programmatically to enable framework-specific init clis\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"162\">\x3Ca href=\"#162\">1.6.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-59\">\x3Ca href=\"#patch-changes-59\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>cee4692: Use index accesses instead of \x3Ccode>.at\x3C/code> function for better compatability with legacy browsers\x3C/li>\n\x3Cli>4b631aa: Update invalid type-declarations\x3C/li>\n\x3Cli>3c7a87c: Fixes a race-condition when creating the messages directory during \x3Ccode>paraglide-js init\x3C/code>\x3C/li>\n\x3Cli>ab1fe48: When initialising and a single project is available, it no longer suggests and empty string as the project path\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"161\">\x3Ca href=\"#161\">1.6.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-60\">\x3Ca href=\"#patch-changes-60\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>fa6aa31: Update internal adapter-utilities\x3C/li>\n\x3Cli>dee5aa6: Add \x3Ccode>--silent\x3C/code> option to \x3Ccode>paraglide-js compile\x3C/code> command that will only log errors\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"160\">\x3Ca href=\"#160\">1.6.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-31\">\x3Ca href=\"#minor-changes-31\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>462325b: Paraglide now ships with internal utility functions that handle common adapter tasks such as language-negotiation. These aren't public facing, but the version bump is required to make sure adapter-packages resolve the correct version of paragldie.\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"150\">\x3Ca href=\"#150\">1.5.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-32\">\x3Ca href=\"#minor-changes-32\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>2428451: \x3Ccode>paraglide-js init\x3C/code> now finds more existing projects\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"140\">\x3Ca href=\"#140\">1.4.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-33\">\x3Ca href=\"#minor-changes-33\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>d47b2aa: Generate empty \x3Ccode>messages/{lang}.js\x3C/code> files if no messages are present. This way the \"shape\" of the generated output is always the same regardless of messages\x3C/li>\n\x3C/ul>
1837\n\x3Ch3 id=\"patch-changes-61\">\x3Ca href=\"#patch-changes-61\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>192fdec: prompt the user for the \x3Ccode>outdir\x3C/code> during \x3Ccode>paraglide-js init\x3C/code>\x3C/li>\n\x3Cli>0b7c82e: Inline package-version at build time to be more robust\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"137\">\x3Ca href=\"#137\">1.3.7\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-62\">\x3Ca href=\"#patch-changes-62\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>1cc9cbc: Run compiler after \x3Ccode>paraglide-js init\x3C/code> so that initial files are present\x3C/li>\n\x3Cli>5401f95: Add \x3Ccode>--outdir\x3C/code> flag to the generated CLI commands\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"136\">\x3Ca href=\"#136\">1.3.6\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-63\">\x3Ca href=\"#patch-changes-63\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>526b0ba: \x3Ccode>paraglide-js init\x3C/code> now prompts for which languages should be supported\x3C/li>\n\x3Cli>26d2ba1: No longer add \x3Ccode>identical-pattern\x3C/code> lint rule by default\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"135\">\x3Ca href=\"#135\">1.3.5\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-64\">\x3Ca href=\"#patch-changes-64\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>7dce581: fix \x3Ccode>openRepository\x3C/code> crash in non-git environments\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"134\">\x3Ca href=\"#134\">1.3.4\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-65\">\x3Ca href=\"#patch-changes-65\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>2a42b6e: bump \x3Ccode>@lix-js/client\x3C/code> dependency\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"133\">\x3Ca href=\"#133\">1.3.3\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-66\">\x3Ca href=\"#patch-changes-66\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>11f0e18: Update dependency\x3C/li>\n\x3Cli>10e3c28: fix JSDoc annotations on message aliases\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"132\">\x3Ca href=\"#132\">1.3.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-67\">\x3Ca href=\"#patch-changes-67\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>45975c0: Fail gracefully if adding \x3Ccode>.vscode\x3C/code> folder fails\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"131\">\x3Ca href=\"#131\">1.3.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-68\">\x3Ca href=\"#patch-changes-68\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>afaaffa: Bundle \x3Ccode>@inlang/recommend-sherlock\x3C/code>. This is used to promot \x3Cem>once\x3C/em> during \x3Ccode>paraglide-js init\x3C/code> to ask if you want to install the Sherlock vscode extension\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"130\">\x3Ca href=\"#130\">1.3.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-34\">\x3Ca href=\"#minor-changes-34\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>4970afc: paraglide deprecate aliases\x3C/li>\n\x3Cli>4837297: File locking for concurrent message updates through the load/store plugin api\nAuto-generated human-IDs and aliases - only with experimental: { aliases: true }\x3C/li>\n\x3C/ul>\n\x3Ch3 id=\"patch-changes-69\">\x3Ca href=\"#patch-changes-69\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"129\">\x3Ca href=\"#129\">1.2.9\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-70\">\x3Ca href=\"#patch-changes-70\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>a99e35fee: use \x3Ccode>@inlang/recommend-sherlock\x3C/code> during vscode extension initialization\x3C/li>\n\x3Cli>Updated dependencies [a99e35fee]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"128\">\x3Ca href=\"#128\">1.2.8\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-71\">\x3Ca href=\"#patch-changes-71\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>b0f1e908b: Prompt user for tech-stack when running \x3Ccode>paraglide-js init\x3C/code> & recommend Adapters\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"127\">\x3Ca href=\"#127\">1.2.7\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-72\">\x3Ca href=\"#patch-changes-72\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>f6ec6cdc9: bump \x3Ccode>@inlang/sdk\x3C/code> dependency\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"126\">\x3Ca href=\"#126\">1.2.6\x3C/a>\x3C/h2>
1837\n\x3Ch3 id=\"patch-changes-73\">\x3Ca href=\"#patch-changes-73\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>960f8fb70: rename the vscode extension to \"Sherlock\"\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"125\">\x3Ca href=\"#125\">1.2.5\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-74\">\x3Ca href=\"#patch-changes-74\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>00f181ad3: fix broken dependency\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"124\">\x3Ca href=\"#124\">1.2.4\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-75\">\x3Ca href=\"#patch-changes-75\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>Updated dependencies [244442698]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"123\">\x3Ca href=\"#123\">1.2.3\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-76\">\x3Ca href=\"#patch-changes-76\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>4c26fa70a: bump dependencies\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"122\">\x3Ca href=\"#122\">1.2.2\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-77\">\x3Ca href=\"#patch-changes-77\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>613ef9877: fix: Bump \x3Ccode>@lix-js/client\x3C/code> dependency\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"121\">\x3Ca href=\"#121\">1.2.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-78\">\x3Ca href=\"#patch-changes-78\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>74dc1f8c6: Update dependencies\x3C/li>\n\x3Cli>4ae6295d0: Detect when \x3Ccode>paraglide-js init\x3C/code> is being run inside the VsCode terminal and skip the VsCode question if so\x3C/li>\n\x3Cli>Updated dependencies [74ac11c47]\n\x3Cul>\n\x3Cli>@inlang/[email protected]\x3C/li>\n\x3C/ul>\n\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"120\">\x3Ca href=\"#120\">1.2.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-35\">\x3Ca href=\"#minor-changes-35\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>0f0e8496d: Throw runtime error if \x3Ccode>languageTag()\x3C/code> returns a non-language tag value\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"111\">\x3Ca href=\"#111\">1.1.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"patch-changes-79\">\x3Ca href=\"#patch-changes-79\">Patch Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>7ea9753fb: Improve onboarding message\x3C/li>\n\x3Cli>4277232db: fix: better formatting of messageID fallbacks\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"110\">\x3Ca href=\"#110\">1.1.0\x3C/a>\x3C/h2>\n\x3Ch3 id=\"minor-changes-36\">\x3Ca href=\"#minor-changes-36\">Minor Changes\x3C/a>\x3C/h3>\n\x3Cul>\n\x3Cli>cd29edb11: bumbing fixed env var dependecy issue affected packages\x3C/li>\n\x3C/ul>\n\x3Ch2 id=\"100\">\x3Ca href=\"#100\">1.0.0\x3C/a>\x3C/h2>\n\x3Cp>Bump Version to 1.0 as no more breaking changes are expected.\x3C/p>\n\x3Ch2 id=\"100-prerelease26\">\x3Ca href=\"#100-prerelease26\">1.0.0-prerelease.26\x3C/a>\x3C/h2>\n\x3Cp>Hotfix: Bundle SDK\x3C/p>\n\x3Ch2 id=\"100-prerelease25\">\x3Ca href=\"#100-prerelease25\">1.0.0-prerelease.25\x3C/a>\x3C/h2>\n\x3Cp>Update dependencies\x3C/p>\n\x3Ch2 id=\"100-prerelease24\">\x3Ca href=\"#100-prerelease24\">1.0.0-prerelease.24\x3C/a>\x3C/h2>\n\x3Cp>feat: Support language Fallbacks according to BCP 47 specification\x3C/p>\n\x3Ch2 id=\"100-prerelease23\">\x3Ca href=\"#100-prerelease23\">1.0.0-prerelease.23\x3C/a>\x3C/h2>\n\x3Cp>Update dependencies\x3C/p>\n\x3Ch2 id=\"100-prerelease22\">\x3Ca href=\"#100-prerelease22\">1.0.0-prerelease.22\x3C/a>\x3C/h2>\n\x3Cp>Update dependencies\x3C/p>\n\x3Ch2 id=\"100-prerelease21\">\x3Ca href=\"#100-prerelease21\">1.0.0-prerelease.21\x3C/a>\x3C/h2>\n\x3Cp>feat: Handle variables that have invalid JS identifiers as names.\nfix: Better text escaping in the compiler.\nfix: Compiler now fails reliably when a message ID is an invalid JS identifier.\x3C/p>\n\x3Ch2 id=\"100-prerelease20\">\x3Ca href=\"#100-prerelease20\">1.0.0-prerelease.20\x3C/a>\x3C/h2>\n\x3Cp>Paraglide now checks if the messages have actually changed before recompiling. This should improve reliability and performance.\x3C/p>\n\x3Ch2 id=\"100-prerelease19\">\x3Ca href=\"#100-prerelease19\">1.0.0-prerelease.19\x3C/a>\x3C/h2>\n\x3Cp>fix: Fix inlang/internal#195\x3C/p>\n\x3Ch2 id=\"100-prerelease18\">\x3Ca href=\"#100-prerelease18\">
18371.0.0-prerelease.18\x3C/a>\x3C/h2>\n\x3Cp>\x3Ccode>paraglide-js init\x3C/code> now adds \x3Ccode>@inlang/message-lint-rule-valid-js-identifier\x3C/code> by default.\x3C/p>\n\x3Ch2 id=\"100-prerelease17\">\x3Ca href=\"#100-prerelease17\">1.0.0-prerelease.17\x3C/a>\x3C/h2>\n\x3Cp>\x3Ccode>paraglide-js init\x3C/code> now adds \x3Ccode>paraglide-js compile\x3C/code> to the postinstall script by default. This sidesteps numerous linting issues when using paraglide in CI environments.\x3C/p>\n\x3Ch2 id=\"100-prerelease16\">\x3Ca href=\"#100-prerelease16\">1.0.0-prerelease.16\x3C/a>\x3C/h2>\n\x3Cp>Fix \x3Ccode>paraglide-js compile\x3C/code> hanging for a couple seconds after successful compilation\x3C/p>\n\x3Ch2 id=\"100-prerelease15\">\x3Ca href=\"#100-prerelease15\">1.0.0-prerelease.15\x3C/a>\x3C/h2>\n\x3Cp>Fix crash when using \x3Ccode>npx @inlang/paraglide-js init\x3C/code> and selecting vscode.\x3C/p>\n\x3Ch2 id=\"100-prerelease14\">\x3Ca href=\"#100-prerelease14\">1.0.0-prerelease.14\x3C/a>\x3C/h2>\n\x3Cp>Added \x3Ccode>--watch\x3C/code> flag to the \x3Ccode>paraglide-js compile\x3C/code> command. This will keep the process alive and recompile whenever messages are changed.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-bash\">paraglide-js compile --project ./project.inlang --watch\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease13\">\x3Ca href=\"#100-prerelease13\">1.0.0-prerelease.13\x3C/a>\x3C/h2>\n\x3Cp>\x3Ccode>./paraglide/runtime.js\x3C/code> now exports a function called \x3Ccode>isAvailableLanguageTag\x3C/code>. This is\nthe recommended way to check if something is a valid language tag, while maintaining\ntype safety.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-comment\">//Pseudo code\x3C/span>\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> { isAvailableLanguageTag } \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/runtime\"\x3C/span>;\n\n\x3Cspan class=\"hljs-keyword\">if\x3C/span> (\x3Cspan class=\"hljs-title function_\">isAvailableLanguageTag\x3C/span>(params.\x3Cspan class=\"hljs-property\">
1837lang\x3C/span>)) {\n\t\x3Cspan class=\"hljs-keyword\">return\x3C/span> \x3Cspan class=\"hljs-title function_\">renderSite\x3C/span>(params.\x3Cspan class=\"hljs-property\">lang\x3C/span>);\n} \x3Cspan class=\"hljs-keyword\">else\x3C/span> {\n\t\x3Cspan class=\"hljs-keyword\">return\x3C/span> \x3Cspan class=\"hljs-number\">404\x3C/span>;\n}\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease12\">\x3Ca href=\"#100-prerelease12\">1.0.0-prerelease.12\x3C/a>\x3C/h2>\n\x3Cp>[Internal Change]\nExpose the compiler so that bundler plugins can call it programmatically instead of going through the CLI.\x3C/p>\n\x3Ch2 id=\"100-prerelease11\">\x3Ca href=\"#100-prerelease11\">1.0.0-prerelease.11\x3C/a>\x3C/h2>\n\x3Cp>\x3Ccode>onSetLanguageTag\x3C/code> no longer throws when called multiple times. Newer callbacks will overwrite old ones.\nDevelopers still should not call \x3Ccode>onSetLanguageTag\x3C/code> multiple times, this is needed for HMR to work reliably.\x3C/p>\n\x3Cp>Big thanks to \x3Ca href=\"https://github.com/KraXen72\">@KraXen72\x3C/a> for helping us find this bug.\x3C/p>\n\x3Ch2 id=\"100-prerelease10\">\x3Ca href=\"#100-prerelease10\">1.0.0-prerelease.10\x3C/a>\x3C/h2>\n\x3Cp>Add an optional options argument to message functions, to allow forcing a languageTag regardless of which languageTag is currently set.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-keyword\">import\x3C/span> * \x3Cspan class=\"hljs-keyword\">as\x3C/span> m \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/messages\"\x3C/span>;\n\x3Cspan class=\"hljs-keyword\">const\x3C/span> msg = m.\x3Cspan class=\"hljs-title function_\">hello\x3C/span>({ \x3Cspan class=\"hljs-attr\">name\x3C/span>: \x3Cspan class=\"hljs-string\">\"John\"\x3C/span> }, { \x3Cspan class=\"hljs-attr\">languageTag\x3C/span>: \x3Cspan class=\"hljs-string\">\"de\"\x3C/span> });\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease9\">\x3Ca href=\"#100-prerelease9\">1.0.0-prerelease.9\x3C/a>\x3C/h2>\n\x3Cp>The \x3Ccode>paraglide-js init\x3C/code> command now uses the \x3Ca href=\"https://inlang.com/m/reootnfj\">inlang message format\x3C/a> 2.0 which is human readable.\x3C/p>\n\x3Ch2 id=\"100-prerelease8\">\x3Ca href=\"#100-prerelease8\">1.0.0-prerelease.8\x3C/a>\x3C/h2>\n\x3Cp>IMPROVE: Paraglide now splits messages into different resource files as a step towards splitting messages by language via a bundler plugin.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-ts\">\x3Cspan class=\"hljs-keyword\">import\x3C/span> * \x3Cspan class=\"hljs-keyword\">as\x3C/span> en \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/messages/en\"\x3C/span>;\n\x3Cspan class=\"hljs-keyword\">import\x3C/span> * \x3Cspan class=\"hljs-keyword\">as\x3C/span> de \x3Cspan class=\"hljs-keyword\">from\x3C/span> \x3Cspan class=\"hljs-string\">\"./paraglide/messages/de\"\x3C/span>;\n\nen.\x3Cspan class=\"hljs-title function_\">hello\x3C/span>();\nde.\x3Cspan class=\"hljs-title function_\">hello\x3C/span>();\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease7\">\x3Ca href=\"#100-prerelease7\">1.0.0-prerelease.7\x3C/a>\x3C/h2>\n\x3Cp>FIX: type error \x3Ca href=\"https://github.com/opral/monorepo/pull/1610#issuecomment-1801768825\">https://github.com/opral/monorepo/pull/1610#issuecomment-1801768825\x3C/a>\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">export const currentLanguageTag = (params) => {\n\x3Cspan class=\"hljs-addition\">+\t/** @type {Record<string, string>} */\x3C/span>\n\tconst variants = {\n\t\ten: `The current language tag is \"${params.languageTag}\".`,\n\t\tde: `Der aktuelle Sprachtag ist \"${params.languageTag}\".`,\n\t}\n\treturn variants[languageTag()] ?? \"currentLanguageTag\"\n}\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease6\">\x3Ca href=\"#100-prerelease6\">1.0.0-prerelease.6\x3C/a>\x3C/h2>\n\x3Cp>BREAKING: Paraglide JS now compiles into source code, see \x3Ca href=\"https://github.com/opral/monorepo/issues/1607\">https://github.com/opral/monorepo/issues/1607\x3C/a>.\x3C/p>\n\x3Cp>What you need to change:\x3C/p>\n\x3Col>\n\x3Cli>Remove \x3Ccode>--namespace\x3C/code> from the compile command\x3C/li>\n\x3Cli>Replace imports from paraglide to point to the directory in ther source code:\x3C/li>\n\x3C/ol>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-diff\">\x3Cspan class=\"hljs-deletion\">-import { setLanguageTag, languageTag } from '@inlang/paraglide-js/sveltekit-example';
1837\x3C/span>\n\x3Cspan class=\"hljs-addition\">+import { setLanguageTag, languageTag } from '../../paraglide-js/runtime';\x3C/span>\n\x3Cspan class=\"hljs-deletion\">-import * as m from \"@inlang/paraglide-js/sveltekit-example/messages\"\x3C/span>\n\x3Cspan class=\"hljs-addition\">+import * as m from \"../../paraglide-js/messages\"\x3C/span>\n\x3C/code>\x3C/pre>\n\x3Ch2 id=\"100-prerelease5\">\x3Ca href=\"#100-prerelease5\">1.0.0-prerelease.5\x3C/a>\x3C/h2>\n\x3Cp>improve: \x3Ccode>paraglide-js init\x3C/code> now adds the Visual Studio Code extension (Sherlock) if vscode is used\x3C/p>\n\x3Ch2 id=\"100-prerelease4\">\x3Ca href=\"#100-prerelease4\">1.0.0-prerelease.4\x3C/a>\x3C/h2>\n\x3Cp>add: \x3Ccode>paraglide-js init\x3C/code> command which simplifies the setup process\x3C/p>\n\x3Ch2 id=\"100-prerelease3\">\x3Ca href=\"#100-prerelease3\">1.0.0-prerelease.3\x3C/a>\x3C/h2>\n\x3Cp>fix: \x3Ca href=\"https://github.com/opral/monorepo/issues/1478\">https://github.com/opral/monorepo/issues/1478\x3C/a>\x3C/p>\n\x3Ch2 id=\"100-prerelease1\">\x3Ca href=\"#100-prerelease1\">1.0.0-prerelease.1\x3C/a>\x3C/h2>\n\x3Ch3 id=\"fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports\">\x3Ca href=\"#fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports\">fix: Jetbrains based editors not detecting \x3Ccode>@inlang/paraglide-js/{namespace}/messages\x3C/code> imports\x3C/a>\x3C/h3>\n\x3Cp>The bug has been fixed by moving \x3Ccode>./*/messages\x3C/code> above the less specifc \x3Ccode>./*\x3C/code> export.\x3C/p>\n\x3Cpre data-mwc-codeblock=\"\">\x3Ccode class=\"hljs language-json\">\t\x3Cspan class=\"hljs-attr\">\"exports\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-punctuation\">{\x3C/span>\n\t\t\x3Cspan class=\"hljs-attr\">\"./*/messages\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"./dist/compiled-output/*/messages.js\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\t\t\x3Cspan class=\"hljs-attr\">\"./*\"\x3C/span>\x3Cspan class=\"hljs-punctuation\">:\x3C/span> \x3Cspan class=\"hljs-string\">\"./dist/compiled-output/*/runtime.js\"\x3C/span>\n\t\x3Cspan class=\"hljs-punctuation\">}\x3C/span>\x3Cspan class=\"hljs-punctuation\">,\x3C/span>\n\x3C/code>\x3C/pre>",rawMarkdown:"# @inlang/paraglide-js\n\n## 2.25.4\n\n### Patch Changes\n\n- afe6fdc: Fix default URL routing dropping trailing slashes when localizing or delocalizing paths. When `trailingSlash` is omitted, `/about/` now becomes `/en/about/` and `/en/about/` delocalizes to `/about/`, matching equivalent explicit URL patterns. Paths without trailing slashes and localized root behavior remain unchanged. Set `trailingSlash: \"never\"` to explicitly generate slashless URLs; `\"always\"` continues to enforce trailing slashes.\n\n## 2.25.3\n\n### Patch Changes\n\n- e1e6e61: Upgrade the inlang SDK to 3.0.6 with Lix 0.17.0.\n\n## 2.25.2\n\n### Patch Changes\n\n- b26bada: Upgrade Inlang SDK to 3.0.5 with Lix 0.16.1 to fix compilation of sorted message files above 512 tracked-state rows. Includes transaction error handling and snapshot restoration fixes.\n\n## 2.25.1\n\n### Patch Changes\n\n- 845e819: Upgrade the Inlang SDK to 3.0.4, including Lix 0.15.1 fixes for transaction-local message and variant reads.\n\n## 2.25.0\n\n### Minor Changes\n\n- f719e1f: Expose `cleanOutdir`, `experimentalStaticLocale`, and `disableAsyncLocalStorage` as `paraglide-js compile` CLI flags.\n- 5ed1745: Add support for a `paraglide.config.js` (or `.mjs`, `.ts`, `.cjs`)\n configuration file inside the inlang project directory.\n\n The CLI and all bundler plugins now pick up compiler options from\n `\x3Cproject>/paraglide.config.*`. The project directory comes from `--project`\n or the plugin's `project` option and defaults to the conventional\n `./project.inlang` â which means every bundler plugin can now be\n instantiated without arguments. Since the config lives inside the project it\n configures, it cannot set `project` itself. Explicit flags and plugin\n options win over the config file, which wins over the built-in defaults.\n Existing setups keep working unchanged.\n\n Also included:\n - A new `defineConfig` helper exported from `@inlang/paraglide-js` for type\n inference and autocompletion in config files.\n - Watch modes reload when the active config file changes, including renames\n between the supported file names. Deleting all config files falls back to\n the built-in defaults;
1837 an invalid config skips the compilation with an\n error â watch modes keep serving the previous output, production builds\n fail loudly. (esbuild does not support config watching.)\n - `cleanOutdir` is accepted but ignored: watch integrations always preserve\n the output directory for incremental compilation.\n\n### Patch Changes\n\n- aa4ffd3: Resolve references to earlier local variables correctly in message declarations and formatter options.\n- 3634877: Fix `experimentalMiddlewareLocaleSplitting` corrupting the generated server file when a compiled message value contains a literal `$` (e.g. a price or currency symbol) that forms a `String.replace()` special replacement pattern such as `` $` ``.\n- 1bacc27: Fix `experimentalMiddlewareLocaleSplitting` keying `compiledBundles` by the raw bundle id instead of the safe module id, so every SSR message lookup missed and threw `globalThis.__paraglide.ssr.\x3Cid> is not a function` on hydration.\n\n## 2.24.1\n\n### Patch Changes\n\n- d2aeb93: Update the inlang SDK dependency to 3.0.1, which includes the Lix WASM fallback for musl-based Node.js environments.\n\n## 2.24.0\n\n### Minor Changes\n\n- 7028c8a: Upgrade to `@inlang/sdk` v3 and remove obsolete local account migration code.\n\n### Patch Changes\n\n- 0ac907e: Cache compiled URL patterns to speed up repeated localized-link generation.\n- fda90d2: Skip unchanged Vite compilations across dev-server restarts by persisting and validating the compiler input cache.\n- 84e2766: Add a fast path for common locale-prefix and static-domain URL patterns while preserving the generic URLPattern fallback.\n- 5de9441: Improve compiler output writes by using Node's synchronous SHA-256 implementation and only creating directories for generated files that changed.\n- 5c17acf: Allow importing the programmatic compiler API without installing the optional Vite peer dependency.\n- c52b523: Preserve request bodies in `paraglideMiddleware` by cloning body-bearing requests before rewrapping them, preventing \"Body has already been read\" errors on POST/PUT/PATCH/DELETE.\n- 32d285b: Avoid rewriting unchanged output files during one-shot CLI compilation.\n- 9e1ee2e: Add an opt-in `trailingSlash` compiler option for canonicalizing localized URLs.\n\n## 2.23.2\n\n### Patch Changes\n\n- b8af4b1: Embed TypeScript sources in published JavaScript sourcemaps and stop emitting declaration sourcemaps that reference unpublished source files.\n\n## 2.23.1\n\n### Patch Changes\n\n- 6f9b062: Keep the server middleware's AsyncLocalStorage available when module instrumentation snapshots mutable exports.\n\n## 2.23.0\n\n### Minor Changes\n\n- c2b9c17: Replace the experimental per-locale framework-output specialization with a\n Vite 8+ environment architecture. `experimentalPerLocaleBuild: true` now\n generates locale source modules before bundling, builds independent native\n Rolldown graphs, supports unminified builds and source maps, and emits\n `paraglide-vite-locales.json` without rewriting completed chunks or framework\n output.\n\n Remove the private TanStack Start and SvelteKit renderer integrations. Those\n frameworks now require public client-variant build and render-selection APIs\n before they can compose with experimental per-locale builds.\n\n### Patch Changes\n\n- 608385f: Use `baseLocale` as the exhaustive branch in generated message functions.\n\n## 2.22.0\n\n### Minor Changes\n\n- 2571af2: Add experimental Vite 8 per-locale client builds for TanStack Start and SvelteKit. Enable the same `experimentalPerLocaleBuild: true` flag in either framework; Paraglide detects the framework and serves compiler-specialized client assets for each locale.\n\n## 2.21.0\n\n### Minor Changes\n\n- ab5bfc7: fix `emitTsDeclarations` with TypeScript 7 https://github.com/opral/paraglide-js/issues/711\n\n TypeScript 7 (the Go-based compiler) no longer ships the in-process compiler API that Paraglide used to generate `.d.ts` files, which made `paraglide-js compile --emit-ts-declarations` fail with `TypeError: Cannot read properties of undefined (reading 'ESNext')`. Paraglide now detects this and invokes TypeScript's `tsc` CLI instead. TypeScript 5 and 6 keep using the compiler API as before.\n\n Note that the declaration output of TypeScript 7 differs cosmetically from TypeScript 5/6 (quote style, declaration ordering, `export declare const` vs `export const`) but is semantically equivalent.\n\n## 2.20.2\n\n### Patch Changes\n\n- a48e767: Cache
1837client cookie locale extraction for synchronous message bursts.\n\n## 2.20.1\n\n### Patch Changes\n\n- 8c3493d: Fix server cookie locale parsing when Cookie headers omit whitespace after semicolons.\n\n## 2.20.0\n\n### Minor Changes\n\n- 2c34351: Emit `messages/package.json` with `{ \"type\": \"module\", \"sideEffects\": false }` for `message-modules` output, declaring the generated message modules side-effect-free.\n\n 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.\n\n 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\"`).\n\n See https://github.com/opral/paraglide-js/issues/668\n\n### Patch Changes\n\n- 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.\n\n## 2.19.0\n\n### Minor Changes\n\n- 67a8942: Compile pattern-level function-reference annotations to registry calls\n\n 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:\n\n ```js\n // before\n const en_views = (i) => `${i?.count} views`;\n // after\n const en_views = (i) => `${registry.number(\"en\", i?.count, {})} views`;\n ```\n\n 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.\n\n Fixes https://github.com/opral/paraglide-js/issues/694\n\n- d57efa1: Skip recompilation when input
1837s are unchanged across bundler runs in the same process\n\n `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:\n\n ```\n vite v6.4.1 building for production...\n â [paraglide-js] Compilation complete (locale-modules)\n â built in 634ms\n vite v6.4.1 building SSR bundle for production...\n â¹ [paraglide-js] Compilation skipped â inputs unchanged (locale-modules)\n â built in 15ms\n ```\n\n 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`.\n\n Also fixed along the way:\n - 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.\n - 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.\n\n Fixes https://github.com/opral/paraglide-js/issues/693\n\n### Patch Changes\n\n- 6010611: Update `@inlang/sdk` to 2.10.0.\n\n## 2.18.2\n\n### Patch Changes\n\n- 4bea31a: Prevent `paraglide-js compile --watch` from cleaning the output directory on the initial compile.\n- 4dfa099: Fix emitted TypeScript declarations for message keys that require quoted export aliases, such as dotted nested keys.\n\n `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.\n\n## 2.18.1\n\n### Patch Changes\n\n- 6eb7d02: Fix input match generation so `Infinity` selectors match both numeric `Infinity` values and string `\"Infinity\"` values.\n- c16730d: Pin default jsDelivr plugin URLs to exact versions in generated project settings.\n\n## 2.18.0\n\n### Minor Changes\n\n- 62d37f0: Add a `relativetime` declaration formatter backed by `Intl.RelativeTimeFormat`.\n\n### Patch Changes\n\n- a5f31bc: Update `@inlang/sdk` to 2.9.3.\n- d2bf729: Mark `typescript` as an optional peer dependency and show a clear error when `emitTsDeclarations` is enabled without TypeScript installed.\n- 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.\n\n## 2.17.0\n\n### Minor Changes\n\n- 109e588: Add `--output-structure` option to the compile command.\n\n## 2.16.1\n\n### Patch Changes\n\n- 3bb446a: Update `@inlang/sdk` to `2.9.2`.\n\n## 2.16.0\n\n### Minor Changes\n\n- 8401dae: Add new `paraglide-js compile` CLI flags for compiler options that were\n previously only available through the programmatic API or bundler plugins.\n\n You can now:\n - enable or disable emitted `.gitignore`, `.prettierignore`, and `README.md`\n - explicitly enable or disable emitted `.d.ts` files\n - pass a custom `isServer` expression for runtime tree-shaking\n\n These options are forwarded through regular and `--watch` compiles so the CLI\n matches the existing compiler behavior more closely.\n\n## 2.15.3\n\n### Patch Changes\n\n- b10186d: Fix numeric input match inference so generated message typings accept both numeric and string literal forms for values like `input=1`, matching runtime behavior without relying on broad loose coercion.\n\n## 2.15.2\n\n### Patch Changes\n\n- c716c6d: Fix proxy-aware URL handling in `paraglideMiddleware()`, `shouldRedirect()`, and locale extraction by adding an `effectiveRequestUrl` override for browser-facing URLs behind TLS-terminating proxies and load balancers. Addresses [#652](https://github.com/opral/paraglide-js/issues/652).\n\n## 2.15.1\n\n### Patch Changes\n\n- 2e8b5a1: Add markup documentation and message format plugin references to compiled README\n- 8964e8b: Update `@inlang/sdk` to `2.9.1`.\n\n## 2.15.0\n\n### Minor Changes\n\n- 862433c: Add `toLocale()` for case-insensitive locale normalization, make `isLocale()`\n strictly match canonical project locales, and return canonical locale values\n across runtime locale helpers.\n\n ```ts\n // configured locales: [\"fr\", \"en-US\"]\n\n isLocale(\"FR\"); // false\n toLocale(\"FR\"); // \"fr\"\n\n isLocale(\"en-us\"); // false\n toLocale(\"en-us\"); // \"en-US\"\n ```\n\n Runtime helpers that resolve locales from external input now return canonical\n project locale values as well.\n\n## 2.14.1\n\n### Patch Changes\n\n- 7d29058: Remove dead JSDoc `@import` stripping from the runtime generator.\n- 46ac447: Upgrade `@inlang/sdk` to v2.8.0.\n\n## 2.14.0\n\n### Minor Changes\n\n- 067509d: Improve generated runtime typing by centralizing shared type definitions, avoiding strict `checkJs` locale type errors, and moving middleware locale-splitting state under `globalThis.__paraglide.ssr`.\n\n### Patch Changes\n\n- a17af28: Remove stale telemetry internals that were no longer used by the CLI or compiler.\n\n## 2.13.2\n\n### Patch Changes\n\n- 2e18cc0: Fix compiler code generation for formatter option literals so Intl numeric and boolean options are emitted with the correct literal types.\n\n This resolves strict `checkJs`/`svelte-check` errors where generated `number()` options like `minimumFractionDigits` were emitted as strings and caused `Type 'string' is not assignable to type 'number'`.\n\n## 2.13.1\n\n### Patch Changes\n\n- 9d79aff: Fix single-locale message generation to avoid emitting an unused `locale` variable in strict TypeScript `checkJs` setups. This removes `TS6133` (`'locale' is declared but its value is never read`) warnings for generated message files when only one locale is configured.\n\n Add a regression type test that asserts single-locale generated messages do not produce this warning.\n\n## 2.13.0\n\n### Minor Changes\n\n- 7185902: Add a new runtime utility: `getTextDirection(locale?)`.\n - Returns `\"ltr\"` or `\"rtl\"` for a given locale.\n - Defaults to the current locale from `getLocale()` when no locale is provided.\n - Uses `Intl.Locale` text info
1837when available, with a safe RTL fallback for runtimes without that API.\n\n Also updates SvelteKit example/docs to show setting both `%lang%` and `%dir%` in `app.html` using runtime APIs.\n\n## 2.12.0\n\n### Minor Changes\n\n- af0084e: Add route-level locale strategy overrides via `routeStrategies`.\n\n You can now define per-route strategy behavior (first match wins), including:\n - `strategy` overrides for paths like `/dashboard/*` and `/rpc/*`\n - `exclude: true` to skip i18n middleware behavior for paths like `/api/*`\n\n## 2.11.0\n\n### Minor Changes\n\n- d1c86fb: Improve emitted message-module output by gating middleware locale-splitting hooks behind `experimentalMiddlewareLocaleSplitting`.\n\n When the option is disabled (default), generated message functions no longer emit:\n - `if (experimentalMiddlewareLocaleSplitting && isServer === false) { ...__paraglide.ssr... }`\n - `trackMessageCall(...)`\n - related runtime imports (`experimentalMiddlewareLocaleSplitting`, `isServer`, `trackMessageCall`)\n\n When `experimentalMiddlewareLocaleSplitting` is enabled, the existing SSR/middleware injection flow is preserved.\n\n- 90a1580: Add compiler support for markup messages with a new `message.parts()` API.\n\n Messages that contain markup now compile to framework-neutral parts (`text`, `markup-start`, `markup-end`, and `markup-standalone`) while `message()` continues to return plain strings.\n\n## 2.10.0\n\n### Minor Changes\n\n- fc66ee1: Add type-safe literal unions for match variants in generated message typings https://github.com/opral/paraglide-js/issues/538.\n\n For example, the following minimal message definition:\n\n ```json\n {\n \t\"auth_password_error\": [\n \t\t{\n \t\t\t\"match\": {\n \t\t\t\t\"type=empty\": \"You must provide a password\"\n \t\t\t}\n \t\t}\n \t]\n }\n ```\n\n Before:\n\n ```ts\n m.auth_password_error({ type: \"typo\" }); // â
OK (typed as NonNullable\x3Cunknown>)\n ```\n\n After:\n\n ```ts\n m.auth_password_error({ type: \"typo\" }); // ð¥ Type error\n ```\n\n## 2.9.1\n\n### Patch Changes\n\n- c43effb: Update `@inlang/sdk` to v2.6.2, which removes a file queue settlement that could prevent the compiler from exiting in some environments. See https://github.com/opral/paraglide-js/issues/598.\n\n## 2.9.0\n\n### Minor Changes\n\n- badca6a: Add the experimental `experimentalStaticLocale` compiler option for per-locale tree-shaking (see https://github.com/opral/paraglide-js/issues/88#issuecomment-3634754638).\n- a0c5665: Prune async_hooks import from generated server output when async local storage is disabled (fixes https://github.com/opral/paraglide-js/issues/539).\n\n### Patch Changes\n\n- 9ae2381: Add `@see` documentation links to runtime and server APIs, making it easier for developers to find relevant documentation directly from their IDE.\n- 867ea44: Avoid cyclic fallback maps when a language-only locale exists alongside a regional base locale.\n\n Previously, a setup like `locales: [\"it\", \"it-IT\"]` with `baseLocale: \"it-IT\"` could create a fallback cycle (`it â it-IT â it`) and throw a runtime error. The compiler now breaks that cycle by making the `baseLocale` terminal, so `it-IT` no longer falls back to `it` while `it` still falls back to `it-IT`.\n\n Issue: https://github.com/opral/paraglide-js/issues/544\n\n- 3cbdd75: Fix message compilation for input names with non-identifier characters (like `half!`).\n\n Before: i18next-style placeholders with symbols produced invalid JS because we emitted `i.half!` in patterns, local variables, and match conditions (syntax error).\n Now: Paraglide quotes the key in JSDoc and uses bracket access in generated code (e.g. `i[\"half!\"]`), so the same message compiles and runs correctly.\n\n ```diff\n -// before (invalid JS)\n -// input: { \"half!\": \"1st\" }\n -return `${i.half!} Half - Corner Handicap`\n +// after (valid JS)\n +// input: { \"half!\": \"1st\" }\n +return `${i[\"half!\"]} Half - Corner Handicap`\n ```\n\n Issue: https://github.com/opral/paraglide-js/issues/514\n\n- deb9877: Avoid locale/message name collisions in the locale-modules output structure by prefixing locale imports.\n\n Previously, a locale like `no` could collide with a message
1837key `no`, causing duplicate symbol errors in the generated `messages/_index.js`.\n Now, locale imports are prefixed (e.g. `__no`), keeping message exports intact and avoiding the conflict.\n\n Issue: https://github.com/opral/paraglide-js/issues/492\n\n## 2.8.0\n\n### Minor Changes\n\n- 07e17c0: Emit a `README.md` in the compiled output to help LLMs understand the generated code. The README includes usage examples, runtime API documentation, and links to further resources. Can be disabled with `emitReadme: false`.\n- 991c314: Improve watch mode to monitor directories so newly added translation files trigger recompiles in the CLI and bundler plugin.\n- 4a75259: Update inlang SDK to v2.6.0 with improved project structure and forward-compatibility.\n\n **New `.meta.json` file in inlang projects:**\n\n The SDK now writes a `.meta.json` file to track which SDK version last modified the project. This enables safe forward migrations and prevents accidental downgrades when switching between SDK versions.\n\n ```\n project.inlang/\n settings.json\n README.md\n .gitignore\n .meta.json \x3C-- new\n ```\n\n **Updated `.gitignore` handling:**\n\n Inlang projects now manage their own `.gitignore` that ignores everything except `settings.json`. If you see the `.gitignore` file inside your `.inlang` project folder showing up as changed in git, run these commands to fix it:\n\n ```bash\n # Remove the tracked .gitignore from git's index\n git rm --cached '**/*.inlang/.gitignore'\n\n # Commit the change\n git commit -m \"fix: remove tracked .gitignore from inlang project\"\n ```\n\n This is a one-time fix. The inlang SDK handles the `.gitignore` automatically starting with v2.5.\n\n### Patch Changes\n\n- ec7f3e3: Add a `--watch` flag to the CLI `compile` command to recompile on changes.\n- be10228: Strip sourcemap references from generated runtime and server outputs to avoid missing map warnings. (https://github.com/opral/paraglide-js/issues/581)\n- e75e2a3: Add documentation for avoiding redirect loops with frameworks that handle URL localization themselves (e.g., TanStack Router).\n - Added JSDoc example in `paraglideMiddleware()` explaining when to use the original request vs the modified request\n - Added troubleshooting section in SSR docs explaining the redirect loop issue and solution\n - Updated TanStack Start example README with an important callout about using the original request\n\n## 2.7.2\n\n### Patch Changes\n\n- 983d893: Added a defensive try catch request cloning in `paraglideMiddleware` for runtimes with custom `Request` wrappers (TanStack Start 1.143+: https://github.com/TanStack/router/issues/6089, https://github.com/opral/paraglide-js/issues/573).\n\n## 2.7.1\n\n### Patch Changes\n\n- update `@inlang/sdk` to `2.4.10` which contains a fix for dynamically loading plugins in bun https://github.com/opral/monorepo/pull/3787.\n\n## 2.7.0\n\n### Minor Changes\n\n- Add an opt-in `emitTsDeclarations` compiler flag to generate `.d.ts` files for the compiled output.\n\n This is useful when `allowJs: true` cannot be set in your `tsconfig.json` (e.g., due to project constraints or conflicting compiler options).\n\n **Usage:**\n\n ```ts\n // vite.config.ts\n import { defineConfig } from \"vite\";\n import { paraglideVitePlugin } from \"@inlang/paraglide-js\";\n\n export default defineConfig({\n \tplugins: [\n \t\tparaglideVitePlugin({\n \t\t\tproject: \"./project.inlang\",\n \t\t\toutdir: \"./src/paraglide\",\n \t\t\temitTsDeclarations: true,\n \t\t}),\n \t],\n });\n ```\n\n Or via CLI:\n\n ```bash\n paraglide compile --project ./project.inlang --outdir ./src/paraglide --emitTsDeclarations\n ```\n\n **Note:** Enabling this option reduces compiler speed because TypeScript needs to generate declaration files for all output modules.\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/566\n Closes https://github.com/opral/inlang-paraglide-js/issues/238\n Closes https://github.com/opral/inlang-paraglide-js/issues/160\n\n Example output (locale-modules):\n\n ```diff\n src/paraglide/\n messages/\n _index.js\n + _index.d.ts\n de.js\n + de.d.ts\n en.js\n + en.d.ts\n messages.js\n + messages.d.ts\n ```\n\n## 2.6.0\n\n### Minor Changes\n\n- 3d6259c: Add `LocalizedString` branded type for compile-time i18n safety.\n\n Message functions now return `LocalizedString` instead of `string`, enabling TypeScript users to distinguish between translated and untranslated strings at compile time. This is fully backward compatible since branded types are assignable to their base type.\n\n ```typescript\n import { m } from \"./paraglide/messages.js\";\n import type { LocalizedString } from \"@inlang/paraglide-js\";\n\n const greeting: LocalizedString = m.hello(); // â Type-safe\n const raw: LocalizedString = \"Hello\"; // â Type error\n ```\n\n- 4bde3eb: Add optional chaining to compiled message inputs so missing inputs no longer throw at runtime; include tests covering single- and multi-variant messages.\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/568\n\n Example:\n\n ```js\n // compiled translation\n export const greeting = (i) => `Hello ${i?.name}`;\n\n // TypeScript still enforces the input shape; this is purely runtime safety (handy in dev).\n greeting(); // no throw, returns \"Hello undefined\"\n greeting({ name: \"Ada\" }); // \"Hello Ada\"\n\n // previously (boom ð¥)\n export const greetingOld = (i) => `Hello ${i.name}`;\n greetingOld(); // TypeError: Cannot read properties of undefined (reading 'name')\n ```\n\n## 2.5.0\n\n- 72d1c53: Ensure the CLI honours allowJs flags defined in extended or referenced tsconfig files instead of prompting unnecessarily.\n\n Refs https://github.com/opral/inlang-paraglide-js/issues/560.\n\n- c59da26: fix: make locale matching case-insensitive\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/549\n\n This fixes an issue that locales containing uppercase characters like `pt-BR` failed to load when using `extractLocaleFromNavigator` or `extractLocaleFromHeader`.\n\n The issue occurred because these functions converted locales to lowercase, while the comparison logic inside `assertIsLocale` and `isLocale` wasn't case-sensitive.\n\n List of changes:\n - Ensured locale comparisons in `assertIsLocale()` and `isLocale()` are fully case-insensitive.\n - Made `assertIsLocale()` return the canonical-cased locale from `locales` instead of the raw input.\n - Added new test coverage for case-insensitive behavior in `assertIsLocale()` and `isLocale()`.\n\n- 9735b82: Fix fallback assignment generation so locale chains emit dependencies first and avoid \"Block-scoped variable used before its declaration\" errors. See https://github.com/opral/inlang-paraglide-js/issues/507 for details.\n\n## 2.4.0\n\n### Minor Changes\n\n- 4111ee6: Add an isomorphic `shouldRedirect()` helper shared by the middleware and client routers, improve redirect typing, and document the new API in the URL strategy guide.\n\n### Patch Changes\n\n- 4a48c07: fix: fix eslint incorrectly linting generated files\n\n closes https://github.com/opral/inlang-paraglide-js/issues/558\n\n eslint ignores single-line 'eslint-disable' comments at the start of a file.\n Using a block comment without a closing one instead will prompt eslint to ignore it.\n\n ```diff\n -\toutput[filename] = `// eslint-disable\\n${content}`;\n +\toutput[filename] = `/* eslint-disable */\\n${content}`;\n ```\n\n- 4c8921f: Fixes `overwriteSetLocale` to keep the full `(locale, options?)` signature when overriding `setLocale`, preventing TypeScript from rejecting calls that pass `{ reload: false }`. Adds a regression test ensuring custom handlers receive the options object.\n- Updated dependencies [7791be7]\n - @inlang/[email protected]\n\n## 2.3.2\n\n### Patch Changes\n\n- 4ea9e7a: fix: ensure that async custom setLocale funcs resolve with reload: false\n\n## 2.3.1\n\n### Patch Changes\n\n- 090964b: fix(runtime/set-locale.js): ensure reload waits for async custom setLocale funcs https://github.com/opral/monorepo/pull/3692\n\n## 2.3.0\n\n### Minor Changes\n\n- bfe8518: Crash the build process (for example during `vite build`) if paraglide can't compile the project.\n- Removed local account loading which suddenly led to crashes for some users.\n\n## 2.2.0\n\n### Minor Changes\n\n- 69ac911: Add support for async custom server strategies with `extractLocaleFromRequestAsync`\n\n This change introduces a new `extractLocaleFromRequestAsync` function that supports asynchronous custom server strategies, enabling use cases like fetching user locale preferences from databases.\n\n ## What's Changed\n - **New Function**: Added `extractLocaleFromRequestAsync` that supports async custom server strategies\n - **Middleware Update**: Server middleware now uses the async version to support async custom strategies\n - **Breaking Change**: The synchronous `extractLocaleFromRequest` no longer supports custom server strategies\n - **Improved Documentation**: Added comprehensive examples and usage guidance\n\n ## Migration Guide\n\n ### For users with custom server strategies:\n\n **Before:**\n\n ```js\n // This no longer works in sync ver
1837sion\n defineCustomServerStrategy(\"custom-database\", {\n \tgetLocale: async (request) => {\n \t\treturn await getUserLocaleFromDatabase(request);\n \t},\n });\n\n const locale = extractLocaleFromRequest(request); // Won't call async custom strategies\n ```\n\n **After:**\n\n ```js\n // Use the async version for custom strategies\n defineCustomServerStrategy(\"custom-database\", {\n \tgetLocale: async (request) => {\n \t\treturn await getUserLocaleFromDatabase(request);\n \t},\n });\n\n const locale = await extractLocaleFromRequestAsync(request); // Supports async custom strategies\n ```\n\n ### For users calling `extractLocaleFromRequest` directly:\n\n If you're using `extractLocaleFromRequest` directly in your code without custom strategies, no changes are needed. For custom server strategies, switch to `extractLocaleFromRequestAsync`.\n\n The server middleware automatically uses the async version, so no changes are needed for standard middleware usage.\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/527\n\n### Patch Changes\n\n- 5589e30: (likely) fix: handler is of type `unknown` ts error https://github.com/opral/inlang-paraglide-js/issues/529\n- 3712f09: Fix cookieDomain default behavior for better server/client cookie compatibility.\n\n When `cookieDomain` is undefined or empty, cookies are now set without a domain attribute, scoping them to the exact current domain only (no subdomains). This fixes compatibility issues with server-side cookies that don't include a domain attribute.\n\n **Before**:\n\n ```js\n // When cookieDomain was undefined, cookies were set as:\n document.cookie =\n \t\"PARAGLIDE_LOCALE=en; path=/; max-age=34560000; domain=example.com\";\n // This made cookies available to subdomains\n ```\n\n **After**:\n\n ```js\n // When cookieDomain is undefined, cookies are now set as:\n document.cookie = \"PARAGLIDE_LOCALE=en; path=/; max-age=34560000\";\n // This scopes cookies to the exact current domain only\n ```\n\n **Migration**:\n - If you want the previous behavior (subdomain sharing), explicitly set `cookieDomain` in your configuration:\n\n ```diff\n paraglideWebpackPlugin({\n project: './project.inlang',\n outdir: \"./src/paraglide\",\n + cookieDomain: 'example.com'\n })\n ```\n\n## 2.1.0\n\n### Minor Changes\n\n- 4255bd5: Provide functions for getting the preferred language on server and client.\n\n This defines two new functions for getting the preferred language:\n - `extractLocaleFromHeader`: Extracts the locale from the accept-language header on the server.\n - `extractLocaleFromNavigator`: Extracts the locale from the navigator.languages array on the client.\n\n The code was already present in the `@inlang/paraglide-js` package, but it was not exported. Now it is exported so that\n it can be used in custom strategies.\n\n- dc287f1: Implement custom strategy concept for locale resolution.\n\n This introduces a new way to define custom locale resolution strategies alongside built-in strategies. Custom strategies provide a cleaner, more composable approach compared to overwriting `getLocale()` and `setLocale()` functions directly.\n\n **New APIs:**\n - `defineCustomClientStrategy()`: Define custom strategies for client-side locale resolution\n - `defineCustomServerStrategy()`: Define custom strategies for server-side locale resolution\n\n **Key features:**\n - Custom strategies must follow the pattern `custom-\x3Cname>` where `\x3Cname>` contains only alphanumeric characters\n - Can be combined with built-in strategies in the strategy array\n - Respect strategy order for fallback handling\n - Support both client and server environments\n - Provide better error isolation and type safety\n\n **Usage example:**\n\n ```js\n import { defineCustomClientStrategy } from \"./paraglide/runtime.js\";\n\n defineCustomClientStrategy(\"custom-sessionStorage\", {\n \tgetLocale: () => sessionStorage.getItem(\"user-locale\") ?? undefined,\n \tsetLocale: (locale) => sessionStorage.setItem(\"user-locale\", locale),\n });\n ```\n\n Then include in your strategy configuration:\n\n ```js\n compile({\n \tstrategy: [\"custom-sessionStorage\", \"cookie\", \"baseLocale\"],\n });\n ```\n\n### Patch Changes\n\n- 4c0b997: perf(paraglide): improve bundle size by removing message id fallback for fully translated messages\n- 9621803: Add Vary: Accept-Language header when preferredLanguage strategy is used\n\n Paraglide middleware now automatically sets the `Vary: Accept-Language` header when performing redirects based on the `preferredLanguage` strategy. This indicates to clients (CDN cache, crawlers, etc.) that the response will be different depending on the `Accept-Language` header, ensuring proper caching behavior and SEO compliance.\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/522\n\n- Updated dependencies [22089a2]\n - @inlang/[email protected]\n\n## 2.0.13\n\n### Patch Changes\n\n- 688c7c8: Add support for callbacks in server middleware\n- 635861b: `extractLocaleFromUrl()` now uses a cache for the last value.\n\n Useful on the client-side where the same URL is being extracted many times for each message on a given page.\n\n## 2.0.12\n\n### Patch Changes\n\n- 31337ba: expose `createParaglide()`\n- Updated dependencies [56acb22]\n - @inlang/[email protected]\n\n## 2.0.11\n\n### Patch Changes\n\n- de0439f: Add domain property to cookie options.\n\n ```diff\n paraglideVitePlugin({\n project: './project.inlang',\n outdir: \"./src/paraglide\",\n + cookieDomain: 'example.com'\n }),\n ```\n\n## 2.0.10\n\n### Patch Changes\n\n- d16e853: fix: [2.0.8] Adds extra \\*/ in generated .js files https://github.com/opral/inlang-paraglide-js/issues/493\n\n## 2.0.9\n\n### Patch Changes\n\n- Updated dependencies [bd2c366]\n - @inlang/[email protected]\n\n## 2.0.8\n\n### Patch Changes\n\n- 5258af0: fix: compiling message bundles with case sensitive ids for the locale module output https://github.com/opral/inlang-paraglide-js/issues/490\n\n Case sensitive ids led to duplicate exports in the locale module output. This has been fixed by adjusting the `toSafeModuleId()` used by the compiler internally to append a number of uppercase characters to de-duplicate the ids.\n\n ```diff\n toSafeModuleId(\"helloworld\")\n \"helloworld\"\n\n toSafeModuleId(\"helloWorld\")\n - \"helloworld\"\n + \"helloworld1\"\n ```\n\n## 2.0.7\n\n### Patch Changes\n\n- 48931f5: make `output-structure: locale-modules` the default for dev builds https://github.com/opral/inlang-paraglide-js/issues/486\n- Updated dependencies [49a7880]\n - @inlang/[email protected]\n\n## 2.0.6\n\n### Patch Changes\n\n- 3fa27c0: fix: duplicate (case sensitive) message
1837keys leading to compile error when using `output-structure: locale-modules`. closes https://github.com/opral/inlang-paraglide-js/issues/487\n- 02c2d34: improve: compiler should log warnings when plugins can not be imported\n- Updated dependencies [083ff1f]\n - @inlang/[email protected]\n\n## 2.0.5\n\n### Patch Changes\n\n- 698b9a9: add `cookieMaxAge` option to compiler and runtime\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/483\n - Introduced `cookieMaxAge` option to `CompilerOptions`, allowing configuration of cookie expiration time.\n - Adjusted tests to verify `max-age` in cookies.\n\n## 2.0.4\n\n### Patch Changes\n\n- @inlang/[email protected]\n\n## 2.0.3\n\n### Patch Changes\n\n- cf404e0: improve: handle duplicate inputs https://github.com/opral/inlang-paraglide-js/issues/479\n\n## 2.0.2\n\n### Patch Changes\n\n- a6c43ea: fix: error handling in paraglideMiddleware breaks SvelteKit features that rely on errors being thrown\n\n## 2.0.1\n\n### Patch Changes\n\n- b906c0c: fix: window undefined bug in webpack\n - @inlang/[email protected]\n\n## Paraglide JS 2.0 ð\n\nParaglide JS 2.0 had three main goals which have all been achieved:\n\n1. Use the new inlang SDK v2 which supports variants [#201](https://github.com/opral/inlang-paraglide-js/issues/201).\n2. Unify the API across any framework [#217](https://github.com/opral/inlang-paraglide-js/issues/217).\n3. Support any i18n strategy (cookie, url, domain, session, etc).\n\n- ð **Variants (pluralization) are now supported** [docs](https://paraglidejs.com/variants)\n- ð **No more adapters or providers are needed** (!)\n- ð£ï¸ **Any strategy (url, cookie, local storage) is now supported** [docs](https://paraglidejs.com/strategy)\n\nIn addition, Paraglide JS 2.0 comes with:\n\n- ð **Nested message keys** are now supported (most requested feature!)\n- ⨠**Auto-imports** when writing `m.` (no more manual `import * as m`)\n- ð **Arbitrary key names** including emojis via `m[\"ð\"]()`\n- ð **Incremental migration** to Paraglide JS is now possible\n- ðï¸ **Multi-tenancy support** for domain-based routing\n- ð§ **Exposing the compiler API** for advanced workflows\n- ð£ï¸ **Configurable routing strategies** (URL, cookie, domain, etc)\n- 𧪠**Experimental per-locale splitting** for decreasing bundle sizes\n- ð **Framework-agnostic server middleware** for SSR (SvelteKit, Next.js, etc)\n\n### Highlights\n\n#### Interactive benchmark\n\nCheck out the [benchmark](https://paraglidejs.com/benchmark) to see how Paraglide JS compares to other libraries like i18next.\n\n[](https://paraglidejs.com/benchmark)\n\n#### No more adapters are needed\n\n```diff\n- @inlang/paraglide-sveltekit\n- @inlang/paraglide-next\n+ // No more adapters are needed\n```\n\n#### ð Framework-Agnostic Server Middleware\n\nDocs are [here](https://paraglidejs.com/server-side-rendering)\n\n- **New**: Universal `paraglideMiddleware()` works in any SSR framework\n- **Built-in**: Automatic locale redirects when user preference detected\n\n```ts\n// SvelteKit example - same pattern works for Next.js, Astro, etc.\nimport { paraglideMiddleware } from \"./paraglide/server.js\";\n\nexport const handle = ({ event, resolve }) => {\n\treturn paraglideMiddleware(event.request, () => resolve(event));\n};\n```\n\n#### ð£ï¸ Configurable Routing Strategies\n\nRead more about strategies on the [docs](https://paraglidejs.com/strategy).\n\nLiterally anything is now possible. URL-based, domain-based, path-based, cookie-based, etc.\n\n```js\nparaglide({\n\tstrategy: [\n \"url\",\n \"cookie\",\n \"preferredLanguage\",\n \"...\"\n ],\n}),\n```\n\n#### ð§ Exposing the compiler API\n\n- **New**: Direct compiler access for advanced workflows\n- **Why**: Enable CI/CD pipelines and custom tooling\n- **Benefit**: Full control over compilation timing/caching\n\n```ts\n// New programmatic API\nimport { compile } from \"@inlang/paraglide-js\";\n\nawait compile({\n\tproject: \"./project.inlang\",\n\toutdir: \"./src/paraglide\",\n});\n```\n\n#### ð Arbitrary key names\n\n- **New**: Arbitrary key names including emojis via `m[\"ð\"]()\n- **Why**: Enable nesting of messages\n- **Benefit**: More expressive and fun translations\n\n```ts\n// Paraglide
18371.0\nm.some_message(); // â
Works\nm.nested.message(); // ð¥ Error\n\n// Paraglide 2.0\nm.some_message(); // â
Works\nm[\"nested.message\"](); // â
Works\n\n// Even emojis are supported\nm[\"ð\"]();\n```\n\n#### ð Incrementally migrating to Paraglide JS\n\nParaglide JS 2.0 can load multiple [translation file formats](https://paraglidejs.com/file-formats). As such, you can incrementally migrate to Paraglide JS with existing translation file formats.\n\n```js\n// In this example, Paraglide JS compiles i18next translation files\n// which enables using both i18next and Paraglide JS.\n\nimport i18next from \"i18next\";\nimport { m } from \"./paraglide/messages.js\";\n\nconsole.log(i18next.t(\"greeting\", { name: \"World\" }));\nconsole.log(m.greeting({ name: \"World\" }));\n```\n\n#### ðï¸ Multi-tenancy support\n\nParaglide JS 2.0 supports multi-tenant applications. Read more about it [here](https://paraglidejs.com/multi-tenancy).\n\n```\n# Domain-based with sub-locale\ncustomer1.fr/about â French (default)\ncustomer1.fr/en/about â English version\n\n# Domain-based with root locale\ncustomer2.com/about â English (default)\ncustomer2.com/fr/about â French version\n\n# Path-based for any domain\nexample.com/en/about â English\nexample.com/fr/about â French\napp.example.com/en/about â English\napp.example.com/fr/about â French\n```\n\n### Migrating breaking changes\n\nIf problems arise, please refer to the framework-specific getting started guide:\n\n- [SvelteKit](https://paraglidejs.com/sveltekit)\n- [Next.js](https://paraglidejs.com/next-js)\n- [Astro](https://paraglidejs.com/astro)\n- [Vite](https://paraglidejs.com/vite)\n- [React Router](https://paraglidejs.com/react-router)\n\n#### `LanguageTag` got renamed to `locale`\n\nTo align with industry standards, we renamed `LanguageTag` to `locale`.\n\n```diff\n-languageTag()\n+getLocale()\n-setLanguageTag()\n+setLocale()\n-availableLanguageTags\n+locales\n```\n\n#### Remove adapters `@inlang/paraglide-*` from your dependencies\n\n````diff\n// package.json\n{\n \"dependencies\": {\n- \"@inlang/paraglide-sveltekit\": \"^1.0.0\",\n- \"@inlang/paraglide-next\": \"^1.0.0\",\n- \"@inlang/paraglide-astro\": \"^1.0.0\",\n- \"@inlang/paraglide-vite\": \"^1.0.0\",\n+ \"@inlang/paraglide-js\": \"^2.0.0\",\n }\n}\n```\n\n### Replace adapter bundler plugins\n\n```diff\n// vite.config.js\n-import { paraglide } from \"@inlang/paraglide-vite\";\n+import { paraglideVitePlugin } from \"@inlang/paraglide-js\";\n\n\nexport default defineConfig({\n\tplugins: [\n-\t\tparaglide({\n+\t\tparaglideVitePlugin({\n\t\t\tproject: \"./project.inlang\",\n\t\t\toutdir: \"./src/paraglide\",\n\t\t}),\n\t],\n});\n\n````\n\n#### Remove Paraglide Providers\n\nParaglide JS 2.0 no longer requires providers.\n\n```diff\n// app.tsx, layout.svelte, etc.\n-import { ParaglideProvider } from \"@inlang/paraglide-{framework}\";\n\nfunction App() {\n return (\n- \x3CParaglideProvider>\n \x3CYourApp />\n- \x3C/ParaglideProvider>\n )\n}\n```\n\n#### Shorten key names longer than 255 characters\n\nParaglide JS 2.0 build output now defaults to [message-modules](https://paraglidejs.com/compiler-options#outputstructure) to improve tree-shaking. Some filesystem's limitations require key names to be shorter than 255 characters.\n\nUpvote [#423](https://github.com/opral/inlang-paraglide-js/issues/423) to remove this limitation.\n\n```diff\n- m.this_is_a_very_long_key_name_that_should_be_shortened()\n+ m.shortened_key_name()\n```\n\n#### Changing the locale requires a reload\n\nChanging the locale works via `setLocale()` in any framework now.\n\nIf you used an adapter in v1 like the SvelteKit one, this behavior is new. The new behaviour leads to a page reload. The reload is a deliberate design decision. Reloading the site eliminates the need for providers, adapters, and API differences between frameworks. Furthermore, optimizations like per-locale splitting is expected to be easier to implement.\n\nRead https://github.com/opral/inlang-paraglide-js/issues/438#issuecomment-2703733096 for more information.\n\n```diff\n-\x3Ca href=\"/de\">
1837Deutsch\x3C/a>\n+\x3Cbutton onclick=\"setLocale('de')\">Deutsch\x3C/button>\n```\n\n#### Lint rules were deprecated\n\nRemove lint rules from your project modules.\n\nWe want to re-introduce lint rules in a better form in the future. Please upvote the [#239 lix validation rules](https://github.com/opral/lix-sdk/issues/239) proposal.\n\n```diff\nmodules: [\n- \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js\",\n-\t \"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js\"\n ...\n]\n\n```\n\n#### `localizeHref()` is now required\n\nSome Paraglide adapters used AST transforms to automatically transform `\x3Ca>` into localized links. That led to many bugs and edge cases. The AST transforms were removed for v2.\n\n```diff\n-\x3Ca href=\"/page\">\x3C/a>\n+\x3Ca href={localizeHref(\"/page\")}\n```\n\n## 2.0.0-beta.31 (released as 2.0.0)\n\n- feat: New API: `createParaglide()`\n\n The function allows a no build step or before build step access to Paraglide's compiled APIs.\n\n ```typescript\n const project = await fs.readFile(\"./project.inlang\");\n\n const paraglide = await createParaglideModule({\n \tproject,\n \tcompilerOptions: {\n \t\tstrategy: [\"url\"],\n \t},\n });\n\n // Use runtime functions\n paraglide.localizeUrl(\"https://example.com\", { locale: \"de\" });\n\n // Use server middleware\n app.use(paraglide.paraglideMiddleware());\n ```\n\n- fix: `getLocale` returns correct value on SvelteKit server [#461](https://github.com/opral/inlang-paraglide-js/issues/461)\n\n- fix: Prevent redirect loops by normalizing URLs with trailing slashes [#408](https://github.com/opral/inlang-paraglide-js/issues/408)\n\n- fix: Support for explicit port numbers in URL patterns\n\n- improve: Better error handling in server middleware\n\n## 2.0.0-beta.30\n\n- improve: if no url pattern matches, `localizeUrl()` and `deLocalizeUrl()` will return the input url unchanged instead of throwing an error [#452](https://github.com/opral/inlang-paraglide-js/issues/452#issuecomment-2715761308)\n\n- improve: make AsyncLocalStorage tree-shakable by moving `disableAsyncLocalStorage` into the compiler options [#424](https://github.com/opral/inlang-paraglide-js/issues/424#issuecomment-2711453627)\n\n```diff\n- serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })\n+ serverMiddleware(req, resolve)\n\nparaglideVitePlugin({\n // ...\n+ disableAsyncLocalStorage: true\n})\n\n```\n\n- improve: allow fall through. enables partially localized patterns and thereby eases adoption.\n\n## 2.0.0-beta.29\n\n- fix [#455 setLocale and getLocale call each other in a loop](https://github.com/opral/inlang-paraglide-js/issues/455)\n\n- fix [#454 Adapt config to the new localized param of beta.28](https://github.com/opral/inlang-paraglide-js/issues/454)\n\n## 2.0.0-beta.28\n\n### BREAKING update to the URLPattern API\n\nhttps://github.com/opral/monorepo/pull/3485\n\nThe `localizedNamedGroups` and `deLocalizedNamedGroups` API has been replaced with a tuple-based `localized` array to:\n\n- enable translated pathnames in any combination\n- make the API more intuitive\n\n#### Migration Guide:\n\n**Refer to the updated documentation [here](https://paraglidejs.com/strategy#url).**\n\nBefore\n\n```json\n{\n\t\"pattern\": \"https://:domain(.*)/:locale(de|fr)?/:path*\",\n\t\"deLocalizedNamedGroups\": { \"locale\": null },\n\t\"localizedNamedGroups\": {\n\t\t\"en\": { \"locale\": null },\n\t\t\"fr\": { \"locale\": \"fr\" },\n\t\t\"de\": { \"locale\": \"de\" }\n\t}\n}\n```\n\nAfter\n\n```json\n{\n \"pattern\": \"https://:domain(.*)/:path*\",\n \"localized\": [\n [\"fr\", \"https://:domain(.*)/fr/:path*\"],\n [\"de\", \"https://:domain(.*)/de/:path*\"]\n [\"en\", \"https://:domain(.*)/:path*\"],\n ]\n}\n```\n\n### other changes\n\n- improve: fallback to `typeof window` in vite [#445](https://github.com/opral/inlang-paraglide-js/issues/445)\n\n- make `setLocale()` set all strategies. Setting all strategies aligns with user expectations and ensures that server APIs can receive the cookie of the client, for example. [#439](https://github.com/opral/inlang-paraglide-js/issues/439)\n\n- new `generateStaticLocalizedUrls()` API [#443](https://github.com/opral/inlang-paraglide-js/issues/433)\n\n```diff\nconst localizedUrls = generateStaticLocalizedUrls([\n \"/example\",\n \"/page/blog\",\n \"/123/hello\"\n])\n\nconsole.log(localizedUrls.map(url => url.pathnames))\n>> /de/example\n>> /fr/example\n>> ...\n```\n\n## 2.0.0-beta.27\n\n- fix wrong matching in API requests [#427](https://github.com/opral/inlang-paraglide-js/issues/427)\n\nParaglide JS is no longer extracting the locale from API requests for the `url` strategy because that can lead to unwanted re-directs. To get the right locale in API requests, at least add the `baseLocale` strategy to your options.\n\n```diff\n-strategy: [\"url\"]\n+strategy: [\"url\", \"cookie\", \"baseLocale\"]\n```\n\n- consolidated `message-modules` output into a single file [#434](https://github.com/opral/inlang-paraglide-js/issues/434) to severaly improve scalability\n\n- `experimentalMiddlewareLocaleSplitting` option https://github.com/opral/inlang-paraglide-js/issues/425#issuecomment-2692351073\n\n- fix [setLocale() triggers re-loads if the same locale is set](https://github.com/opral/inlang-paraglide-js/issues/430)\n\n- fix [serverMiddleware() throws when cookie contains invali
1837d locale](https://github.com/opral/inlang-paraglide-js/issues/442)\n\n- add `localStorage` strategy [#431](https://github.com/opral/inlang-paraglide-js/issues/431)\n\n- fix url strategy with optional locale always resoles base locale [#436](https://github.com/opral/inlang-paraglide-js/issues/436)\n\n## 2.0.0-beta.26\n\n- replace `node:crypto` with the Web Crypto API https://github.com/opral/inlang-paraglide-js/issues/424\n\n## 2.0.0-beta.25\n\n- added optional localized groups\n- keeps hashes, etc. in the URL when localizing https://github.com/opral/monorepo/pull/3452\n- fixes the multi-variant return\n\n## 2.0.0-beta.24\n\n- changes the redirect status from `302` to `307` https://github.com/opral/inlang-paraglide-js/issues/416\n- adds a `cleanOutdir` option which defaults to true https://github.com/opral/inlang-paraglide-js/issues/420\n- adds a `machine-translate` command if desired on init\n\n## 2.0.0-beta.23\n\nRenames and splits the `serverMiddleware()` into a dedicated `server.js` file to avoid bundler issues.\n\n```diff\n- import { serverMiddleware } from \"./paraglide/runtime.js\";\n+ import { paraglideMiddleware } from \"./paraglide/server.js\";\n```\n\n## 2.0.0-beta.22\n\n- fix `serverMiddleware()` only imports async_hooks on the server\n- add `serverMiddleware(req, resolve, { disableAsyncLocalStorage: true })` to disable async local storage\n- fix `serverMiddleware()` throws in next js when `url` strategy is not used https://github.com/opral/inlang-paraglide-js/issues/411#issuecomment-2683530533\n\n## 2.0.0-beta.21\n\n- compile arbitrary message keys https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2680006131\n- only polyfills `URLPattern` if needed https://github.com/opral/inlang-paraglide-js/issues/381\n- don't include `url` strategy by default https://github.com/opral/inlang-paraglide-js/issues/405\n- fixes webpack watch mode https://github.com/opral/inlang-paraglide-js/issues/406\n\n## 2.0.0-beta.20\n\n- automatic re-directs in `serverMiddleware()` https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2675823651\n- various bug fixes and improvements\n\n## 2.0.0-beta.19\n\nNO MORE ADAPTERS NEEDED.\n\nIf you have code from an adapter, remove it and follow the examples in the documentation. https://paraglidejs.com/sveltekit\n\n```diff\n-@inlang/paraglide-sveltekit\n-@inlang/paraglide-next\n-@inlang/paraglide-astro\n```\n\n- introduced `serverMiddleware()` https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2673375348\n\n- rename `defineGetLocale()` and `defineSetLocale()` to `overwriteGetLocale()` and `overwriteSetLocale()` https://github.com/opral/inlang-paraglide-js/issues/382\n\n- enables `import { m } from \"./paraglide/messages.js\"` for auto imports https://github.com/opral/inlang-paraglide-js/issues/345\n\n- adds the `strategy` compiler option to the cli https://github.com/opral/inlang-paraglide-js/issues/316\n\n## 2.0.0-beta.18\n\nAdded URLPatterns as a replacement for the beta 17 pathnames API.\n\nThe URLPattern API is extremly powerful. You can express base paths, translated pathnames, domain based localization, and even multi-tenancy.\n\nRead the docs [here](https://paraglidejs.com/strategy#url) and make PRs to improve the documentation.\n\n```diff\nawait compile({\n- strategy: [\"pathname\"],\n+ strategy: [\"url\"],\n})\n```\n\nThe `localizePath()` API had to be replaced by a new `localizeHref()` API. Please give feedback on the new API in [#380](https://github.com/opral/inlang-paraglide-js/issues/380)\n\n```diff\n- \x3Ca href={localizePath(\"/about\")}>About\x3C/a>\n+ \x3Ca href={localizeHref(\"/about\")}>About\x3C/a>\n```\n\n## 2.0.0-beta.17\n\nAdd support for `pathnames` API https://github.com/opral/inlang-paraglide-js/issues/359\n\nYou can now create whatever pathname pattern you want. The syntax is provided by https://github.com/pillarjs/path-to-regexp.\n\n```diff\nawait compile({\n strategy: [\"pathname\", \"cookie\", \"baseLocale\"],\n+ pathnames: {\n+ \"{*path}\": {\n+ \"de\": \"/de{/*path}\",\n+ \"en\": \"/en{/*path}\",\n}\n}\n})\n```\n\nAdd support for `pathnameBase` https://github.com/opral/inlang-paraglide-js/issues/362\n\n```diff\nawait compile({\n strategy: [\"pathname\", \"cookie\", \"baseLocale\"],\n+ pathnameBase: \"/base\"\n}
1837)\n\n```\n\n## 2.0.0-beta.16\n\nNew `strategy` API. See https://github.com/opral/inlang-paraglide-js/issues/346.\n\nYou can now define your own stragegy for getting and setting a locale.\n\n```diff\nawait compile({\n+ strategy: [\"pathname\", \"cookie\", \"baseLocale\"]\n})\n```\n\n## 2.0.0-beta.14\n\nFixes windows path normalization https://github.com/opral/monorepo/pull/3374\n\n## 2.0.0-beta.13\n\n- flat compiler options\n\n```diff\nawait compile({\n- compilerOptions: {\n- emitPrettierIgnore: false,\n- },\n+ emitPrettierIgnore: false,\n})\n```\n\n- removed `experimentalEmitTs`. the overhead of maintaing two syntaxes is too large https://github.com/opral/inlang-paraglide-js/issues/329\n\n```diff\nawait compile({\n- experimentalEmitTs: true,\n})\n```\n\n## 2.0.0-beta.11\n\n- improve: compiler awaits ongoing compilations before starting a new one\n- update dependency that fixes https://github.com/opral/inlang-paraglide-js/issues/320\n\n## 2.0.0-beta.10\n\n- remove `available` prefix from locale APIs alltogether https://github.com/opral/inlang-paraglide-js/issues/201#issuecomment-2596202820\n\n## 2.0.0-beta.9\n\n- Expose compiler on the index\n\n```diff\n-import { compile } from \"@inlang/paraglide-js/compiler\";\n+import { compile } from \"@inlang/paraglide-js\";\n```\n\n- expose paraglide compile args\n\n```diff\n+ import { type CompileArgs } from \"@inlang/paraglide-js\";\n```\n\n## 2.0.0-beta.8\n\n- rename `runtime.locales` to `runtime.availableLocales` to align with v1 API and avoid ambiguity https://github.com/opral/inlang-paraglide-js/issues/314\n- remove legacy `languageTag` APIs https://github.com/opral/inlang-paraglide-js/issues/315\n\n## 2.0.0-beta.7\n\n- fixed windows path problems\n- increased performance of the compiler by removing a redundant setTimeout\n- increased performance of the compiler by removing prettier\n- `experimentalEmitTs` flag\n\n## 2.0.0-beta.3\n\n### Patch Changes\n\n- remove `fast-glob` as dependency in favor of node's built-in `fs.glob` (a new API in node 22)\n\n## 2.0.0\n\n### Major changes\n\n- Upgrade to @inlang/sdk v2\n- Support for variants (pluralization, gendering, A/B test, etc.)\n\n### Minor Changes\n\n- 1d62451: remove `dedent` dependency in CLI\n- 5d906bd: refactor: remove posthog-node dependency\n\n Posthog node has been replaced for a fetch call. Removing 3 (posthog + 2 transitive dependencies).\n\n- 855a71c: adds `experimentalEmitTsDeclarations` compiler option https://github.com/opral/inlang-paraglide-js/issues/288\n\n ```diff\n await compile({\n // ...\n options: {\n + experimentalEmitTsDeclarations: true\n }\n })\n ```\n\n Projects can now select if TypeScript declaration file should be emitted. The need for the `allowJs: true` option in TypeScript configs becomes redundant at the cost of slower compilation times (https://github.com/opral/inlang-paraglide-js/issues/238).\n\n- 346c21b: maintenance: remove path prop from tsconfig\n\n ```diff\n -\"paths\": {\n - \"~/*\": [\"./src/*\"]\n -}\n ```\n\n So not worth it \"nice to have\" \"but it's better DX\" thing. Breaks path resolving in JS. Vitest needed a vite config to resolve the paths because only TS knew how to resolve thep paths. Etc. Etc. Etc.\n\n- fb06546: adds `emitGitIgnore` and `emitPrettierIgnore` compiler options\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/189\n\n ```diff\n await compile({\n // ...\n options: {\n + emitPrettierIgnore: false\n + emitGitIgnore: false\n }\n })\n ```\n\n- e2b9e24: feat: expose compiler as library\n\n closes https://github.com/opral/inlang-paraglide-js/issues/206\n\n The Paraglide compiler is now exposed as a library. This allows you to use and extend the compiler however you need.\n\n ```ts\n import { compile } from \"@inlang/paraglide-js/compiler\";\n\n await compile({\n \tpath: \"/path/to/project.inlang\",\n \toutdir: \"/path/to/output\",\n });\n ```\n\n- 44ac447: maintenance: remove vite in favor of tsc to build paraglide js lib\n\n Closes https://github.com/opral/inlang-paraglide-js/issues/208\n\n ```diff\n - \"build\": \"vite build\",\n + \"build\": \"tsc\",\n ```\n\n Paraglide JS used vite to build the library. This change removes vite in favor of tsc to build the library. This change is made to simplify the build process and to make it easier to maintain the library in the future.\n\n## 1.11.2\n\n### Patch Changes\n\n- 59c8b11: Fix Ninja recommendation and adoption if working directory is not the repo root\n\n## 1.11.1\n\n### Patch Changes\n\n- 14d80b3: Removed the \"Which tech-stack are you using?\" prompt from the `init` command as it was not providing any real value. All it did was link you to the appropriate documentation.\n\n From now on we rely on the docuemntation site to guide people to the correct documenation for their framework.\n - SvelteKit: https://inlang.com/m/d
1837xnzrydw/paraglide-sveltekit-i18n\n - NextJs: https://inlang.com/m/osslbuzt/paraglide-next-i18n\n - Astro: https://inlang.com/m/iljlwzfs/paraglide-astro-i18n\n - SolidStart: https://inlang.com/m/n860p17j/paraglide-solidstart-i18n\n - Vite: https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-vite\n\n## 1.11.0\n\n### Minor Changes\n\n- e37eabf: - renamed packages `@inlang/cross-sell-X` to `@inlang/recommend-X` be more descriptive\n - refactor recommendation view in Sherlock VS Code extension\n - introduce new `shouldRecommend` function to `@inlang/recommend-sherlock` & `@inlang/recommend-ninja`\n\n## 1.10.1\n\n### Patch Changes\n\n- c5d145d: use types from SDK for error handling\n\n## 1.10.0\n\n### Minor Changes\n\n- 33662e6: Gracefully handle errors in the Inlang Project. Only crash on errors that are fatal to paraglide specifically\n\n## 1.9.1\n\n### Patch Changes\n\n- b8573fa: Improved error-reporting\n\n## 1.9.0\n\n### Minor Changes\n\n- eb941fe: Prompt about adding the [Ninja](https://inlang.com/m/3gk8n4n4/app-inlang-ninjaI18nAction) Github Action for translation-linting during `paraglide-js init`. Also exposes it over the internal API.\n\n### Patch Changes\n\n- 9566348: Better handling of `tsconfig` files that `extends` another config.\n\n## 1.8.0\n\n### Minor Changes\n\n- 21ab0a0: Add an output mode where each message is it's own file. This enables treeshaking in less capable bundlers. Currently this is only available via the programmatic API.\n\n### Patch Changes\n\n- 21ab0a0: performance improvements\n\n## 1.7.3\n\n### Patch Changes\n\n- 32cbe48: Improve `bestMatch` reliability\n\n## 1.7.2\n\n### Patch Changes\n\n- 6105a50: No longer log \"Exiting the Watcher\" when stopping the watching process, as it was causing annoying CMD popups on windows\n\n## 1.7.1\n\n### Patch Changes\n\n- 4d24188: `paraglide-js init` now uses the `createNewProject` API from `@inlang/sdk` for creating new projects. This resulits in higher reliability.\n\n## 1.7.0\n\n### Minor Changes\n\n- 0774c1a: Expose CLI programmatically to enable framework-specific init clis\n\n## 1.6.2\n\n### Patch Changes\n\n- cee4692: Use index accesses instead of `.at` function for better compatability with legacy browsers\n- 4b631aa: Update invalid type-declarations\n- 3c7a87c: Fixes a race-condition when creating the messages directory during `paraglide-js init`\n- ab1fe48: When initialising and a single project is available, it no longer suggests and empty string as the project path\n\n## 1.6.1\n\n### Patch Changes\n\n- fa6aa31: Update internal adapter-utilities\n- dee5aa6: Add `--silent` option to `paraglide-js compile` command that will only log errors\n\n## 1.6.0\n\n### Minor Changes\n\n- 462325b: Paraglide now ships with internal utility functions that handle common adapter tasks such as language-negotiation. These aren't public facing, but the version bump is required to make sure adapter-packages resolve the correct version of paragldie.\n\n## 1.5.0\n\n### Minor Changes\n\n- 2428451: `paraglide-js init` now finds more existing projects\n\n## 1.4.0\n\n### Minor Changes\n\n- d47b2aa: Generate empty `messages/{lang}.js` files if no messages are present. This way the \"shape\" of the generated output is always the same regardless of messages\n\n### Patch Changes\n\n- 192fdec: prompt the user for the `outdir` during `paraglide-js init`\n- 0b7c82e: Inline package-version at build time to be more robust\n\n## 1.3.7\n\n### Patch Changes\n\n- 1cc9cbc: Run compiler after `paraglide-js init` so that initial files are present\n- 5401f95: Add `--outdir` flag to the generated CLI commands\n\n## 1.3.6\n\n### Patch Changes\n\n- 526b0ba: `paraglide-js init` now prompts for which languages should be supported\n- 26d2ba1: No longer add `identical-pattern` lint rule by default\n\n## 1.3.5\n\n### Patch Changes\n\n- 7dce581: fix `openRepository` crash in non-git environments\n\n## 1.3.4\n\n### Patch Changes\n\n- 2a42b6e: bump `@lix-js/client` dependency\n\n## 1.3.3\n\n### Patch Changes\n\n- 11f0e18: Update dependency\n- 10e3c28: fix JSDoc annotations on message aliases\n\n## 1.3.2\n\n### Patch Changes\n\n- 45975c0: Fail gracefully if adding `.vscode` folder fails\n\n## 1.3.1\n\n### Patch Changes\n\n- afaaffa: Bundle `@inlang/recommend-sherlock`. This is used to promot _once_ during `paraglide-js init` to ask if you want to install the Sherlock vscode extension\n\n## 1.3.0\n\n### Minor Changes\n\n- 4970afc: paraglide deprecate aliases\n- 4837297: File locking for concurrent message updates through the load/store plugin api\n Auto-generated human-IDs and aliases - only with experimental: { aliases: true }\n\n### Patch Changes\n\n- @inlang/[email protected]\n\n## 1.2.9\n\n### Patch Changes\n\n- a99e35fee: use `@inlang/recommend-sherlock` during vscode extension initialization\n- Updated dependencies [a99e35fee]\n - @inlang/[email protected]\n\n## 1.2.8\n\n### Patch Changes\n\n- b0f1e908b: Prompt user for tech-stack when running `paraglide-js init` & recommend Adapters\n\n## 1.2.7\n\n### Patch Changes\n\n- f6ec6cdc9: bump `@inlang/sdk` dependency\n\n## 1.2.6\n\n### Patch Changes\n\n- 960f8fb70: rename the vscode extension to \"Sherlock\"\n\n## 1.2.5\n\n### Patch Changes\n\n- 00f181ad3: fix broken depen
1837dency\n\n## 1.2.4\n\n### Patch Changes\n\n- Updated dependencies [244442698]\n - @inlang/[email protected]\n\n## 1.2.3\n\n### Patch Changes\n\n- 4c26fa70a: bump dependencies\n\n## 1.2.2\n\n### Patch Changes\n\n- 613ef9877: fix: Bump `@lix-js/client` dependency\n\n## 1.2.1\n\n### Patch Changes\n\n- 74dc1f8c6: Update dependencies\n- 4ae6295d0: Detect when `paraglide-js init` is being run inside the VsCode terminal and skip the VsCode question if so\n- Updated dependencies [74ac11c47]\n - @inlang/[email protected]\n\n## 1.2.0\n\n### Minor Changes\n\n- 0f0e8496d: Throw runtime error if `languageTag()` returns a non-language tag value\n\n## 1.1.1\n\n### Patch Changes\n\n- 7ea9753fb: Improve onboarding message\n- 4277232db: fix: better formatting of messageID fallbacks\n\n## 1.1.0\n\n### Minor Changes\n\n- cd29edb11: bumbing fixed env var dependecy issue affected packages\n\n## 1.0.0\n\nBump Version to 1.0 as no more breaking changes are expected.\n\n## 1.0.0-prerelease.26\n\nHotfix: Bundle SDK\n\n## 1.0.0-prerelease.25\n\nUpdate dependencies\n\n## 1.0.0-prerelease.24\n\nfeat: Support language Fallbacks according to BCP 47 specification\n\n## 1.0.0-prerelease.23\n\nUpdate dependencies\n\n## 1.0.0-prerelease.22\n\nUpdate dependencies\n\n## 1.0.0-prerelease.21\n\nfeat: Handle variables that have invalid JS identifiers as names.\nfix: Better text escaping in the compiler.\nfix: Compiler now fails reliably when a message ID is an invalid JS identifier.\n\n## 1.0.0-prerelease.20\n\nParaglide now checks if the messages have actually changed before recompiling. This should improve reliability and performance.\n\n## 1.0.0-prerelease.19\n\nfix: Fix inlang/internal#195\n\n## 1.0.0-prerelease.18\n\n`paraglide-js init` now adds `@inlang/message-lint-rule-valid-js-identifier` by default.\n\n## 1.0.0-prerelease.17\n\n`paraglide-js init` now adds `paraglide-js compile` to the postinstall script by default. This sidesteps numerous linting issues when using paraglide in CI environments.\n\n## 1.0.0-prerelease.16\n\nFix `paraglide-js compile` hanging for a couple seconds after successful compilation\n\n## 1.0.0-prerelease.15\n\nFix crash when using `npx @inlang/paraglide-js init` and selecting vscode.\n\n## 1.0.0-prerelease.14\n\nAdded `--watch` flag to the `paraglide-js compile` command. This will keep the process alive and recompile whenever messages are changed.\n\n```bash\nparaglide-js compile --project ./project.inlang --watch\n```\n\n## 1.0.0-prerelease.13\n\n`./paraglide/runtime.js` now exports a function called `isAvailableLanguageTag`. This is\nthe recommended way to check if something is a valid language tag, while maintaining\ntype safety.\n\n```ts\n//Pseudo code\nimport { isAvailableLanguageTag } from \"./paraglide/runtime\";\n\nif (isAvailableLanguageTag(params.lang)) {\n\treturn renderSite(params.lang);\n} else {\n\treturn 404;\n}\n```\n\n## 1.0.0-prerelease.12\n\n[Internal Change]\nExpose the compiler so that bundler plugins can call it programmatically instead of going through the CLI.\n\n## 1.0.0-prerelease.11\n\n`onSetLanguageTag` no longer throws when called multiple times. Newer callbacks will overwrite old ones.\nDevelopers still should not call `onSetLanguageTag` multiple times, this is needed for HMR to work reliably.\n\nBig thanks to [@KraXen72](https://github.com/KraXen72) for helping us find this bug.\n\n## 1.0.0-prerelease.10\n\nAdd an optional options argument to message functions, to allow forcing a languageTag regardless of which languageTag is currently set.\n\n```ts\nimport * as m from \"./paraglide/messages\";\nconst msg = m.hello({ name: \"John\" }, { languageTag: \"de\" });\n```\n\n## 1.0.0-prerelease.9\n\nThe `paraglide-js init` command now uses the [inlang message format](https://inlang.com/m/reootnfj) 2.0 which is human readable.\n\n## 1.0.0-prerelease.8\n\nIMPROVE: Paraglide now splits messages into different resource files as a step towards splitting messages by language via a bundler plugin.\n\n```ts\nimport * as en from \"./paraglide/messages/en\";\nimport * as de from \"./paraglide/messages/de\";\n\nen.hello();\nde.hello();\n```\n\n## 1.0.0-prerelease.7\n\nFIX: type error https://github.com/opral/monorepo/pull/1610#issuecomment-1801768825\n\n```diff\nexport const currentLanguageTag = (params) => {\n+\t/** @type {Record\x3Cstring, string>} */\n\tconst variants = {\n\t\ten: `The current language tag is \"${params.languageTag}\".`,\n\t\tde: `Der aktuelle Sprachtag ist \"${params.languageTag}\".`,\n\t}
1837\n\treturn variants[languageTag()] ?? \"currentLanguageTag\"\n}\n```\n\n## 1.0.0-prerelease.6\n\nBREAKING: Paraglide JS now compiles into source code, see https://github.com/opral/monorepo/issues/1607.\n\nWhat you need to change:\n\n1. Remove `--namespace` from the compile command\n2. Replace imports from paraglide to point to the directory in ther source code:\n\n```diff\n-import { setLanguageTag, languageTag } from '@inlang/paraglide-js/sveltekit-example';\n+import { setLanguageTag, languageTag } from '../../paraglide-js/runtime';\n-import * as m from \"@inlang/paraglide-js/sveltekit-example/messages\"\n+import * as m from \"../../paraglide-js/messages\"\n```\n\n## 1.0.0-prerelease.5\n\nimprove: `paraglide-js init` now adds the Visual Studio Code extension (Sherlock) if vscode is used\n\n## 1.0.0-prerelease.4\n\nadd: `paraglide-js init` command which simplifies the setup process\n\n## 1.0.0-prerelease.3\n\nfix: https://github.com/opral/monorepo/issues/1478\n\n## 1.0.0-prerelease.1\n\n### fix: Jetbrains based editors not detecting `@inlang/paraglide-js/{namespace}/messages` imports\n\nThe bug has been fixed by moving `./*/messages` above the less specifc `./*` export.\n\n```json\n\t\"exports\": {\n\t\t\"./*/messages\": \"./dist/compiled-output/*/messages.js\",\n\t\t\"./*\": \"./dist/compiled-output/*/runtime.js\"\n\t},\n```\n",frontmatter:$R[14]={},pagePath:"/changelog",source:"./CHANGELOG.md",editUrl:"https://github.com/opral/paraglide-js/blob/main/CHANGELOG.md",imports:void 0,headings:$R[15]=[$R[16]={id:"inlangparaglide-js",text:"@inlang/paraglide-js",level:1},$R[17]={id:"2254",text:"2.25.4",level:2},$R[18]={id:"patch-changes",text:"Patch Changes",level:3},$R[19]={id:"2253",text:"2.25.3",level:2},$R[20]={id:"patch-changes-2",text:"Patch Changes",level:3},$R[21]={id:"2252",text:"2.25.2",level:2},$R[22]={id:"patch-changes-3",text:"Patch Changes",level:3},$R[23]={id:"2251",text:"2.25.1",level:2},$R[24]={id:"patch-changes-4",text:"Patch Changes",level:3},$R[25]={id:"2250",text:"2.25.0",level:2},$R[26]={id:"minor-changes",text:"Minor Changes",level:3},$R[27]={id:"patch-changes-5",text:"Patch Changes",level:3},$R[28]={id:"2241",text:"2.24.1",level:2},$R[29]={id:"patch-changes-6",text:"Patch Changes",level:3},$R[30]={id:"2240",text:"2.24.0",level:2},$R[31]={id:"minor-changes-2",text:"Minor Changes",level:3},$R[32]={id:"patch-changes-7",text:"Patch Changes",level:3},$R[33]={id:"2232",text:"2.23.2",level:2},$R[34]={id:"patch-changes-8",text:"Patch Changes",level:3},$R[35]={id:"2231",text:"2.23.1",level:2},$R[36]={id:"patch-changes-9",text:"Patch Changes",level:3},$R[37]={id:"2230",text:"2.23.0",level:2},$R[38]={id:"minor-changes-3",text:"Minor Changes",level:3},$R[39]={id:"patch-changes-10",text:"Patch Changes",level:3},$R[40]={id:"2220",text:"2.22.0",level:2},$R[41]={id:"minor-changes-4",text:"Minor Changes",level:3},$R[42]={id:"2210",text:"2.21.0",level:2},$R[43]={id:"minor-changes-5",text:"Minor Changes",level:3},$R[44]={id:"2202",text:"2.20.2",level:2},$R[45]={id:"patch-changes-11",text:"Patch Changes",level:3},$R[46]={id:"2201",text:"2.20.1",level:2},$R[47]={id:"patch-changes-12",text:"Patch Changes",level:3},$R[48]={id:"2200",text:"2.20.0",level:2},$R[49]={id:"minor-changes-6",text:"Minor Changes",level:3},$R[50]={id:"patch-changes-13",text:"Patch Changes",level:3},$R[51]={id:"2190",text:"2.19.0",level:2},$R[52]={id:"minor-changes-7",text:"Minor Changes",level:3},$R[53]={id:"patch-changes-14",text:"Patch Changes",level:3},$R[54]={id:"2182",text:"2.18.2",level:2},$R[55]={id:"patch-changes-15",text:"Patch Changes",level:3},$R[56]={id:"2181",text:"2.18.1",level:2},$R[57]={id:"patch-changes-16",text:"Patch Changes",level:3},$R[58]={id:"2180",text:"2.18.0",level:2},$R[59]={id:"minor-changes-8",text:"Minor Changes",level:3},$R[60]={id:"patch-changes-17",text:"Patch Changes",level:3},$R[61]={id:"2170",text:"2.17.0",level:2},$R[62]={id:"minor-changes-9",text:"Minor Changes",level:3},$R[63]={id:"2161",text:"2.16.1",level:2},$R[64]={id:"patch-changes-18",text:"Patch Changes",level:3},$R[65]={id:"2160",text:"2.16.0",level:2},$R[66]={id:"minor-changes-10",text:"Minor Changes",level:3},$R[67]={id:"2153",text:"2.15.3",level:2}
1837,$R[68]={id:"patch-changes-19",text:"Patch Changes",level:3},$R[69]={id:"2152",text:"2.15.2",level:2},$R[70]={id:"patch-changes-20",text:"Patch Changes",level:3},$R[71]={id:"2151",text:"2.15.1",level:2},$R[72]={id:"patch-changes-21",text:"Patch Changes",level:3},$R[73]={id:"2150",text:"2.15.0",level:2},$R[74]={id:"minor-changes-11",text:"Minor Changes",level:3},$R[75]={id:"2141",text:"2.14.1",level:2},$R[76]={id:"patch-changes-22",text:"Patch Changes",level:3},$R[77]={id:"2140",text:"2.14.0",level:2},$R[78]={id:"minor-changes-12",text:"Minor Changes",level:3},$R[79]={id:"patch-changes-23",text:"Patch Changes",level:3},$R[80]={id:"2132",text:"2.13.2",level:2},$R[81]={id:"patch-changes-24",text:"Patch Changes",level:3},$R[82]={id:"2131",text:"2.13.1",level:2},$R[83]={id:"patch-changes-25",text:"Patch Changes",level:3},$R[84]={id:"2130",text:"2.13.0",level:2},$R[85]={id:"minor-changes-13",text:"Minor Changes",level:3},$R[86]={id:"2120",text:"2.12.0",level:2},$R[87]={id:"minor-changes-14",text:"Minor Changes",level:3},$R[88]={id:"2110",text:"2.11.0",level:2},$R[89]={id:"minor-changes-15",text:"Minor Changes",level:3},$R[90]={id:"2100",text:"2.10.0",level:2},$R[91]={id:"minor-changes-16",text:"Minor Changes",level:3},$R[92]={id:"291",text:"2.9.1",level:2},$R[93]={id:"patch-changes-26",text:"Patch Changes",level:3},$R[94]={id:"290",text:"2.9.0",level:2},$R[95]={id:"minor-changes-17",text:"Minor Changes",level:3},$R[96]={id:"patch-changes-27",text:"Patch Changes",level:3},$R[97]={id:"280",text:"2.8.0",level:2},$R[98]={id:"minor-changes-18",text:"Minor Changes",level:3},$R[99]={id:"patch-changes-28",text:"Patch Changes",level:3},$R[100]={id:"272",text:"2.7.2",level:2},$R[101]={id:"patch-changes-29",text:"Patch Changes",level:3},$R[102]={id:"271",text:"2.7.1",level:2},$R[103]={id:"patch-changes-30",text:"Patch Changes",level:3},$R[104]={id:"270",text:"2.7.0",level:2},$R[105]={id:"minor-changes-19",text:"Minor Changes",level:3},$R[106]={id:"260",text:"2.6.0",level:2},$R[107]={id:"minor-changes-20",text:"Minor Changes",level:3},$R[108]={id:"250",text:"2.5.0",level:2},$R[109]={id:"240",text:"2.4.0",level:2},$R[110]={id:"minor-changes-21",text:"Minor Changes",level:3},$R[111]={id:"patch-changes-31",text:"Patch Changes",level:3},$R[112]={id:"232",text:"2.3.2",level:2},$R[113]={id:"patch-changes-32",text:"Patch Changes",level:3},$R[114]={id:"231",text:"2.3.1",level:2},$R[115]={id:"patch-changes-33",text:"Patch Changes",level:3},$R[116]={id:"230",text:"2.3.0",level:2},$R[117]={id:"minor-changes-22",text:"Minor Changes",level:3},$R[118]={id:"220",text:"2.2.0",level:2},$R[119]={id:"minor-changes-23",text:"Minor Changes",level:3},$R[120]={id:"whats-changed",text:"What's Changed",level:2},$R[121]={id:"migration-guide",text:"Migration Guide",level:2},$R[122]={id:"for-users-with-custom-server-strategies",text:"For users with custom server strategies:",level:3},$R[123]={id:"for-users-calling-extractlocalefromrequest-directly",text:"For users calling extractLocaleFromRequest directly:",level:3},$R[124]={id:"patch-changes-34",text:"Patch Changes",level:3},$R[125]={id:"210",text:"2.1.0",level:2},$R[126]={id:"minor-changes-24",text:"Minor Changes",level:3},$R[127]={id:"patch-changes-35",text:"Patch Changes",level:3},$R[128]={id:"2013",text:"2.0.13",level:2},$R[129]={id:"patch-changes-36",text:"Patch Changes",level:3},$R[130]={id:"2012",text:"2.0.12",level:2},$R[131]={id:"patch-changes-37",text:"Patch Changes",level:3},$R[132]={id:"2011",text:"2.0.11",level:2},$R[133]={id:"patch-changes-38",text:"Patch Changes",level:3},$R[134]={id:"2010",text:"2.0.10",level:2},$R[135]={id:"patch-changes-39",text:"Patch Changes",level:3},$R[136]={id:"209",text:"2.0.9",level:2},$R[137]={id:"patch-changes-40",text:"Patch Changes",level:3},$R[138]={id:"208",text:"2.0.8",level:2},$R[139]={id:"patch-changes-41",text:"Patch Changes",level:3},$R[140]={id:"207",text:"2.0.7",level:2},$R[141]={id:"patch-changes-42",text:"Patch Changes",level:3},$R[142]={id:"206",text:"2.0.6",level:2},$R[143]={id:"patch-changes-43",text:"Patch Changes",level:3},$R[144]={id:"205",text:"2.0.5",level:2}
1837,$R[145]={id:"patch-changes-44",text:"Patch Changes",level:3},$R[146]={id:"204",text:"2.0.4",level:2},$R[147]={id:"patch-changes-45",text:"Patch Changes",level:3},$R[148]={id:"203",text:"2.0.3",level:2},$R[149]={id:"patch-changes-46",text:"Patch Changes",level:3},$R[150]={id:"202",text:"2.0.2",level:2},$R[151]={id:"patch-changes-47",text:"Patch Changes",level:3},$R[152]={id:"201",text:"2.0.1",level:2},$R[153]={id:"patch-changes-48",text:"Patch Changes",level:3},$R[154]={id:"paraglide-js-20-ð",text:"Paraglide JS 2.0 ð",level:2},$R[155]={id:"highlights",text:"Highlights",level:3},$R[156]={id:"migrating-breaking-changes",text:"Migrating breaking changes",level:3},$R[157]={id:"200-beta31-released-as-200",text:"2.0.0-beta.31 (released as 2.0.0)",level:2},$R[158]={id:"200-beta30",text:"2.0.0-beta.30",level:2},$R[159]={id:"200-beta29",text:"2.0.0-beta.29",level:2},$R[160]={id:"200-beta28",text:"2.0.0-beta.28",level:2},$R[161]={id:"breaking-update-to-the-urlpattern-api",text:"BREAKING update to the URLPattern API",level:3},$R[162]={id:"other-changes",text:"other changes",level:3},$R[163]={id:"200-beta27",text:"2.0.0-beta.27",level:2},$R[164]={id:"200-beta26",text:"2.0.0-beta.26",level:2},$R[165]={id:"200-beta25",text:"2.0.0-beta.25",level:2},$R[166]={id:"200-beta24",text:"2.0.0-beta.24",level:2},$R[167]={id:"200-beta23",text:"2.0.0-beta.23",level:2},$R[168]={id:"200-beta22",text:"2.0.0-beta.22",level:2},$R[169]={id:"200-beta21",text:"2.0.0-beta.21",level:2},$R[170]={id:"200-beta20",text:"2.0.0-beta.20",level:2},$R[171]={id:"200-beta19",text:"2.0.0-beta.19",level:2},$R[172]={id:"200-beta18",text:"2.0.0-beta.18",level:2},$R[173]={id:"200-beta17",text:"2.0.0-beta.17",level:2},$R[174]={id:"200-beta16",text:"2.0.0-beta.16",level:2},$R[175]={id:"200-beta14",text:"2.0.0-beta.14",level:2},$R[176]={id:"200-beta13",text:"2.0.0-beta.13",level:2},$R[177]={id:"200-beta11",text:"2.0.0-beta.11",level:2},$R[178]={id:"200-beta10",text:"2.0.0-beta.10",level:2},$R[179]={id:"200-beta9",text:"2.0.0-beta.9",level:2},$R[180]={id:"200-beta8",text:"2.0.0-beta.8",level:2},$R[181]={id:"200-beta7",text:"2.0.0-beta.7",level:2},$R[182]={id:"200-beta3",text:"2.0.0-beta.3",level:2},$R[183]={id:"patch-changes-49",text:"Patch Changes",level:3},$R[184]={id:"200",text:"2.0.0",level:2},$R[185]={id:"major-changes",text:"Major changes",level:3},$R[186]={id:"minor-changes-25",text:"Minor Changes",level:3},$R[187]={id:"1112",text:"1.11.2",level:2},$R[188]={id:"patch-changes-50",text:"Patch Changes",level:3},$R[189]={id:"1111",text:"1.11.1",level:2},$R[190]={id:"patch-changes-51",text:"Patch Changes",level:3},$R[191]={id:"1110",text:"1.11.0",level:2},$R[192]={id:"minor-changes-26",text:"Minor Changes",level:3},$R[193]={id:"1101",text:"1.10.1",level:2},$R[194]={id:"patch-changes-52",text:"Patch Changes",level:3},$R[195]={id:"1100",text:"1.10.0",level:2},$R[196]={id:"minor-changes-27",text:"Minor Changes",level:3},$R[197]={id:"191",text:"1.9.1",level:2},$R[198]={id:"patch-changes-53",text:"Patch Changes",level:3},$R[199]={id:"190",text:"1.9.0",level:2},$R[200]={id:"minor-changes-28",text:"Minor Changes",level:3},$R[201]={id:"patch-changes-54",text:"Patch Changes",level:3},$R[202]={id:"180",text:"1.8.0",level:2},$R[203]={id:"minor-changes-29",text:"Minor Changes",level:3},$R[204]={id:"patch-changes-55",text:"Patch Changes",level:3},$R[205]={id:"173",text:"1.7.3",level:2},$R[206]={id:"patch-changes-56",text:"Patch Changes",level:3},$R[207]={id:"172",text:"1.7.2",level:2},$R[208]={id:"patch-changes-57",text:"Patch Changes",level:3},$R[209]={id:"171",text:"1.7.1",level:2},$R[210]={id:"patch-changes-58",text:"Patch Changes",level:3},$R[211]={id:"170",text:"1.7.0",level:2},$R[212]={id:"minor-changes-30",text:"Minor Changes",level:3},$R[213]={id:"162",text:"1.6.2",level:2},$R[214]={id:"patch-changes-59",text:"Patch Changes",level:3},$R[215]={id:"161",text:"1.6.1",level:2},$R[216]={id:"patch-changes-60",text:"Patch Changes",level:3},$R[217]={id:"160",text:"1.6.0",level:2},$R[218]={id:"minor-changes-31",text:"Minor Changes",level:3},$R[219]={id:"150",text:"1.5.0",level:2},$R[220]={id:"minor-changes-32",text:"Minor Changes",level:3},$R[221]={id:"140",text:"1.4.0",level:2},$R[222]={id:"minor-changes-33",text:"Minor Changes",level:3}
1837,$R[223]={id:"patch-changes-61",text:"Patch Changes",level:3},$R[224]={id:"137",text:"1.3.7",level:2},$R[225]={id:"patch-changes-62",text:"Patch Changes",level:3},$R[226]={id:"136",text:"1.3.6",level:2},$R[227]={id:"patch-changes-63",text:"Patch Changes",level:3},$R[228]={id:"135",text:"1.3.5",level:2},$R[229]={id:"patch-changes-64",text:"Patch Changes",level:3},$R[230]={id:"134",text:"1.3.4",level:2},$R[231]={id:"patch-changes-65",text:"Patch Changes",level:3},$R[232]={id:"133",text:"1.3.3",level:2},$R[233]={id:"patch-changes-66",text:"Patch Changes",level:3},$R[234]={id:"132",text:"1.3.2",level:2},$R[235]={id:"patch-changes-67",text:"Patch Changes",level:3},$R[236]={id:"131",text:"1.3.1",level:2},$R[237]={id:"patch-changes-68",text:"Patch Changes",level:3},$R[238]={id:"130",text:"1.3.0",level:2},$R[239]={id:"minor-changes-34",text:"Minor Changes",level:3},$R[240]={id:"patch-changes-69",text:"Patch Changes",level:3},$R[241]={id:"129",text:"1.2.9",level:2},$R[242]={id:"patch-changes-70",text:"Patch Changes",level:3},$R[243]={id:"128",text:"1.2.8",level:2},$R[244]={id:"patch-changes-71",text:"Patch Changes",level:3},$R[245]={id:"127",text:"1.2.7",level:2},$R[246]={id:"patch-changes-72",text:"Patch Changes",level:3},$R[247]={id:"126",text:"1.2.6",level:2},$R[248]={id:"patch-changes-73",text:"Patch Changes",level:3},$R[249]={id:"125",text:"1.2.5",level:2},$R[250]={id:"patch-changes-74",text:"Patch Changes",level:3},$R[251]={id:"124",text:"1.2.4",level:2},$R[252]={id:"patch-changes-75",text:"Patch Changes",level:3},$R[253]={id:"123",text:"1.2.3",level:2},$R[254]={id:"patch-changes-76",text:"Patch Changes",level:3},$R[255]={id:"122",text:"1.2.2",level:2},$R[256]={id:"patch-changes-77",text:"Patch Changes",level:3},$R[257]={id:"121",text:"1.2.1",level:2},$R[258]={id:"patch-changes-78",text:"Patch Changes",level:3},$R[259]={id:"120",text:"1.2.0",level:2},$R[260]={id:"minor-changes-35",text:"Minor Changes",level:3},$R[261]={id:"111",text:"1.1.1",level:2},$R[262]={id:"patch-changes-79",text:"Patch Changes",level:3},$R[263]={id:"110",text:"1.1.0",level:2},$R[264]={id:"minor-changes-36",text:"Minor Changes",level:3},$R[265]={id:"100",text:"1.0.0",level:2},$R[266]={id:"100-prerelease26",text:"1.0.0-prerelease.26",level:2},$R[267]={id:"100-prerelease25",text:"1.0.0-prerelease.25",level:2},$R[268]={id:"100-prerelease24",text:"1.0.0-prerelease.24",level:2},$R[269]={id:"100-prerelease23",text:"1.0.0-prerelease.23",level:2},$R[270]={id:"100-prerelease22",text:"1.0.0-prerelease.22",level:2},$R[271]={id:"100-prerelease21",text:"1.0.0-prerelease.21",level:2},$R[272]={id:"100-prerelease20",text:"1.0.0-prerelease.20",level:2},$R[273]={id:"100-prerelease19",text:"1.0.0-prerelease.19",level:2},$R[274]={id:"100-prerelease18",text:"1.0.0-prerelease.18",level:2},$R[275]={id:"100-prerelease17",text:"1.0.0-prerelease.17",level:2},$R[276]={id:"100-prerelease16",text:"1.0.0-prerelease.16",level:2},$R[277]={id:"100-prerelease15",text:"1.0.0-prerelease.15",level:2},$R[278]={id:"100-prerelease14",text:"1.0.0-prerelease.14",level:2},$R[279]={id:"100-prerelease13",text:"1.0.0-prerelease.13",level:2},$R[280]={id:"100-prerelease12",text:"1.0.0-prerelease.12",level:2},$R[281]={id:"100-prerelease11",text:"1.0.0-prerelease.11",level:2},$R[282]={id:"100-prerelease10",text:"1.0.0-prerelease.10",level:2},$R[283]={id:"100-prerelease9",text:"1.0.0-prerelease.9",level:2},$R[284]={id:"100-prerelease8",text:"1.0.0-prerelease.8",level:2},$R[285]={id:"100-prerelease7",text:"1.0.0-prerelease.7",level:2},$R[286]={id:"100-prerelease6",text:"1.0.0-prerelease.6",level:2},$R[287]={id:"100-prerelease5",text:"1.0.0-prerelease.5",level:2},$R[288]={id:"100-prerelease4",text:"1.0.0-prerelease.4",level:2},$R[289]={id:"100-prerelease3",text:"1.0.0-prerelease.3",level:2},$R[290]={id:"100-prerelease1",text:"1.0.0-prerelease.1",level:2},$R[291]={id:"fix-jetbrains-based-editors-not-detecting-inlangparaglide-js{namespace}messages-imports",text:"fix: Jetbrains based editors not detecting @inlang/paraglide-js/{namespace}/messages imports",level:3}],sections:$R[292]=[$R[293]={title:"Overview",pages:$R[294]=[$R[295]={route:"/",source:"./README.md",title:"Introduction",isExternal:!1,href:"/"},$R[296]={route:"/comparison",source:"./docs/comparison.md",title:"Comparison",isExternal:!1,href:"/comparison"},$R[297]={route:"/benchmark",source:"./benchmark/README.md",title:"Benchmark",isExternal:!1,href:"/benchmark"},$R[298]={route:"/changelog",source:"./CHANGELOG.md",title:"Changelog",isExternal:!1,href:"/changelog"}]},$R[299]={title:"Getting Started",pages:$R[300]=[$R[301]={route:"/sveltekit",source:"./examples/sveltekit/README.md",title:"SvelteKit",isExternal:!1,href:"/sveltekit"},$R[302]={route:"/tanstack-router",source:"https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide",title:"TanStack Router",isExternal:!1,href:"/tanstack-router"},$R[303]={route:"/tanstack-start",source:"https://github.com/TanStack/router/tree/main/examples/react/start-i18n-paraglide",title:"TanStack Start",isExternal:!1,href:"/tanstack-start"},$R[304]={route:"/react-router",source:"./examples/react-router/README.md",title:"React Router",isExternal:!1,href:"/react-router"},$R[305]={route:"/next-js",source:"./docs/getting-started/next-js.md",title:"Next.js",isExternal:!1,href:"/next-js"},$R[306]={route:"/astro",source:"./examples/astro/README.md",title:"Astro",isExternal:!1,href:"/astro"},$R[307]={route:"/vite",source:"./examples/vite/README.md",title:"Vite",isExternal:!1,href:"/vite"},$R[308]={route:"/vanilla-js-ts",source:"./docs/getting-started/vanilla-js-ts.md",title:"Vanilla JS/TS",isExternal:!1,href:"/vanilla-js-ts"},$R[309]={route:"/standalone-servers",source:"./docs/getting-started/standalone-servers.md",title:"Standalone Servers",isExternal:!1,href:"/standalone-servers"}]},$R[310]={title:"Usage",pages:$R[311]=[$R[312]={route:"/basics",source:"./docs/basics.md",title:"Basics",isExternal:!1,href:"/basics"},$R[313]={route:"/compiling-messages",source:"./docs/compiling-messages.md",title:"Compiling Messages",isExternal:!1,href:"/compiling-messages"},$R[314]={route:"/message-keys",source:"./docs/message-keys.md",title:"Message Keys",isExternal:!1,href:"/message-keys"},$R[315]={route:"/markup",source:"./docs/markup.md",title:"Markup",isExternal:!1,href:"/markup"},$R[316]={route:"/strategy",source:"./docs/strategy.md",title:"Strategy",isExternal:!1,href:"/strategy"},$R[317]={route:"/i18n-routing",source:"./docs/i18n-routing.md",title:"i18n Routing",isExternal:!1,href:"/i18n-routing"},$R[318]={route:"/middleware",source:"./docs/middleware.md",title:"Middleware",isExternal:!1,href:"/middleware"},$R[319]={route:"/variants",source:"./docs/variants.md",title:"Variants",isExternal:!1,href:"/variants"},$R[320]={route:"/formatting",source:"./docs/formatting.md",title:"Formatting",isExternal:!1,href:"/formatting"},$R[321]={route:"/objects-and-arrays",source:"./docs/objects-and-arrays.md",title:"Objects And Arrays",isExternal:!1,href:"/objects-and-arrays"},$R[322]={route:"/file-formats",source:"./docs/file-formats.md",title:"File Formats",isExternal:!1,href:"/file-formats"},$R[323]={route:"/monorepo",source:"./docs/monorepo.md",title:"Monorepo",isExternal:!1,href:"/monorepo"},$R[324]={route:"/multi-tenancy",source:"./docs/multi-tenancy.md",title:"Multi Tenancy",isExternal:!1,href:"/multi-tenancy"},$R[325]={route:"/server-side-rendering",source:"./docs/server-side-rendering.md",title:"Server Side Rendering",isExternal:!1,href:"/server-side-rendering"},$R[326]={route:"/static-site-generation",source:"./docs/static-site-generation.md",title:"Static Site Generation",isExternal:!1,href:"/static-site-generation"},$R[327]={route:"/incremental-migration",source:"./examples/incremental-migration/README.md",title:"Incremental Migration",isExternal:!1,href:"/incremental-migration"}]},$R[328]={title:"Reference",pages:$R[329]=[$R[330]={route:"/architecture",source:"./docs/architecture.md",title:"Architecture",isExternal:!1,href:"/architecture"},$R[331]={route:"/compiler-options",source:"./docs-api/compiler-options.md",title:"Compiler Options",isExternal:!1,href:"/compiler-options"}
1837,$R[332]={route:"/runtime",source:"./docs-api/runtime/type/-internal-.md",title:"Runtime",isExternal:!1,href:"/runtime"},$R[333]={route:"/server",source:"./docs-api/server/type/-internal-.md",title:"Server",isExternal:!1,href:"/server"},$R[334]={route:"/errors",source:"./docs/errors.md",title:"Errors",isExternal:!1,href:"/errors"}]},$R[335]={title:"Ecosystem",pages:$R[336]=[$R[337]={route:"/Sherlock VSCode extension",source:"/m/r7kp499g/app-inlang-ideExtension",title:"Sherlock vscode extension",isExternal:!0,href:"https://inlang.com/m/r7kp499g/app-inlang-ideExtension"},$R[338]={route:"/CLI for automation",source:"/m/2qj2w8pu/app-inlang-cli",title:"Cli for automation",isExternal:!0,href:"https://inlang.com/m/2qj2w8pu/app-inlang-cli"},$R[339]={route:"/Fink web editor",source:"/m/tdozzpar/app-inlang-finkLocalizationEditor",title:"Fink web editor",isExternal:!0,href:"https://inlang.com/m/tdozzpar/app-inlang-finkLocalizationEditor"}]},$R[340]={title:"Appendix",pages:$R[341]=[$R[342]={route:"/paraglide-vs-react-i18next",source:"./docs/paraglide-vs-react-i18next.md",title:"Paraglide Vs React I18next",isExternal:!1,href:"/paraglide-vs-react-i18next"},$R[343]={route:"/react-i18next-alternatives",source:"./docs/react-i18next-alternatives.md",title:"React I18next Alternatives",isExternal:!1,href:"/react-i18next-alternatives"}]}],prevPagePath:"/benchmark",nextPagePath:"/sveltekit"},ssr:!0}],lastMatchId:"/$/changelog"})($R["tsr"]);$_TSR.e();document.currentScript.remove()</script>
1837<script type="module" async="">import('/assets/main-DR-gCXHy.js')</script>
1837<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"87065939b4254fefbd9ff9b1773b2296","r":1,"spa":2}' crossorigin="anonymous"></script>
1837 1838</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.