docs: update portal for WRNexusJS 0.8.0

This commit is contained in:
2026-08-02 23:57:41 +05:30
parent 9366895f78
commit 8d5d4b8f12
183 changed files with 14433 additions and 2492 deletions
+146 -166
View File
@@ -10,110 +10,76 @@ page wrnexusi18n {
<header class="topbar">
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.7.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
</header>
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
<main class="portal-main docs-layout">
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/i18n</span></nav><section class="doc-intro"><span class="eyebrow">Frontend · Package reference</span><h1>@wrnexus/i18n</h1><p>Translation loading, locale resolution, and Intl formatting.</p><div class="doc-meta"><span>v0.7.0</span><span>Private registry</span><span>Frontend</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/i18n@0.7.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>Per-request translations plus locale-aware number, date, and currency formatting for WRNexusJS apps.</blockquote>
<p>Part of the <strong>WRNexusJS</strong> framework — an SSR-first, Bun-native full-stack web framework.</p>
<h3 id="overview">Overview</h3>
<p><code>@wrnexus/i18n</code> loads locale files from <code>app/locales/&lt;lang&gt;.json</code>, resolves the active language for each request (cookie → <code>Accept-Language</code> → default), and builds a <code>t(key, params)</code> translator used both in server code and in <code>.wrn</code> views. It also ships Intl-based formatting helpers and a tiny client runtime that wires up a language switcher. Translation lookup, language resolution, and HTML marker rewriting run server-side; only the small <code>I18N_RUNTIME</code> snippet runs in the browser.</p>
<pre data-language="bash"><code>bun add @wrnexus/i18n</code></pre>
<blockquote>Private package — the machine must be authenticated to the <code>wrnexus</code> npm org</blockquote>
<blockquote>(a read token in <code>~/.npmrc</code>). Requires <strong>Bun</strong> (Node is not supported).</blockquote>
<h3 id="api">API</h3>
<h4 id="loading-resolving">Loading &amp; resolving</h4>
<div class="table-wrap"><table>
<thead><tr><th>Export</th><th>Signature</th><th>Description</th></tr></thead>
<tbody><tr><td><code>loadLocales</code></td><td><code>(dir: string) =&gt; Record&lt;string, Messages&gt;</code></td><td>Reads every <code>&lt;lang&gt;.json</code> in <code>dir</code> into a <code>&#123; lang: messages &#125;</code> map. Missing dir → <code>&#123;&#125;</code>; a bad file is warned and skipped.</td></tr><tr><td><code>resolveI18n</code></td><td><code>(messages: Record&lt;string, Messages&gt;, config?: I18nConfig) =&gt; ResolvedI18n</code></td><td>Merges loaded messages + config into a resolved bundle (default lang, supported langs, messages).</td></tr><tr><td><code>resolveLang</code></td><td>`(i18n: ResolvedI18n, cookieValue: string \</td><td>undefined, acceptLanguage: string \</td><td>null) =&gt; string`</td><td>Picks the active language: matching cookie → best <code>Accept-Language</code> tag (falls back to base tag, e.g. <code>en-US</code> → <code>en</code>) → <code>i18n.default</code>.</td></tr><tr><td><code>makeT</code></td><td><code>(i18n: ResolvedI18n, lang: string) =&gt; TFunction</code></td><td>Builds a translator resolving current language → default → the key itself, with <code>&#123;param&#125;</code> interpolation.</td></tr></tbody></table></div>
<h4 id="types-constants">Types &amp; constants</h4>
<div class="table-wrap"><table>
<thead><tr><th>Export</th><th>Kind</th><th>Notes</th></tr></thead>
<tbody><tr><td><code>Messages</code></td><td><code>type</code></td><td><code>Record&lt;string, unknown&gt;</code> — a locale's messages (supports nested/dotted keys).</td></tr><tr><td><code>I18nConfig</code></td><td><code>interface</code></td><td><code>&#123; default?: string; locales?: string[] &#125;</code>.</td></tr><tr><td><code>ResolvedI18n</code></td><td><code>interface</code></td><td><code>&#123; default: string; langs: string[]; messages: Record&lt;string, Messages&gt; &#125;</code>.</td></tr><tr><td><code>LANG_COOKIE</code></td><td><code>const</code></td><td><code>&quot;wire-lang&quot;</code> — the cookie the language is read from / written to.</td></tr><tr><td><code>I18N_JS_HREF</code></td><td><code>const</code></td><td><code>&quot;/__wrnexus/i18n.js&quot;</code> — URL the client runtime is served at.</td></tr></tbody></table></div>
<h4 id="html-client-runtime">HTML &amp; client runtime</h4>
<div class="table-wrap"><table>
<thead><tr><th>Export</th><th>Signature</th><th>Description</th></tr></thead>
<tbody><tr><td><code>translateHtml</code></td><td><code>(html: string, t: TFunction) =&gt; string</code></td><td>Rewrites markers in rendered HTML: <code>t:&lt;attr&gt;=&quot;key&quot;</code> → <code>&lt;attr&gt;=&quot;&lt;translation&gt;&quot;</code> (attribute-escaped) and <code>&lt;tag data-t=&quot;key&quot;&gt;…&lt;/tag&gt;</code> → element text becomes the translation (HTML-escaped). No-op unless a marker is present.</td></tr><tr><td><code>renderI18nData</code></td><td><code>(i18n: ResolvedI18n, lang: string) =&gt; string</code></td><td>JS snippet setting <code>window.__wireI18n = &#123; lang, langs, default &#125;</code> for the client switcher.</td></tr><tr><td><code>I18N_RUNTIME</code></td><td><code>const string</code></td><td>Browser IIFE that binds <code>[data-wire-lang-set=&quot;es&quot;]</code> clicks and <code>select[data-wire-lang]</code> changes to set the <code>wire-lang</code> cookie and reload. Exposes <code>window.__wireLang.set(lang)</code>.</td></tr></tbody></table></div>
<h4 id="formatting-helpers-re-exported-from-format-ts">Formatting helpers (re-exported from <code>./format.ts</code>)</h4>
<div class="table-wrap"><table>
<thead><tr><th>Export</th><th>Signature</th><th>Example</th></tr></thead>
<tbody><tr><td><code>formatNumber</code></td><td><code>(value: number, lang: string, options?: Intl.NumberFormatOptions) =&gt; string</code></td><td><code>1234.5 → &quot;1,234.5&quot;</code></td></tr><tr><td><code>formatCurrency</code></td><td><code>(value: number, currency: string, lang: string) =&gt; string</code></td><td><code>9.99, &quot;USD&quot; → &quot;$9.99&quot;</code></td></tr><tr><td><code>formatDate</code></td><td>`(value: Date \</td><td>number \</td><td>string, lang: string, options?: Intl.DateTimeFormatOptions) =&gt; string`</td><td>defaults to <code>&#123; dateStyle: &quot;medium&quot; &#125;</code></td></tr><tr><td><code>formatRelativeTime</code></td><td><code>(value: number, unit: Intl.RelativeTimeFormatUnit, lang: string) =&gt; string</code></td><td><code>-3, &quot;day&quot; → &quot;3 days ago&quot;</code> (<code>numeric: &quot;auto&quot;</code>)</td></tr><tr><td><code>plural</code></td><td><code>(count: number, forms: Partial&lt;Record&lt;Intl.LDMLPluralRule, string&gt;&gt;, lang: string) =&gt; string</code></td><td>picks CLDR form; <code>#</code> is replaced by <code>count</code></td></tr></tbody></table></div>
<h3 id="usage">Usage</h3>
<h4 id="server-load-resolve-translate">Server: load, resolve, translate</h4>
<pre data-language="ts"><code>import &#123;
loadLocales,
resolveI18n,
resolveLang,
makeT,
translateHtml,
LANG_COOKIE,
&#125; from &quot;@wrnexus/i18n&quot;;
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/i18n</span></nav><section class="doc-intro"><span class="eyebrow">Frontend · Package reference</span><h1>@wrnexus/i18n</h1><p>Translation loading, locale resolution, and Intl formatting.</p><div class="doc-meta"><span>v0.8.0</span><span>Private registry</span><span>Frontend</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/i18n@0.8.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><p>Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS.</p>
<h3 id="locale-files">Locale files</h3>
<p>Both layouts can be used together:</p>
<pre data-language="text"><code>app/locales/en.json
app/locales/en/common.json
app/locales/en/auth.json
app/locales/mr/common.json</code></pre>
<p>Namespaced files become keys such as <code>common.save</code> and <code>auth.signIn</code>.</p>
<pre data-language="ts"><code>import &#123; loadLocales, makeT, resolveI18n, resolveLang &#125; from &quot;@wrnexus/i18n&quot;;
// app/locales/en.json, app/locales/es.json
const messages = loadLocales(&quot;app/locales&quot;);
const i18n = resolveI18n(messages, &#123; default: &quot;en&quot;, locales: [&quot;en&quot;, &quot;es&quot;] &#125;);
const i18n = resolveI18n(loadLocales(&quot;app/locales&quot;, &#123; strict: true &#125;), &#123;
default: &quot;en&quot;,
locales: [&quot;en&quot;, &quot;mr&quot;, &quot;hi&quot;],
fallbacks: &#123; &quot;mr-IN&quot;: [&quot;mr&quot;, &quot;en&quot;] &#125;,
cookie: &#123; name: &quot;wire-lang&quot;, sameSite: &quot;Lax&quot;, secure: true &#125;,
&#125;);
// Per request:
const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get(&quot;accept-language&quot;));
const lang = resolveLang(i18n, cookieValue, request.headers.get(&quot;accept-language&quot;));
const t = makeT(i18n, lang);
t(&quot;nav.home&quot;); // dotted key → &quot;Home&quot;
t(&quot;greeting&quot;, &#123; name: &quot;Ada&quot; &#125;); // &quot;Hello, &#123;name&#125;&quot; → &quot;Hello, Ada&quot;
// After rendering a .wrn view, resolve translation markers in the HTML:
const finalHtml = translateHtml(renderedHtml, t);</code></pre>
<p><code>app/locales/en.json</code>:</p>
<pre data-language="json"><code>&#123;
&quot;nav&quot;: &#123; &quot;home&quot;: &quot;Home&quot; &#125;,
&quot;greeting&quot;: &quot;Hello, &#123;name&#125;&quot;
&#125;</code></pre>
<h4 id="views-translation-markers">Views: translation markers</h4>
<pre data-language="html"><code>&lt;h1 data-t=&quot;nav.home&quot;&gt;Home&lt;/h1&gt;
t(&quot;common.hello&quot;, &#123; name: &quot;Ajay&quot; &#125;);</code></pre>
<h3 id="resolution-behavior">Resolution behavior</h3>
<ul>
<li>normalized BCP-47-style locale names</li>
<li>cookie preference</li>
<li>weighted <code>Accept-Language</code></li>
<li>wildcard language ranges</li>
<li>regional base fallback</li>
<li>explicit fallback chains</li>
<li>configured default language</li>
<li>automatic RTL for Arabic, Hebrew, Persian, Urdu, and related languages</li>
</ul>
<p>Locale JSON is size-limited and rejects prototype-pollution keys. Recursive namespace collisions are resolved safely.</p>
<h3 id="views-and-runtime">Views and runtime</h3>
<pre data-language="html"><code>&lt;h1 data-t=&quot;dashboard.title&quot;&gt;Dashboard&lt;/h1&gt;
&lt;input t:placeholder=&quot;search.placeholder&quot; /&gt;</code></pre>
<p><code>translateHtml</code> replaces the element text for <code>data-t</code> and the attribute value for any <code>t:&lt;attr&gt;</code> (e.g. <code>t:placeholder</code>, <code>t:aria-label</code>).</p>
<h4 id="client-language-switcher">Client: language switcher</h4>
<pre data-language="ts"><code>import &#123; renderI18nData, I18N_RUNTIME, I18N_JS_HREF &#125; from &quot;@wrnexus/i18n&quot;;
// In the document &lt;head&gt;:
const head = `
&lt;script&gt;$&#123;renderI18nData(i18n, lang)&#125;&lt;/script&gt;
&lt;script src=&quot;$&#123;I18N_JS_HREF&#125;&quot;&gt;&lt;/script&gt;
`;
// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup:
// &lt;button data-wire-lang-set=&quot;es&quot;&gt;Español&lt;/button&gt;
// &lt;select data-wire-lang&gt;…&lt;/select&gt;</code></pre>
<h4 id="formatting">Formatting</h4>
<p>Text and translated attributes are resolved during SSR. Active/fallback messages are serialized safely for the language runtime, which rebinds <code>data-t</code> markers after client navigation.</p>
<p>Enable <code>i18nPlugin()</code> to use:</p>
<ul>
<li><code>&lt;LanguageSwitcher /&gt;</code></li>
<li><code>&lt;LocaleStatus /&gt;</code></li>
</ul>
<p><code>LanguageSwitcher</code> renders a native <code>select[data-wire-lang]</code>. The packaged runtime validates the selection against the configured locales, writes the configured language cookie, updates the document <code>lang</code>/<code>dir</code> attributes, emits <code>wrnexus:language-change</code>, and reloads so the next SSR request uses the same cookie. No application-owned browser script is required.</p>
<h3 id="formatting">Formatting</h3>
<ul>
<li><code>formatNumber</code></li>
<li><code>formatCurrency</code></li>
<li><code>formatDate</code></li>
<li><code>formatRelativeTime</code></li>
<li><code>plural</code></li>
<li><code>createLocaleFormatter</code></li>
<li><code>translationCoverage</code></li>
<p>Localization tooling can extract statically discoverable <code>t(&quot;key&quot;)</code>, <code>i18n.t(&quot;key&quot;)</code>, and <code>data-i18n=&quot;key&quot;</code> usage, compare every locale with a reference, and create layout-stressing pseudo-locales:</p>
</ul>
<pre data-language="ts"><code>import &#123;
formatNumber,
formatCurrency,
formatDate,
formatRelativeTime,
plural,
auditLocaleKeys,
createPseudoLocale,
extractTranslationKeysFromFiles,
&#125; from &quot;@wrnexus/i18n&quot;;
formatNumber(1234.5, lang); // &quot;1,234.5&quot;
formatCurrency(9.99, &quot;USD&quot;, lang); // &quot;$9.99&quot;
formatDate(Date.now(), lang); // &quot;Jul 4, 2026&quot;
formatRelativeTime(-3, &quot;day&quot;, lang); // &quot;3 days ago&quot;
plural(2, &#123; one: &quot;# item&quot;, other: &quot;# items&quot; &#125;, lang); // &quot;2 items&quot;</code></pre>
<h3 id="configuration">Configuration</h3>
<p><code>resolveI18n</code> accepts an <code>I18nConfig</code>:</p>
<ul>
<li><code>default</code> — fallback language; used when nothing else matches. Ignored if it has</li>
<p>no loaded messages, in which case the first supported language is used.</p>
<li><code>locales</code> — explicit supported-language list; defaults to the loaded locale names.</li>
</ul>
<p>Language resolution order at request time (<code>resolveLang</code>): a supported <code>wire-lang</code> cookie value → the first matching <code>Accept-Language</code> tag (or its base subtag) → the resolved default.</p>
<h3 id="requirements-notes">Requirements / Notes</h3>
<ul>
<li><strong>Bun-only.</strong> Locale loading uses <code>node:fs</code> (<code>existsSync</code>, <code>readdirSync</code>,</li>
<p><code>readFileSync</code>) and <code>node:path</code>; formatting relies on the platform <code>Intl</code> APIs.</p>
<li>Works with [<code>@wrnexus/core</code>](../core) — <code>TFunction</code> (the <code>t(key, params)</code> type)</li>
<p>comes from core, and the resolved translator is exposed as <code>ctx.t</code> / <code>ctx.lang</code> in request handling.</p>
<li>Nested message objects are supported: keys are looked up whole first, then split</li>
<p>on <code>.</code> to walk the object tree.</p>
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>import &#123; TFunction &#125; from '@wrnexus/core';
const used = extractTranslationKeysFromFiles(sourceFiles);
const coverage = auditLocaleKeys(messages, &quot;en&quot;);
const enXA = createPseudoLocale(messages.en);
const arXB = createPseudoLocale(messages.en, &#123; rtl: true &#125;);</code></pre>
<p>Pseudo-localization preserves interpolation placeholders and markup tags. RTL pseudo output uses Unicode direction controls, while runtime direction detection continues to derive <code>rtl</code> from Arabic and other RTL language subtags.</p></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>import &#123; TFunction &#125; from '@wrnexus/core';
export &#123; I18nPluginOptions, i18nComponentsDir, default as i18nPlugin &#125; from './plugin.js';
import '@wrnexus/plugin';
/**
* Locale-aware formatting helpers (Intl-based) + pluralization. Pair with the
@@ -134,6 +100,25 @@ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormat
*/
declare function plural(count: number, forms: Partial&lt;Record&lt;Intl.LDMLPluralRule, string&gt;&gt;, lang: string): string;
interface ExtractedTranslationKey &#123;
key: string;
file?: string;
offset: number;
&#125;
declare function extractTranslationKeys(source: string, file?: string): ExtractedTranslationKey[];
declare function extractTranslationKeysFromFiles(files: Iterable&lt;string&gt;): ExtractedTranslationKey[];
declare function flattenMessageKeys(messages: Messages, prefix?: string): string[];
declare function auditLocaleKeys(messages: Record&lt;string, Messages&gt;, referenceLocale: string): Record&lt;string, &#123;
missing: string[];
extra: string[];
&#125;&gt;;
declare function pseudoLocalize(value: string, options?: &#123;
rtl?: boolean;
&#125;): string;
declare function createPseudoLocale(messages: Messages, options?: &#123;
rtl?: boolean;
&#125;): Messages;
declare function flattenMessages(messages: Messages, prefix?: string, output?: Record&lt;string, string&gt;): Record&lt;string, string&gt;;
declare function localeFallbacks(locale: string, fallback?: string): string[];
declare function translationCoverage(i18n: ResolvedI18n): Record&lt;string, &#123;
@@ -150,108 +135,103 @@ interface LocaleFormatter &#123;
relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string;
list(values: string[], options?: Intl.ListFormatOptions): string;
&#125;
declare function createLocaleFormatter(locale: string, timeZone?: string): LocaleFormatter;
/** Lightweight plural templates: `&#123;count, plural, one &#123;# item&#125; other &#123;# items&#125;&#125;`. */
declare function createLocaleFormatter(locale: string, timeZone?: string, calendar?: string): LocaleFormatter;
/** ICU-style plural/select templates with exact values and recursive interpolation. */
declare function formatMessage(template: string, params: Record&lt;string, string | number&gt;, locale: string): string;
/**
* @wrnexus/i18n — translations for pages and API responses.
*
* Locales live in `app/locales/&lt;lang&gt;.json`. Per request the active language is
* resolved from the `wire-lang` cookie, then Accept-Language, then the default.
* `ctx.t(key, params)` translates on the server; in `.wrn` views `&#123;t:key&#125;` and
* `t:attr=&quot;key&quot;` markers are resolved by `translateHtml` before the HTML is sent.
* @wrnexus/i18n — deterministic locale loading, fallback resolution, SSR
* translation markers, browser translation helpers, and UI language controls.
*/
type Messages = Record&lt;string, unknown&gt;;
/** Load `&lt;dir&gt;/&lt;lang&gt;.json` files into a `&#123; lang: messages &#125;` map. */
declare function loadLocales(dir: string): Record&lt;string, Messages&gt;;
interface LocaleLoadOptions &#123;
/** Throw on invalid JSON instead of warning and continuing. */
strict?: boolean;
/** Maximum JSON file size. Default 1 MiB. */
maxFileBytes?: number;
&#125;
interface I18nCookieConfig &#123;
name?: string;
maxAge?: number;
path?: string;
sameSite?: &quot;Strict&quot; | &quot;Lax&quot; | &quot;None&quot;;
secure?: boolean;
&#125;
interface I18nConfig &#123;
/** Default language, used as the fallback and when nothing else matches. */
default?: string;
/** Explicit set of supported languages (defaults to the loaded locale names). */
locales?: string[];
/** Human-readable locale names used by package language controls. */
labels?: Record&lt;string, string&gt;;
/** Per-locale fallback override. Example: `&#123; &quot;fr-CA&quot;: [&quot;fr&quot;, &quot;en&quot;] &#125;`. */
fallbacks?: Record&lt;string, string[]&gt;;
/** Locale direction overrides. Arabic/Hebrew/Persian/Urdu are RTL automatically. */
direction?: Record&lt;string, &quot;ltr&quot; | &quot;rtl&quot;&gt;;
cookie?: I18nCookieConfig;
strict?: boolean;
&#125;
interface ResolvedI18n &#123;
default: string;
langs: string[];
messages: Record&lt;string, Messages&gt;;
fallbacks: Record&lt;string, string[]&gt;;
direction: Record&lt;string, &quot;ltr&quot; | &quot;rtl&quot;&gt;;
labels: Record&lt;string, string&gt;;
cookie: Required&lt;I18nCookieConfig&gt;;
&#125;
declare const LANG_COOKIE = &quot;wire-lang&quot;;
declare const I18N_JS_HREF = &quot;/__wrnexus/i18n.js&quot;;
/** Merge loaded locale messages + config into a resolved i18n bundle. */
declare function normalizeLocale(locale: string): string;
/**
* Load both supported layouts:
* - `locales/en.json`
* - `locales/en/common.json`, `locales/en/auth.json`
*
* Namespaced files become `messages.en.common` and `messages.en.auth`.
*/
declare function loadLocales(dir: string, options?: LocaleLoadOptions): Record&lt;string, Messages&gt;;
declare function localeDirection(locale: string, overrides?: Record&lt;string, &quot;ltr&quot; | &quot;rtl&quot;&gt;): &quot;ltr&quot; | &quot;rtl&quot;;
declare function resolveI18n(messages: Record&lt;string, Messages&gt;, config?: I18nConfig): ResolvedI18n;
/** Build a `t()` for a language: current → default → the key itself. */
declare function lookupMessage(messages: Messages | undefined, key: string): string | undefined;
declare function interpolate(message: string, params?: Record&lt;string, string | number&gt;): string;
declare function translationChain(i18n: ResolvedI18n, locale: string): string[];
declare function makeT(i18n: ResolvedI18n, lang: string): TFunction;
/** Resolve the active language from a cookie, Accept-Language, then default. */
/** Deeply apply tenant-specific translations without mutating the shared locale bundle. */
declare function withTenantMessages(i18n: ResolvedI18n, overrides: Record&lt;string, Messages&gt;): ResolvedI18n;
/** Load only common and route-specific messages for one locale. */
declare function loadRouteMessages(directory: string, locale: string, route: string): Messages;
declare function parseAcceptLanguage(value: string | null): string[];
declare function resolveLang(i18n: ResolvedI18n, cookieValue: string | undefined, acceptLanguage: string | null): string;
/**
* Resolve translation markers in rendered HTML:
* t:&lt;attr&gt;=&quot;key&quot; → &lt;attr&gt;=&quot;&lt;translation&gt;&quot; (e.g. t:placeholder, t:aria-label)
* &lt;tag data-t=&quot;key&quot;&gt;…&lt;/tag&gt; → element text becomes the translation
* Only runs when the HTML actually contains a marker.
*/
declare function translateHtml(html: string, t: TFunction): string;
/** `window.__wireI18n = &#123; lang, langs &#125;` for the client language switcher. */
declare function renderI18nData(i18n: ResolvedI18n, lang: string): string;
/**
* Client runtime: binds `[data-wire-lang-set=&quot;es&quot;]` elements to set the
* `wire-lang` cookie and reload, so the server re-renders in the new language.
*/
declare const I18N_RUNTIME: string;
export &#123; I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, LANG_COOKIE, type LocaleFormatter, type Messages, type ResolvedI18n, createLocaleFormatter, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, loadLocales, localeFallbacks, makeT, plural, renderI18nData, resolveI18n, resolveLang, translateHtml, translationCoverage &#125;;
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Server: load, resolve, translate</h3><pre data-language="ts"><code>import &#123;
loadLocales,
resolveI18n,
resolveLang,
makeT,
translateHtml,
LANG_COOKIE,
&#125; from &quot;@wrnexus/i18n&quot;;
export &#123; type ExtractedTranslationKey, I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, type I18nCookieConfig, LANG_COOKIE, type LocaleFormatter, type LocaleLoadOptions, type Messages, type ResolvedI18n, auditLocaleKeys, createLocaleFormatter, createPseudoLocale, extractTranslationKeys, extractTranslationKeysFromFiles, flattenMessageKeys, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, interpolate, loadLocales, loadRouteMessages, localeDirection, localeFallbacks, lookupMessage, makeT, normalizeLocale, parseAcceptLanguage, plural, pseudoLocalize, renderI18nData, resolveI18n, resolveLang, translateHtml, translationChain, translationCoverage, withTenantMessages &#125;;
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Namespaced files become keys such as common.save and auth.signIn.</h3><pre data-language="ts"><code>import &#123; loadLocales, makeT, resolveI18n, resolveLang &#125; from &quot;@wrnexus/i18n&quot;;
// app/locales/en.json, app/locales/es.json
const messages = loadLocales(&quot;app/locales&quot;);
const i18n = resolveI18n(messages, &#123; default: &quot;en&quot;, locales: [&quot;en&quot;, &quot;es&quot;] &#125;);
const i18n = resolveI18n(loadLocales(&quot;app/locales&quot;, &#123; strict: true &#125;), &#123;
default: &quot;en&quot;,
locales: [&quot;en&quot;, &quot;mr&quot;, &quot;hi&quot;],
fallbacks: &#123; &quot;mr-IN&quot;: [&quot;mr&quot;, &quot;en&quot;] &#125;,
cookie: &#123; name: &quot;wire-lang&quot;, sameSite: &quot;Lax&quot;, secure: true &#125;,
&#125;);
// Per request:
const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get(&quot;accept-language&quot;));
const lang = resolveLang(i18n, cookieValue, request.headers.get(&quot;accept-language&quot;));
const t = makeT(i18n, lang);
t(&quot;nav.home&quot;); // dotted key → &quot;Home&quot;
t(&quot;greeting&quot;, &#123; name: &quot;Ada&quot; &#125;); // &quot;Hello, &#123;name&#125;&quot; → &quot;Hello, Ada&quot;
// After rendering a .wrn view, resolve translation markers in the HTML:
const finalHtml = translateHtml(renderedHtml, t);</code></pre></article><article class="example-card"><h3>Server: load, resolve, translate</h3><pre data-language="json"><code>&#123;
&quot;nav&quot;: &#123; &quot;home&quot;: &quot;Home&quot; &#125;,
&quot;greeting&quot;: &quot;Hello, &#123;name&#125;&quot;
&#125;</code></pre></article><article class="example-card"><h3>Views: translation markers</h3><pre data-language="html"><code>&lt;h1 data-t=&quot;nav.home&quot;&gt;Home&lt;/h1&gt;
&lt;input t:placeholder=&quot;search.placeholder&quot; /&gt;</code></pre></article><article class="example-card"><h3>Client: language switcher</h3><pre data-language="ts"><code>import &#123; renderI18nData, I18N_RUNTIME, I18N_JS_HREF &#125; from &quot;@wrnexus/i18n&quot;;
// In the document &lt;head&gt;:
const head = `
&lt;script&gt;$&#123;renderI18nData(i18n, lang)&#125;&lt;/script&gt;
&lt;script src=&quot;$&#123;I18N_JS_HREF&#125;&quot;&gt;&lt;/script&gt;
`;
// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup:
// &lt;button data-wire-lang-set=&quot;es&quot;&gt;Español&lt;/button&gt;
// &lt;select data-wire-lang&gt;…&lt;/select&gt;</code></pre></article><article class="example-card"><h3>Formatting</h3><pre data-language="ts"><code>import &#123;
formatNumber,
formatCurrency,
formatDate,
formatRelativeTime,
plural,
t(&quot;common.hello&quot;, &#123; name: &quot;Ajay&quot; &#125;);</code></pre></article><article class="example-card"><h3>## Views and runtime</h3><pre data-language="html"><code>&lt;h1 data-t=&quot;dashboard.title&quot;&gt;Dashboard&lt;/h1&gt;
&lt;input t:placeholder=&quot;search.placeholder&quot; /&gt;</code></pre></article><article class="example-card"><h3>reference, and create layout-stressing pseudo-locales</h3><pre data-language="ts"><code>import &#123;
auditLocaleKeys,
createPseudoLocale,
extractTranslationKeysFromFiles,
&#125; from &quot;@wrnexus/i18n&quot;;
formatNumber(1234.5, lang); // &quot;1,234.5&quot;
formatCurrency(9.99, &quot;USD&quot;, lang); // &quot;$9.99&quot;
formatDate(Date.now(), lang); // &quot;Jul 4, 2026&quot;
formatRelativeTime(-3, &quot;day&quot;, lang); // &quot;3 days ago&quot;
plural(2, &#123; one: &quot;# item&quot;, other: &quot;# items&quot; &#125;, lang); // &quot;2 items&quot;</code></pre></article></div></section></article>
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#loading-resolving">Loading &amp; resolving</a><a class="toc-level-4" href="#types-constants">Types &amp; constants</a><a class="toc-level-4" href="#html-client-runtime">HTML &amp; client runtime</a><a class="toc-level-4" href="#formatting-helpers-re-exported-from-format-ts">Formatting helpers (re-exported from ./format.ts)</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-4" href="#server-load-resolve-translate">Server: load, resolve, translate</a><a class="toc-level-4" href="#views-translation-markers">Views: translation markers</a><a class="toc-level-4" href="#client-language-switcher">Client: language switcher</a><a class="toc-level-4" href="#formatting">Formatting</a><a class="toc-level-3" href="#configuration">Configuration</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
const used = extractTranslationKeysFromFiles(sourceFiles);
const coverage = auditLocaleKeys(messages, &quot;en&quot;);
const enXA = createPseudoLocale(messages.en);
const arXB = createPseudoLocale(messages.en, &#123; rtl: true &#125;);</code></pre></article></div></section></article>
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#locale-files">Locale files</a><a class="toc-level-3" href="#resolution-behavior">Resolution behavior</a><a class="toc-level-3" href="#views-and-runtime">Views and runtime</a><a class="toc-level-3" href="#formatting">Formatting</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
</main>
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.7.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
<BackToTop />
</div>
}