@ingram-tech/nk-i18n 0.1.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- import { type I18nScope, type Messages, type Translator } from "./core.js";
2
+ import { type CreateTOptions, type I18nScope, type Messages, type Translator } from "./core.js";
3
3
  /**
4
4
  * Provide the active locale to client components. Wrap the app once (in the root
5
5
  * layout) with the server-resolved locale.
@@ -19,5 +19,5 @@ export declare function useLocale<TLocale extends string = string>(): TLocale;
19
19
  * (`useT({ fr, nl })`), so they are held in a ref and the translator identity
20
20
  * only changes when the locale changes — safe to list in hook deps.
21
21
  */
22
- export declare function useT<const TSource extends Messages | I18nScope | undefined>(messagesOrScope?: TSource, runtimeMessages?: Messages | I18nScope): Translator<TSource>;
22
+ export declare function useT<const TSource extends Messages | I18nScope | undefined>(messagesOrScope?: TSource, runtimeMessages?: Messages | I18nScope, options?: CreateTOptions): Translator<TSource>;
23
23
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AACnF,OAAO,EAAW,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAIpF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC9B,KAAK,EACL,QAAQ,GACR,EAAE;IACF,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACpB,+BAEA;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,KAAK,OAAO,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,QAAQ,GAAG,SAAS,GAAG,SAAS,EAC1E,eAAe,CAAC,EAAE,OAAO,EACzB,eAAe,CAAC,EAAE,QAAQ,GAAG,SAAS,GACpC,UAAU,CAAC,OAAO,CAAC,CAarB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AACnF,OAAO,EACN,KAAK,cAAc,EAEnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,MAAM,WAAW,CAAC;AAInB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC9B,KAAK,EACL,QAAQ,GACR,EAAE;IACF,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACpB,+BAEA;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,KAAK,OAAO,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,QAAQ,GAAG,SAAS,GAAG,SAAS,EAC1E,eAAe,CAAC,EAAE,OAAO,EACzB,eAAe,CAAC,EAAE,QAAQ,GAAG,SAAS,EACtC,OAAO,CAAC,EAAE,cAAc,GACtB,UAAU,CAAC,OAAO,CAAC,CAcrB"}
package/dist/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { createContext, useContext, useMemo, useRef } from "react";
4
- import { createT } from "./core.js";
4
+ import { createT, } from "./core.js";
5
5
  const LocaleContext = createContext("en");
6
6
  /**
7
7
  * Provide the active locale to client components. Wrap the app once (in the root
@@ -23,10 +23,10 @@ export function useLocale() {
23
23
  * (`useT({ fr, nl })`), so they are held in a ref and the translator identity
24
24
  * only changes when the locale changes — safe to list in hook deps.
25
25
  */
26
- export function useT(messagesOrScope, runtimeMessages) {
26
+ export function useT(messagesOrScope, runtimeMessages, options) {
27
27
  const locale = useContext(LocaleContext);
28
- const sources = useRef({ messagesOrScope, runtimeMessages });
29
- sources.current = { messagesOrScope, runtimeMessages };
30
- return useMemo(() => createT(locale, sources.current.messagesOrScope, sources.current.runtimeMessages), [locale]);
28
+ const sources = useRef({ messagesOrScope, runtimeMessages, options });
29
+ sources.current = { messagesOrScope, runtimeMessages, options };
30
+ return useMemo(() => createT(locale, sources.current.messagesOrScope, sources.current.runtimeMessages, sources.current.options), [locale]);
31
31
  }
32
32
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACnF,OAAO,EAAE,OAAO,EAAkD,MAAM,WAAW,CAAC;AAEpF,MAAM,aAAa,GAAG,aAAa,CAAS,IAAI,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAC9B,KAAK,EACL,QAAQ,GAIR;IACA,OAAO,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA0B,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS;IACxB,OAAO,UAAU,CAAC,aAAa,CAAY,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CACnB,eAAyB,EACzB,eAAsC;IAEtC,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,OAAO,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;IACvD,OAAO,OAAO,CACb,GAAG,EAAE,CACJ,OAAO,CACN,MAAM,EACN,OAAO,CAAC,OAAO,CAAC,eAAe,EAC/B,OAAO,CAAC,OAAO,CAAC,eAAe,CAC/B,EACF,CAAC,MAAM,CAAC,CACR,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACnF,OAAO,EAEN,OAAO,GAIP,MAAM,WAAW,CAAC;AAEnB,MAAM,aAAa,GAAG,aAAa,CAAS,IAAI,CAAC,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAC9B,KAAK,EACL,QAAQ,GAIR;IACA,OAAO,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA0B,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS;IACxB,OAAO,UAAU,CAAC,aAAa,CAAY,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CACnB,eAAyB,EACzB,eAAsC,EACtC,OAAwB;IAExB,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,OAAO,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC;IAChE,OAAO,OAAO,CACb,GAAG,EAAE,CACJ,OAAO,CACN,MAAM,EACN,OAAO,CAAC,OAAO,CAAC,eAAe,EAC/B,OAAO,CAAC,OAAO,CAAC,eAAe,EAC/B,OAAO,CAAC,OAAO,CAAC,OAAO,CACvB,EACF,CAAC,MAAM,CAAC,CACR,CAAC;AACH,CAAC"}
package/dist/config.d.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  /**
2
- * Reserved: declared for forward compatibility but not yet consumed by
3
- * `createT`/`useT` a missing key currently always falls back to the English
4
- * source silently, regardless of this setting.
2
+ * What a translator does when the active locale's catalog has no entry for a
3
+ * key: `"error"` throws, `"warn"` logs once per locale+key, `"ignore"` (the
4
+ * default) silently falls back to the English source. Pass a locale's policy to
5
+ * `createT`/`useT` via their `missingKeys` option (e.g.
6
+ * `createT(locale, msgs, undefined, { missingKeys: config.locales[locale].missingKeys })`).
5
7
  */
6
8
  export type MissingKeysPolicy = "error" | "warn" | "ignore";
7
9
  /**
8
10
  * Metadata for one locale. `label` (the display name, usually native) is
9
- * required; sites may add their own fields (e.g. `htmlLang`, `ogLocale`) and
10
- * read them back type-safely with {@link localeMap}.
11
+ * required; `missingKeys` sets this locale's {@link MissingKeysPolicy} (read it
12
+ * back with `config.locales[locale].missingKeys` and hand it to the translator).
13
+ * Sites may add their own fields (e.g. `htmlLang`, `ogLocale`) and read them
14
+ * back type-safely with {@link localeMap}.
11
15
  */
12
16
  export type LocaleDefinition = {
13
17
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,UAAU,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,MAAM,CACzD,MAAM,EACN,gBAAgB,CAChB,EACD,WAAW,SAAS,MAAM,GAAG,MAAM,IAChC;IACH,UAAU,EAAE,WAAW,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EACnE,MAAM,EAAE,OAAO,GACb,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EACxE,MAAM,EAAE,OAAO,GACb;IACF,iBAAiB,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;IAC5D,cAAc,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAGtC,YAAY,EAAE;SACZ,CAAC,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;KACxE,CAAC;CACF,CAYA;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EAAE,MAAM,EACpE,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,CACL,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,EAC1D,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,KACrC,MAAM,GACT,MAAM,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,CAQnD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,UAAU,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,MAAM,CACzD,MAAM,EACN,gBAAgB,CAChB,EACD,WAAW,SAAS,MAAM,GAAG,MAAM,IAChC;IACH,UAAU,EAAE,WAAW,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC;CAClB,CAAC;AAEF,KAAK,aAAa,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EACnE,MAAM,EAAE,OAAO,GACb,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EACxE,MAAM,EAAE,OAAO,GACb;IACF,iBAAiB,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;IAC5D,cAAc,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAGtC,YAAY,EAAE;SACZ,CAAC,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;KACxE,CAAC;CACF,CAYA;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,EAAE,MAAM,EACpE,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,CACL,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,EAC1D,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,KACrC,MAAM,GACT,MAAM,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,CAQnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAe;IAEf,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACpC,MAAe;IAWf,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAsC,CAAC;IACpF,OAAO;QACN,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;QACpD,cAAc,EAAE,MAAM,CAAC,UAAU;QACjC,YAAY,EAAE,MAAM,CAAC,WAAW,CAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAGnD;KACD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACxB,MAAe,EACf,IAGW;IAGX,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAE5C,CAAC;IACF,OAAO,MAAM,CAAC,WAAW,CACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CACjC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAqCA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAe;IAEf,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACpC,MAAe;IAWf,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAsC,CAAC;IACpF,OAAO;QACN,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;QACpD,cAAc,EAAE,MAAM,CAAC,UAAU;QACjC,YAAY,EAAE,MAAM,CAAC,WAAW,CAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAGnD;KACD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACxB,MAAe,EACf,IAGW;IAGX,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAE5C,CAAC;IACF,OAAO,MAAM,CAAC,WAAW,CACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CACjC,CAAC;AAC7B,CAAC"}
package/dist/core.d.ts CHANGED
@@ -1,5 +1,18 @@
1
+ import type { MissingKeysPolicy } from "./config.js";
1
2
  type MessageCatalog = Record<string, string>;
2
3
  declare const I18N_KEY_BRAND: unique symbol;
4
+ declare const LOCALIZED_STRING_BRAND: unique symbol;
5
+ /**
6
+ * A string that has passed through a {@link Translator} — display-ready text in
7
+ * the active locale. It is a plain `string` at runtime (the brand is erased), so
8
+ * it flows anywhere a `string` is wanted; the brand only matters where a prop is
9
+ * tightened to require `LocalizedString`, which turns hardcoded English at that
10
+ * boundary into a compile error. Sites that need to pass deliberately
11
+ * untranslated text (a name, an id, a number) opt out with `x as LocalizedString`.
12
+ */
13
+ export type LocalizedString = string & {
14
+ readonly [LOCALIZED_STRING_BRAND]: "LocalizedString";
15
+ };
3
16
  /**
4
17
  * A set of per-locale message catalogs, keyed by locale code. The English
5
18
  * source text is used as the key, so there is no `en` catalog: a missing lookup
@@ -32,8 +45,12 @@ type DeepMessageKeys<TValue> = TValue extends string ? I18nKey<TValue> : TValue
32
45
  * source the key is checked against the catalogs at compile time; without one,
33
46
  * any literal string is allowed. The optional `values` are interpolated with
34
47
  * ICU MessageFormat (`{name}`, `{count, number}`, plurals, …).
48
+ *
49
+ * The return is branded {@link LocalizedString} so a prop can require translated
50
+ * text; interpolation done here stays branded, but composing with `+` or a
51
+ * template literal collapses back to a plain `string`.
35
52
  */
36
- export type Translator<TSource extends MessageSource | undefined = undefined> = <const TValue extends string>(english: AllowedMessageKey<TSource, TValue>, values?: Record<string, unknown>) => string;
53
+ export type Translator<TSource extends MessageSource | undefined = undefined> = <const TValue extends string>(english: AllowedMessageKey<TSource, TValue>, values?: Record<string, unknown>) => LocalizedString;
37
54
  /**
38
55
  * Brand a tree of English source strings as translation keys so the compiler
39
56
  * can check them. Returns the value unchanged at runtime.
@@ -44,12 +61,25 @@ export declare function defineI18nScope<const TMessages extends Messages>(scope:
44
61
  name: string;
45
62
  messages: TMessages;
46
63
  }): I18nScope<TMessages>;
64
+ /** Options for {@link createT}. */
65
+ export interface CreateTOptions {
66
+ /**
67
+ * What to do when the active locale's catalog has no entry for a key. Pass
68
+ * the locale's {@link MissingKeysPolicy} (e.g.
69
+ * `config.locales[locale].missingKeys`). Defaults to `"ignore"`. Only pass a
70
+ * non-`ignore` policy for locales that actually ship a catalog — the base
71
+ * locale has none by design (the English source *is* the key), so every
72
+ * lookup there is an expected "miss".
73
+ */
74
+ missingKeys?: MissingKeysPolicy;
75
+ }
47
76
  /**
48
77
  * Build a translator bound to `locale`. The English source is the key, so the
49
78
  * base/source locale needs no catalog — a missing lookup returns the key. Pass
50
79
  * a scope or raw `{ fr, nl, … }` catalogs as the source; `runtimeMessages`
51
- * overrides them (e.g. request-scoped data).
80
+ * overrides them (e.g. request-scoped data). `options.missingKeys` enforces a
81
+ * {@link MissingKeysPolicy} for locales that ship a catalog.
52
82
  */
53
- export declare function createT<const TSource extends MessageSource | undefined>(locale: string, messagesOrScope?: TSource, runtimeMessages?: MessageSource): Translator<TSource>;
83
+ export declare function createT<const TSource extends MessageSource | undefined>(locale: string, messagesOrScope?: TSource, runtimeMessages?: MessageSource, options?: CreateTOptions): Translator<TSource>;
54
84
  export {};
55
85
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC7C,OAAO,CAAC,MAAM,cAAc,EAAE,OAAO,MAAM,CAAC;AAE5C;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEtD,KAAK,OAAO,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG;IACvD,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;CACrC,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,SAAS,CAAC,SAAS,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,SAAS,SAAS,QAAQ,GAAG,QAAQ,IAC5D,SAAS,GACT,SAAS,CAAC,SAAS,CAAC,CAAC;AAExB,KAAK,gBAAgB,CAAC,SAAS,SAAS,QAAQ,IAAI,MAAM,SAAS,CAAC,MAAM,SAAS,CAAC,GACnF,MAAM,CAAC;AACR,KAAK,eAAe,CAAC,OAAO,SAAS,aAAa,IACjD,OAAO,SAAS,SAAS,CAAC,MAAM,SAAS,CAAC,GACvC,gBAAgB,CAAC,SAAS,CAAC,GAC3B,OAAO,SAAS,QAAQ,GACvB,gBAAgB,CAAC,OAAO,CAAC,GACzB,KAAK,CAAC;AACX,KAAK,OAAO,CAAC,MAAM,SAAS,MAAM,IACjC,MAAM,SAAS,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC;AACpD,KAAK,aAAa,CAAC,MAAM,SAAS,MAAM,IAAI,MAAM,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AACnF,KAAK,gBAAgB,CAAC,MAAM,SAAS,MAAM,IAC1C,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEjE,MAAM,MAAM,cAAc,CAAC,OAAO,SAAS,aAAa,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;AAErF,KAAK,iBAAiB,CACrB,OAAO,SAAS,aAAa,GAAG,SAAS,EACzC,MAAM,SAAS,MAAM,IAClB,OAAO,SAAS,aAAa,GAC9B,OAAO,CAAC,MAAM,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,GAC/C,MAAM,GACN,eAAe,CAAC,OAAO,CAAC,GACzB,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE5B,KAAK,eAAe,CAAC,MAAM,IAAI,MAAM,SAAS,MAAM,GACjD,OAAO,CAAC,MAAM,CAAC,GACf,MAAM,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAC3C,MAAM,GACN,MAAM,SAAS,SAAS,OAAO,EAAE,GAChC;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CAAE,GAC5D,MAAM,SAAS,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,GAC1C;KAAG,CAAC,IAAI,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CAAE,GACnD,MAAM,CAAC;AAEb;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,SAAS,aAAa,GAAG,SAAS,GAAG,SAAS,IAAI,CAC/E,KAAK,CAAC,MAAM,SAAS,MAAM,EAE3B,OAAO,EAAE,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,EAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,MAAM,CAAC;AAyDZ;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAEnF;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,KAAK,CAAC,SAAS,SAAS,QAAQ,EAAE,KAAK,EAAE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACpB,GAAG,SAAS,CAAC,SAAS,CAAC,CAEvB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,CAAC,OAAO,SAAS,aAAa,GAAG,SAAS,EACtE,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,OAAO,EACzB,eAAe,CAAC,EAAE,aAAa,GAC7B,UAAU,CAAC,OAAO,CAAC,CAWrB"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/dist/core.js CHANGED
@@ -5,6 +5,22 @@ const cache = new Map();
5
5
  // memory without limit.
6
6
  const CACHE_MAX = 5000;
7
7
  const warnedFormatErrors = new Set();
8
+ const warnedMissingKeys = new Set();
9
+ /** Apply a locale's {@link MissingKeysPolicy} when a catalog lookup misses.
10
+ * `"error"` throws; `"warn"` logs once per locale+key; `"ignore"` is silent.
11
+ * The caller falls back to the English key regardless (except when thrown). */
12
+ function reportMissingKey(key, locale, policy) {
13
+ if (policy === "ignore")
14
+ return;
15
+ const message = `@ingram-tech/nk-i18n: missing "${locale}" translation for "${key}"`;
16
+ if (policy === "error")
17
+ throw new Error(message);
18
+ const dedupe = `${locale}:${key}`;
19
+ if (!warnedMissingKeys.has(dedupe)) {
20
+ warnedMissingKeys.add(dedupe);
21
+ console.warn(message);
22
+ }
23
+ }
8
24
  function format(message, locale, values) {
9
25
  try {
10
26
  const key = `${locale}:${message}`;
@@ -57,15 +73,22 @@ export function defineI18nScope(scope) {
57
73
  * Build a translator bound to `locale`. The English source is the key, so the
58
74
  * base/source locale needs no catalog — a missing lookup returns the key. Pass
59
75
  * a scope or raw `{ fr, nl, … }` catalogs as the source; `runtimeMessages`
60
- * overrides them (e.g. request-scoped data).
76
+ * overrides them (e.g. request-scoped data). `options.missingKeys` enforces a
77
+ * {@link MissingKeysPolicy} for locales that ship a catalog.
61
78
  */
62
- export function createT(locale, messagesOrScope, runtimeMessages) {
79
+ export function createT(locale, messagesOrScope, runtimeMessages, options) {
63
80
  const resolvedMessages = resolveMessages(runtimeMessages) ?? resolveMessages(messagesOrScope);
81
+ const missingKeys = options?.missingKeys ?? "ignore";
82
+ // The brand is erased at runtime; this function is the sole mint site.
64
83
  const translate = (english, values) => {
65
- const translated = resolvedMessages?.[locale]?.[english] ?? english;
84
+ const translated = resolvedMessages?.[locale]?.[english];
85
+ if (translated === undefined && missingKeys !== "ignore") {
86
+ reportMissingKey(english, locale, missingKeys);
87
+ }
88
+ const text = translated ?? english;
66
89
  if (!values)
67
- return translated;
68
- return format(translated, locale, values);
90
+ return text;
91
+ return format(text, locale, values);
69
92
  };
70
93
  return translate;
71
94
  }
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createT, defineI18nScope, defineMessages, type I18nScope, type Messages, type MessageSource, type TranslationKey, type Translator, } from "./core.js";
1
+ export { createT, type CreateTOptions, defineI18nScope, defineMessages, type I18nScope, type LocalizedString, type Messages, type MessageSource, type TranslationKey, type Translator, } from "./core.js";
2
2
  export { defineI18nConfig, deriveLocaleConstants, type I18nConfig, localeMap, type LocaleDefinition, type MissingKeysPolicy, } from "./config.js";
3
3
  export { negotiateAcceptLanguage } from "./negotiate.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,OAAO,EACP,eAAe,EACf,cAAc,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,UAAU,EACf,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,OAAO,EACP,KAAK,cAAc,EACnB,eAAe,EACf,cAAc,EACd,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,UAAU,EACf,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,EACN,OAAO,EACP,eAAe,EACf,cAAc,GAMd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EAErB,SAAS,GAGT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,EACN,OAAO,EAEP,eAAe,EACf,cAAc,GAOd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,qBAAqB,EAErB,SAAS,GAGT,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * Pick the best supported locale from an `Accept-Language` header value.
3
- * Compares on the primary subtag only (`fr-BE` → `fr`), case-insensitively,
4
- * honoring q-values per RFC 9110: highest quality wins (header order breaks
5
- * ties), and `q=0` an explicit rejection never matches. Returns
6
- * `undefined` when nothing matches. Purecompose it inside a
7
- * framework-specific locale resolver.
3
+ * Compares on the primary subtag only (`fr-BE` → `fr`), case-insensitively on
4
+ * **both** sides (so `supported: ["EN"]` or `["en-US"]` still match an `en`
5
+ * header), honoring q-values per RFC 9110: highest quality wins (header order
6
+ * breaks ties), and `q=0` an explicit rejectionnever matches. Returns the
7
+ * matching entry from `supported` verbatim (its own casing), or `undefined`
8
+ * when nothing matches. Pure — compose it inside a framework-specific locale
9
+ * resolver.
8
10
  */
9
11
  export declare function negotiateAcceptLanguage(header: string | null | undefined, supported: readonly string[]): string | undefined;
10
12
  //# sourceMappingURL=negotiate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"negotiate.d.ts","sourceRoot":"","sources":["../src/negotiate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,GAAG,SAAS,CAgBpB"}
1
+ {"version":3,"file":"negotiate.d.ts","sourceRoot":"","sources":["../src/negotiate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,GAAG,SAAS,CAyBpB"}
package/dist/negotiate.js CHANGED
@@ -1,14 +1,25 @@
1
1
  /**
2
2
  * Pick the best supported locale from an `Accept-Language` header value.
3
- * Compares on the primary subtag only (`fr-BE` → `fr`), case-insensitively,
4
- * honoring q-values per RFC 9110: highest quality wins (header order breaks
5
- * ties), and `q=0` an explicit rejection never matches. Returns
6
- * `undefined` when nothing matches. Purecompose it inside a
7
- * framework-specific locale resolver.
3
+ * Compares on the primary subtag only (`fr-BE` → `fr`), case-insensitively on
4
+ * **both** sides (so `supported: ["EN"]` or `["en-US"]` still match an `en`
5
+ * header), honoring q-values per RFC 9110: highest quality wins (header order
6
+ * breaks ties), and `q=0` an explicit rejectionnever matches. Returns the
7
+ * matching entry from `supported` verbatim (its own casing), or `undefined`
8
+ * when nothing matches. Pure — compose it inside a framework-specific locale
9
+ * resolver.
8
10
  */
9
11
  export function negotiateAcceptLanguage(header, supported) {
10
12
  if (!header)
11
13
  return undefined;
14
+ // Map each supported locale's primary subtag (lowercased) back to the entry as
15
+ // written, so the comparison is case-insensitive but the returned value keeps
16
+ // the caller's canonical form. First entry wins a shared primary subtag.
17
+ const byPrimary = new Map();
18
+ for (const entry of supported) {
19
+ const key = entry.split("-")[0]?.toLowerCase();
20
+ if (key && !byPrimary.has(key))
21
+ byPrimary.set(key, entry);
22
+ }
12
23
  const candidates = [];
13
24
  header.split(",").forEach((part, index) => {
14
25
  const [tag, ...params] = part.split(";");
@@ -25,6 +36,7 @@ export function negotiateAcceptLanguage(header, supported) {
25
36
  candidates.push({ lang, q, index });
26
37
  });
27
38
  candidates.sort((a, b) => b.q - a.q || a.index - b.index);
28
- return candidates.find((c) => supported.includes(c.lang))?.lang;
39
+ const winner = candidates.find((c) => byPrimary.has(c.lang));
40
+ return winner ? byPrimary.get(winner.lang) : undefined;
29
41
  }
30
42
  //# sourceMappingURL=negotiate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"negotiate.js","sourceRoot":"","sources":["../src/negotiate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACtC,MAAiC,EACjC,SAA4B;IAE5B,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,UAAU,GAAiD,EAAE,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACzC,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,qCAAqC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChE,IAAI,KAAK;gBAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1D,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC;AACjE,CAAC"}
1
+ {"version":3,"file":"negotiate.js","sourceRoot":"","sources":["../src/negotiate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACtC,MAAiC,EACjC,SAA4B;IAE5B,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,+EAA+E;IAC/E,8EAA8E;IAC9E,yEAAyE;IACzE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QAC/C,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,UAAU,GAAiD,EAAE,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACzC,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,qCAAqC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChE,IAAI,KAAK;gBAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,GAAG,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-tech/nk-i18n",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Type-safe, English-as-key i18n for Ingram Next.js sites — ICU translator, scopes, locale config, and Accept-Language negotiation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,14 +31,14 @@
31
31
  "test": "vitest run"
32
32
  },
33
33
  "dependencies": {
34
- "intl-messageformat": "^11.2.9"
34
+ "intl-messageformat": "^11.2.10"
35
35
  },
36
36
  "devDependencies": {
37
- "@ingram-tech/nk-dev": "0.2.5",
37
+ "@ingram-tech/nk-dev": "0.5.0",
38
38
  "@types/react": "^19.2.17",
39
39
  "react": "^19.2.7",
40
- "typescript": "^6.0.3",
41
- "vitest": "^4.1.9"
40
+ "typescript": "^7.0.2",
41
+ "vitest": "^4.1.10"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "react": "^18.0.0 || ^19.0.0"