@pyreon/i18n 0.6.0 → 0.7.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.
@@ -1,74 +1,30 @@
1
- function _notify() {
2
- for (const listener of _listeners) listener();
3
- }
1
+ //#region src/devtools.d.ts
4
2
  /**
5
- * Register an i18n instance for devtools inspection.
6
- *
7
- * @example
8
- * const i18n = createI18n({ ... })
9
- * registerI18n("app", i18n)
10
- */
11
- function registerI18n(name, instance) {
12
- _activeInstances.set(name, new WeakRef(instance));
13
- _notify();
14
- }
3
+ * @pyreon/i18n devtools introspection API.
4
+ * Import: `import { ... } from "@pyreon/i18n/devtools"`
5
+ */
6
+ /**
7
+ * Register an i18n instance for devtools inspection.
8
+ *
9
+ * @example
10
+ * const i18n = createI18n({ ... })
11
+ * registerI18n("app", i18n)
12
+ */
13
+ declare function registerI18n(name: string, instance: object): void;
15
14
  /** Unregister an i18n instance. */
16
- function unregisterI18n(name) {
17
- _activeInstances.delete(name);
18
- _notify();
19
- }
15
+ declare function unregisterI18n(name: string): void;
20
16
  /** Get all registered i18n instance names. Cleans up garbage-collected instances. */
21
- function getActiveI18nInstances() {
22
- for (const [name, ref] of _activeInstances) if (ref.deref() === void 0) _activeInstances.delete(name);
23
- return [..._activeInstances.keys()];
24
- }
17
+ declare function getActiveI18nInstances(): string[];
25
18
  /** Get an i18n instance by name (or undefined if GC'd or not registered). */
26
- function getI18nInstance(name) {
27
- const ref = _activeInstances.get(name);
28
- if (!ref) return void 0;
29
- const instance = ref.deref();
30
- if (!instance) {
31
- _activeInstances.delete(name);
32
- return;
33
- }
34
- return instance;
35
- }
36
- /** Safely read a property that may be a signal (callable). */
37
- function safeRead(obj, key, fallback = void 0) {
38
- try {
39
- const val = obj[key];
40
- return typeof val === "function" ? val() : fallback;
41
- } catch {
42
- return fallback;
43
- }
44
- }
19
+ declare function getI18nInstance(name: string): object | undefined;
45
20
  /**
46
- * Get a snapshot of an i18n instance's state.
47
- */
48
- function getI18nSnapshot(name) {
49
- const instance = getI18nInstance(name);
50
- if (!instance) return void 0;
51
- const ns = safeRead(instance, "loadedNamespaces", /* @__PURE__ */new Set());
52
- return {
53
- locale: safeRead(instance, "locale"),
54
- availableLocales: safeRead(instance, "availableLocales", []),
55
- loadedNamespaces: ns instanceof Set ? [...ns] : [],
56
- isLoading: safeRead(instance, "isLoading", false)
57
- };
58
- }
21
+ * Get a snapshot of an i18n instance's state.
22
+ */
23
+ declare function getI18nSnapshot(name: string): Record<string, unknown> | undefined;
59
24
  /** Subscribe to i18n registry changes. Returns unsubscribe function. */
60
- function onI18nChange(listener) {
61
- _listeners.add(listener);
62
- return () => {
63
- _listeners.delete(listener);
64
- };
65
- }
25
+ declare function onI18nChange(listener: () => void): () => void;
66
26
  /** @internal — reset devtools registry (for tests). */
67
- function _resetDevtools() {
68
- _activeInstances.clear();
69
- _listeners.clear();
70
- }
71
-
27
+ declare function _resetDevtools(): void;
72
28
  //#endregion
73
29
  export { _resetDevtools, getActiveI18nInstances, getI18nInstance, getI18nSnapshot, onI18nChange, registerI18n, unregisterI18n };
74
- //# sourceMappingURL=devtools.d.ts.map
30
+ //# sourceMappingURL=devtools2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.d.ts","names":[],"sources":["../../src/devtools.ts"],"mappings":"AAQA,SAAS,OAAA,CAAA,EAAgB;EACvB,KAAK,MAAM,QAAA,IAAY,UAAA,EAAY,QAAA,CAAA,CAAU;;;;;;;;;AAU/C,SAAgB,YAAA,CAAa,IAAA,EAAc,QAAA,EAAwB;EACjE,gBAAA,CAAiB,GAAA,CAAI,IAAA,EAAM,IAAI,OAAA,CAAQ,QAAA,CAAS,CAAC;EACjD,OAAA,CAAA,CAAS;;;AAIX,SAAgB,cAAA,CAAe,IAAA,EAAoB;EACjD,gBAAA,CAAiB,MAAA,CAAO,IAAA,CAAK;EAC7B,OAAA,CAAA,CAAS;;;AAIX,SAAgB,sBAAA,CAAA,EAAmC;EACjD,KAAK,MAAM,CAAC,IAAA,EAAM,GAAA,CAAA,IAAQ,gBAAA,EACxB,IAAI,GAAA,CAAI,KAAA,CAAA,CAAO,KAAK,KAAA,CAAA,EAAW,gBAAA,CAAiB,MAAA,CAAO,IAAA,CAAK;EAE9D,OAAO,CAAC,GAAG,gBAAA,CAAiB,IAAA,CAAA,CAAM,CAAC;;;AAIrC,SAAgB,eAAA,CAAgB,IAAA,EAAkC;EAChE,MAAM,GAAA,GAAM,gBAAA,CAAiB,GAAA,CAAI,IAAA,CAAK;EACtC,IAAI,CAAC,GAAA,EAAK,OAAO,KAAA,CAAA;EACjB,MAAM,QAAA,GAAW,GAAA,CAAI,KAAA,CAAA,CAAO;EAC5B,IAAI,CAAC,QAAA,EAAU;IACb,gBAAA,CAAiB,MAAA,CAAO,IAAA,CAAK;IAC7B;;EAEF,OAAO,QAAA;;;AAIT,SAAS,QAAA,CACP,GAAA,EACA,GAAA,EACA,QAAA,GAAoB,KAAA,CAAA,EACX;EACT,IAAI;IACF,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,CAAA;IAChB,OAAO,OAAO,GAAA,KAAQ,UAAA,GAAc,GAAA,CAAA,CAAuB,GAAG,QAAA;UACxD;IACN,OAAO,QAAA;;;;;;AAOX,SAAgB,eAAA,CACd,IAAA,EACqC;EACrC,MAAM,QAAA,GAAW,eAAA,CAAgB,IAAA,CAAK;EACtC,IAAI,CAAC,QAAA,EAAU,OAAO,KAAA,CAAA;EACtB,MAAM,EAAA,GAAK,QAAA,CAAS,QAAA,EAAU,kBAAA,EAAA,eAAoB,IAAI,GAAA,CAAA,CAAK,CAAC;EAC5D,OAAO;IACL,MAAA,EAAQ,QAAA,CAAS,QAAA,EAAU,QAAA,CAAS;IACpC,gBAAA,EAAkB,QAAA,CAAS,QAAA,EAAU,kBAAA,EAAoB,EAAE,CAAC;IAC5D,gBAAA,EAAkB,EAAA,YAAc,GAAA,GAAM,CAAC,GAAG,EAAA,CAAG,GAAG,EAAE;IAClD,SAAA,EAAW,QAAA,CAAS,QAAA,EAAU,WAAA,EAAa,KAAA;GAC5C;;;AAIH,SAAgB,YAAA,CAAa,QAAA,EAAkC;EAC7D,UAAA,CAAW,GAAA,CAAI,QAAA,CAAS;EACxB,OAAA,MAAa;IACX,UAAA,CAAW,MAAA,CAAO,QAAA,CAAS;;;;AAK/B,SAAgB,cAAA,CAAA,EAAuB;EACrC,gBAAA,CAAiB,KAAA,CAAA,CAAO;EACxB,UAAA,CAAW,KAAA,CAAA,CAAO"}
1
+ {"version":3,"file":"devtools2.d.ts","names":[],"sources":["../../../src/devtools.ts"],"mappings":";;AAmBA;;;;;AAMA;;;;;iBANgB,YAAA,CAAa,IAAA,UAAc,QAAA;;iBAM3B,cAAA,CAAe,IAAA;;iBAMf,sBAAA,CAAA;AAQhB;AAAA,iBAAgB,eAAA,CAAgB,IAAA;;;;iBA4BhB,eAAA,CACd,IAAA,WACC,MAAA;;iBAaa,YAAA,CAAa,QAAA;;iBAQb,cAAA,CAAA"}
@@ -1,379 +1,244 @@
1
- import { createContext, provide, useContext } from "@pyreon/core";
2
- import { computed, signal } from "@pyreon/reactivity";
3
-
4
- //#region src/context.ts
1
+ import * as _pyreon_core0 from "@pyreon/core";
2
+ import { Props, VNode, VNodeChild } from "@pyreon/core";
3
+ import { Computed, Signal } from "@pyreon/reactivity";
5
4
 
5
+ //#region src/types.d.ts
6
+ /** A nested dictionary of translation strings. */
7
+ type TranslationDictionary = {
8
+ [key: string]: string | TranslationDictionary;
9
+ };
10
+ /** Map of locale → dictionary (or namespace → dictionary). */
11
+ type TranslationMessages = Record<string, TranslationDictionary>;
6
12
  /**
7
- * Provide an i18n instance to the component tree.
8
- *
9
- * @example
10
- * const i18n = createI18n({ locale: 'en', messages: { en: { hello: 'Hello' } } })
11
- *
12
- * // In JSX:
13
- * <I18nProvider instance={i18n}>
14
- * <App />
15
- * </I18nProvider>
16
- */
17
- function I18nProvider(props) {
18
- provide(I18nContext, props.instance);
19
- const ch = props.children;
20
- return typeof ch === "function" ? ch() : ch;
13
+ * Async function that loads translations for a locale and namespace.
14
+ * Return the dictionary for that namespace, or undefined if not found.
15
+ */
16
+ type NamespaceLoader = (locale: string, namespace: string) => Promise<TranslationDictionary | undefined>;
17
+ /** Interpolation values for translation strings. */
18
+ type InterpolationValues = Record<string, string | number>;
19
+ /** Pluralization rules map — locale → function that picks the plural form. */
20
+ type PluralRules = Record<string, (count: number) => string>;
21
+ /** Options for creating an i18n instance. */
22
+ interface I18nOptions {
23
+ /** The initial locale (e.g. "en"). */
24
+ locale: string;
25
+ /** Fallback locale used when a key is missing in the active locale. */
26
+ fallbackLocale?: string;
27
+ /** Static messages keyed by locale. */
28
+ messages?: Record<string, TranslationDictionary>;
29
+ /**
30
+ * Async loader for namespace-based translation loading.
31
+ * Called with (locale, namespace) when `loadNamespace()` is invoked.
32
+ */
33
+ loader?: NamespaceLoader;
34
+ /**
35
+ * Default namespace used when `t()` is called without a namespace prefix.
36
+ * Defaults to "common".
37
+ */
38
+ defaultNamespace?: string;
39
+ /**
40
+ * Custom plural rules per locale.
41
+ * If not provided, uses `Intl.PluralRules` where available.
42
+ */
43
+ pluralRules?: PluralRules;
44
+ /**
45
+ * Missing key handler — called when a translation key is not found.
46
+ * Useful for logging, reporting, or returning a custom fallback.
47
+ */
48
+ onMissingKey?: (locale: string, key: string, namespace?: string) => string | undefined;
21
49
  }
22
- /**
23
- * Access the i18n instance from the nearest I18nProvider.
24
- * Must be called within a component tree wrapped by I18nProvider.
25
- *
26
- * @example
27
- * function Greeting() {
28
- * const { t, locale } = useI18n()
29
- * return <h1>{t('greeting', { name: 'World' })}</h1>
30
- * }
31
- */
32
- function useI18n() {
33
- const instance = useContext(I18nContext);
34
- if (!instance) throw new Error("[@pyreon/i18n] useI18n() must be used within an <I18nProvider>.");
35
- return instance;
50
+ /** The public i18n instance returned by `createI18n()`. */
51
+ interface I18nInstance {
52
+ /**
53
+ * Translate a key with optional interpolation.
54
+ * Reads the current locale reactively — re-evaluates in effects/computeds.
55
+ *
56
+ * Key format: "key" (uses default namespace) or "namespace:key".
57
+ * Nested keys use dots: "user.greeting" or "auth:errors.invalid".
58
+ *
59
+ * Interpolation: "Hello {{name}}" + { name: "Alice" } → "Hello Alice"
60
+ * Pluralization: key with "_one", "_other" etc. suffixes + { count: N }
61
+ */
62
+ t: (key: string, values?: InterpolationValues) => string;
63
+ /** Current locale (reactive signal). */
64
+ locale: Signal<string>;
65
+ /**
66
+ * Load a namespace's translations for the given locale (or current locale).
67
+ * Returns a promise that resolves when loading is complete.
68
+ */
69
+ loadNamespace: (namespace: string, locale?: string) => Promise<void>;
70
+ /**
71
+ * Whether any namespace is currently being loaded.
72
+ */
73
+ isLoading: Computed<boolean>;
74
+ /**
75
+ * Set of namespaces that have been loaded for the current locale.
76
+ */
77
+ loadedNamespaces: Computed<Set<string>>;
78
+ /**
79
+ * Check if a translation key exists in the current locale.
80
+ */
81
+ exists: (key: string) => boolean;
82
+ /**
83
+ * Add translations for a locale (merged with existing).
84
+ * Useful for adding translations at runtime without async loading.
85
+ */
86
+ addMessages: (locale: string, messages: TranslationDictionary, namespace?: string) => void;
87
+ /**
88
+ * Get all available locales (those with any registered messages).
89
+ */
90
+ availableLocales: Computed<string[]>;
36
91
  }
37
-
38
92
  //#endregion
39
- //#region src/interpolation.ts
40
-
41
- /**
42
- * Replace `{{key}}` placeholders in a string with values from the given record.
43
- * Supports optional whitespace inside braces: `{{ name }}` works too.
44
- * Unmatched placeholders are left as-is.
45
- */
46
- function interpolate(template, values) {
47
- if (!values || !template.includes("{{")) return template;
48
- return template.replace(INTERPOLATION_RE, (_, key) => {
49
- const trimmed = key.trim();
50
- const value = values[trimmed];
51
- if (value === void 0) return `{{${trimmed}}}`;
52
- try {
53
- return typeof value === "object" && value !== null ? JSON.stringify(value) : `${value}`;
54
- } catch {
55
- return `{{${trimmed}}}`;
56
- }
57
- });
93
+ //#region src/context.d.ts
94
+ declare const I18nContext: _pyreon_core0.Context<I18nInstance | null>;
95
+ interface I18nProviderProps extends Props {
96
+ instance: I18nInstance;
97
+ children?: VNodeChild;
58
98
  }
59
-
60
- //#endregion
61
- //#region src/pluralization.ts
62
99
  /**
63
- * Resolve the plural category for a given count and locale.
64
- *
65
- * Uses custom rules if provided, otherwise falls back to `Intl.PluralRules`.
66
- * Returns CLDR plural categories: "zero", "one", "two", "few", "many", "other".
67
- */
68
- function resolvePluralCategory(locale, count, customRules) {
69
- if (customRules?.[locale]) return customRules[locale](count);
70
- if (typeof Intl !== "undefined" && Intl.PluralRules) try {
71
- return new Intl.PluralRules(locale).select(count);
72
- } catch {}
73
- return count === 1 ? "one" : "other";
74
- }
75
-
76
- //#endregion
77
- //#region src/create-i18n.ts
100
+ * Provide an i18n instance to the component tree.
101
+ *
102
+ * @example
103
+ * const i18n = createI18n({ locale: 'en', messages: { en: { hello: 'Hello' } } })
104
+ *
105
+ * // In JSX:
106
+ * <I18nProvider instance={i18n}>
107
+ * <App />
108
+ * </I18nProvider>
109
+ */
110
+ declare function I18nProvider(props: I18nProviderProps): VNode;
78
111
  /**
79
- * Resolve a dot-separated key path in a nested dictionary.
80
- * E.g. "user.greeting" dictionary.user.greeting
81
- */
82
- function resolveKey(dict, keyPath) {
83
- const parts = keyPath.split(".");
84
- let current = dict;
85
- for (const part of parts) {
86
- if (current == null || typeof current === "string") return void 0;
87
- current = current[part];
88
- }
89
- return typeof current === "string" ? current : void 0;
90
- }
91
- /**
92
- * Deep-merge source into target (mutates target).
93
- */
94
- function deepMerge(target, source) {
95
- for (const key of Object.keys(source)) {
96
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
97
- const sourceVal = source[key];
98
- const targetVal = target[key];
99
- if (typeof sourceVal === "object" && sourceVal !== null && typeof targetVal === "object" && targetVal !== null) deepMerge(targetVal, sourceVal);else target[key] = sourceVal;
100
- }
101
- }
112
+ * Access the i18n instance from the nearest I18nProvider.
113
+ * Must be called within a component tree wrapped by I18nProvider.
114
+ *
115
+ * @example
116
+ * function Greeting() {
117
+ * const { t, locale } = useI18n()
118
+ * return <h1>{t('greeting', { name: 'World' })}</h1>
119
+ * }
120
+ */
121
+ declare function useI18n(): I18nInstance;
122
+ //#endregion
123
+ //#region src/create-i18n.d.ts
102
124
  /**
103
- * Create a reactive i18n instance.
104
- *
105
- * @example
106
- * const i18n = createI18n({
107
- * locale: 'en',
108
- * fallbackLocale: 'en',
109
- * messages: {
110
- * en: { greeting: 'Hello {{name}}!' },
111
- * de: { greeting: 'Hallo {{name}}!' },
112
- * },
113
- * })
114
- *
115
- * // Reactive translation — re-evaluates on locale change
116
- * i18n.t('greeting', { name: 'Alice' }) // "Hello Alice!"
117
- * i18n.locale.set('de')
118
- * i18n.t('greeting', { name: 'Alice' }) // "Hallo Alice!"
119
- *
120
- * @example
121
- * // Async namespace loading
122
- * const i18n = createI18n({
123
- * locale: 'en',
124
- * loader: async (locale, namespace) => {
125
- * const mod = await import(`./locales/${locale}/${namespace}.json`)
126
- * return mod.default
127
- * },
128
- * })
129
- * await i18n.loadNamespace('auth')
130
- * i18n.t('auth:errors.invalid') // looks up "errors.invalid" in "auth" namespace
131
- */
132
- function createI18n(options) {
133
- const {
134
- fallbackLocale,
135
- loader,
136
- defaultNamespace = "common",
137
- pluralRules,
138
- onMissingKey
139
- } = options;
140
- const locale = signal(options.locale);
141
- const store = /* @__PURE__ */new Map();
142
- const storeVersion = signal(0);
143
- const pendingLoads = signal(0);
144
- const loadedNsVersion = signal(0);
145
- const pendingPromises = /* @__PURE__ */new Map();
146
- const isLoading = computed(() => pendingLoads() > 0);
147
- const loadedNamespaces = computed(() => {
148
- loadedNsVersion();
149
- const currentLocale = locale();
150
- const nsMap = store.get(currentLocale);
151
- return new Set(nsMap ? nsMap.keys() : []);
152
- });
153
- const availableLocales = computed(() => {
154
- storeVersion();
155
- return [...store.keys()];
156
- });
157
- if (options.messages) for (const [loc, dict] of Object.entries(options.messages)) {
158
- const nsMap = /* @__PURE__ */new Map();
159
- nsMap.set(defaultNamespace, dict);
160
- store.set(loc, nsMap);
161
- }
162
- function getNamespaceMap(loc) {
163
- let nsMap = store.get(loc);
164
- if (!nsMap) {
165
- nsMap = /* @__PURE__ */new Map();
166
- store.set(loc, nsMap);
167
- }
168
- return nsMap;
169
- }
170
- function lookupKey(loc, namespace, keyPath) {
171
- const nsMap = store.get(loc);
172
- if (!nsMap) return void 0;
173
- const dict = nsMap.get(namespace);
174
- if (!dict) return void 0;
175
- return resolveKey(dict, keyPath);
176
- }
177
- function resolveTranslation(key, values) {
178
- const currentLocale = locale();
179
- storeVersion();
180
- let namespace = defaultNamespace;
181
- let keyPath = key;
182
- const colonIndex = key.indexOf(":");
183
- if (colonIndex > 0) {
184
- namespace = key.slice(0, colonIndex);
185
- keyPath = key.slice(colonIndex + 1);
186
- }
187
- if (values && "count" in values) {
188
- const category = resolvePluralCategory(currentLocale, Number(values.count), pluralRules);
189
- const pluralKey = `${keyPath}_${category}`;
190
- const pluralResult = lookupKey(currentLocale, namespace, pluralKey) ?? (fallbackLocale ? lookupKey(fallbackLocale, namespace, pluralKey) : void 0);
191
- if (pluralResult) return interpolate(pluralResult, values);
192
- }
193
- const result = lookupKey(currentLocale, namespace, keyPath) ?? (fallbackLocale ? lookupKey(fallbackLocale, namespace, keyPath) : void 0);
194
- if (result !== void 0) return interpolate(result, values);
195
- if (onMissingKey) {
196
- const custom = onMissingKey(currentLocale, key, namespace);
197
- if (custom !== void 0) return custom;
198
- }
199
- return key;
200
- }
201
- const t = (key, values) => {
202
- return resolveTranslation(key, values);
203
- };
204
- const loadNamespace = async (namespace, loc) => {
205
- if (!loader) return;
206
- const targetLocale = loc ?? locale.peek();
207
- const cacheKey = `${targetLocale}:${namespace}`;
208
- const nsMap = getNamespaceMap(targetLocale);
209
- if (nsMap.has(namespace)) return;
210
- const existing = pendingPromises.get(cacheKey);
211
- if (existing) return existing;
212
- pendingLoads.update(n => n + 1);
213
- const promise = loader(targetLocale, namespace).then(dict => {
214
- if (dict) {
215
- nsMap.set(namespace, dict);
216
- storeVersion.update(n => n + 1);
217
- loadedNsVersion.update(n => n + 1);
218
- }
219
- }).finally(() => {
220
- pendingPromises.delete(cacheKey);
221
- pendingLoads.update(n => n - 1);
222
- });
223
- pendingPromises.set(cacheKey, promise);
224
- return promise;
225
- };
226
- const exists = key => {
227
- const currentLocale = locale.peek();
228
- let namespace = defaultNamespace;
229
- let keyPath = key;
230
- const colonIndex = key.indexOf(":");
231
- if (colonIndex > 0) {
232
- namespace = key.slice(0, colonIndex);
233
- keyPath = key.slice(colonIndex + 1);
234
- }
235
- return lookupKey(currentLocale, namespace, keyPath) !== void 0 || (fallbackLocale ? lookupKey(fallbackLocale, namespace, keyPath) !== void 0 : false);
236
- };
237
- const addMessages = (loc, messages, namespace) => {
238
- const ns = namespace ?? defaultNamespace;
239
- const nsMap = getNamespaceMap(loc);
240
- const existing = nsMap.get(ns);
241
- if (existing) deepMerge(existing, messages);else {
242
- const cloned = {};
243
- deepMerge(cloned, messages);
244
- nsMap.set(ns, cloned);
245
- }
246
- storeVersion.update(n => n + 1);
247
- loadedNsVersion.update(n => n + 1);
248
- };
249
- return {
250
- t,
251
- locale,
252
- loadNamespace,
253
- isLoading,
254
- loadedNamespaces,
255
- exists,
256
- addMessages,
257
- availableLocales
258
- };
259
- }
260
-
125
+ * Create a reactive i18n instance.
126
+ *
127
+ * @example
128
+ * const i18n = createI18n({
129
+ * locale: 'en',
130
+ * fallbackLocale: 'en',
131
+ * messages: {
132
+ * en: { greeting: 'Hello {{name}}!' },
133
+ * de: { greeting: 'Hallo {{name}}!' },
134
+ * },
135
+ * })
136
+ *
137
+ * // Reactive translation — re-evaluates on locale change
138
+ * i18n.t('greeting', { name: 'Alice' }) // "Hello Alice!"
139
+ * i18n.locale.set('de')
140
+ * i18n.t('greeting', { name: 'Alice' }) // "Hallo Alice!"
141
+ *
142
+ * @example
143
+ * // Async namespace loading
144
+ * const i18n = createI18n({
145
+ * locale: 'en',
146
+ * loader: async (locale, namespace) => {
147
+ * const mod = await import(`./locales/${locale}/${namespace}.json`)
148
+ * return mod.default
149
+ * },
150
+ * })
151
+ * await i18n.loadNamespace('auth')
152
+ * i18n.t('auth:errors.invalid') // looks up "errors.invalid" in "auth" namespace
153
+ */
154
+ declare function createI18n(options: I18nOptions): I18nInstance;
261
155
  //#endregion
262
- //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
263
- /** Marker for fragment nodes — renders children without a wrapper element */
264
-
265
- function h(type, props, ...children) {
266
- return {
267
- type,
268
- props: props ?? EMPTY_PROPS,
269
- children: normalizeChildren(children),
270
- key: props?.key ?? null
271
- };
272
- }
273
- function normalizeChildren(children) {
274
- for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
275
- return children;
276
- }
277
- function flattenChildren(children) {
278
- const result = [];
279
- for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));else result.push(child);
280
- return result;
281
- }
156
+ //#region src/interpolation.d.ts
282
157
  /**
283
- * JSX automatic runtime.
284
- *
285
- * When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
286
- * rewrites JSX to imports from this file automatically:
287
- * <div class="x" /> → jsx("div", { class: "x" })
288
- */
289
- function jsx(type, props, key) {
290
- const {
291
- children,
292
- ...rest
293
- } = props;
294
- const propsWithKey = key != null ? {
295
- ...rest,
296
- key
297
- } : rest;
298
- if (typeof type === "function") return h(type, children !== void 0 ? {
299
- ...propsWithKey,
300
- children
301
- } : propsWithKey);
302
- return h(type, propsWithKey, ...(children === void 0 ? [] : Array.isArray(children) ? children : [children]));
303
- }
304
-
158
+ * Replace `{{key}}` placeholders in a string with values from the given record.
159
+ * Supports optional whitespace inside braces: `{{ name }}` works too.
160
+ * Unmatched placeholders are left as-is.
161
+ */
162
+ declare function interpolate(template: string, values?: InterpolationValues): string;
305
163
  //#endregion
306
- //#region src/trans.tsx
307
-
164
+ //#region src/pluralization.d.ts
308
165
  /**
309
- * Parse a translated string into an array of plain text and rich tag segments.
310
- *
311
- * @example
312
- * parseRichText("Hello <bold>world</bold>, click <link>here</link>")
313
- * // → ["Hello ", { tag: "bold", children: "world" }, ", click ", { tag: "link", children: "here" }]
314
- */
315
- function parseRichText(text) {
316
- const parts = [];
317
- let lastIndex = 0;
318
- for (const match of text.matchAll(TAG_RE)) {
319
- const before = text.slice(lastIndex, match.index);
320
- if (before) parts.push(before);
321
- parts.push({
322
- tag: match[1],
323
- children: match[2]
324
- });
325
- lastIndex = match.index + match[0].length;
326
- }
327
- const after = text.slice(lastIndex);
328
- if (after) parts.push(after);
329
- return parts;
166
+ * Resolve the plural category for a given count and locale.
167
+ *
168
+ * Uses custom rules if provided, otherwise falls back to `Intl.PluralRules`.
169
+ * Returns CLDR plural categories: "zero", "one", "two", "few", "many", "other".
170
+ */
171
+ declare function resolvePluralCategory(locale: string, count: number, customRules?: PluralRules): string;
172
+ //#endregion
173
+ //#region src/trans.d.ts
174
+ interface RichPart {
175
+ tag: string;
176
+ children: string;
330
177
  }
331
178
  /**
332
- * Rich JSX interpolation component for translations.
333
- *
334
- * Allows embedding JSX components within translated strings using XML-like tags.
335
- * The `t` function resolves the translation and interpolates `{{values}}` first,
336
- * then `<tag>content</tag>` patterns are mapped to the provided components.
337
- *
338
- * @example
339
- * // Translation: "You have <bold>{{count}}</bold> unread messages"
340
- * const { t } = useI18n()
341
- * <Trans
342
- * t={t}
343
- * i18nKey="messages.unread"
344
- * values={{ count: 5 }}
345
- * components={{
346
- * bold: (children) => <strong>{children}</strong>,
347
- * }}
348
- * />
349
- * // Renders: You have <strong>5</strong> unread messages
350
- *
351
- * @example
352
- * // Translation: "Read our <terms>terms of service</terms> and <privacy>privacy policy</privacy>"
353
- * <Trans
354
- * t={t}
355
- * i18nKey="legal"
356
- * components={{
357
- * terms: (children) => <a href="/terms">{children}</a>,
358
- * privacy: (children) => <a href="/privacy">{children}</a>,
359
- * }}
360
- * />
361
- */
362
- function Trans(props) {
363
- const translated = props.t(props.i18nKey, props.values);
364
- if (!props.components) return translated;
365
- const parts = parseRichText(translated);
366
- if (parts.length === 1 && typeof parts[0] === "string") return parts[0];
367
- return /* @__PURE__ */jsx(Fragment, {
368
- children: parts.map(part => {
369
- if (typeof part === "string") return part;
370
- const component = props.components[part.tag];
371
- if (!component) return part.children;
372
- return component(part.children);
373
- })
374
- });
179
+ * Parse a translated string into an array of plain text and rich tag segments.
180
+ *
181
+ * @example
182
+ * parseRichText("Hello <bold>world</bold>, click <link>here</link>")
183
+ * // → ["Hello ", { tag: "bold", children: "world" }, ", click ", { tag: "link", children: "here" }]
184
+ */
185
+ declare function parseRichText(text: string): (string | RichPart)[];
186
+ interface TransProps extends Props {
187
+ /** Translation key (supports namespace:key syntax). */
188
+ i18nKey: string;
189
+ /** Interpolation values for {{placeholder}} syntax. */
190
+ values?: InterpolationValues;
191
+ /**
192
+ * Component map for rich interpolation.
193
+ * Keys match tag names in the translation string.
194
+ * Values are component functions: `(children: any) => VNode`
195
+ *
196
+ * @example
197
+ * // Translation: "Read the <terms>terms</terms> and <privacy>policy</privacy>"
198
+ * components={{
199
+ * terms: (children) => <a href="/terms">{children}</a>,
200
+ * privacy: (children) => <a href="/privacy">{children}</a>,
201
+ * }}
202
+ */
203
+ components?: Record<string, (children: any) => any>;
204
+ /**
205
+ * The i18n instance's `t` function.
206
+ * Can be obtained from `useI18n()` or passed directly.
207
+ */
208
+ t: (key: string, values?: InterpolationValues) => string;
375
209
  }
376
-
210
+ /**
211
+ * Rich JSX interpolation component for translations.
212
+ *
213
+ * Allows embedding JSX components within translated strings using XML-like tags.
214
+ * The `t` function resolves the translation and interpolates `{{values}}` first,
215
+ * then `<tag>content</tag>` patterns are mapped to the provided components.
216
+ *
217
+ * @example
218
+ * // Translation: "You have <bold>{{count}}</bold> unread messages"
219
+ * const { t } = useI18n()
220
+ * <Trans
221
+ * t={t}
222
+ * i18nKey="messages.unread"
223
+ * values={{ count: 5 }}
224
+ * components={{
225
+ * bold: (children) => <strong>{children}</strong>,
226
+ * }}
227
+ * />
228
+ * // Renders: You have <strong>5</strong> unread messages
229
+ *
230
+ * @example
231
+ * // Translation: "Read our <terms>terms of service</terms> and <privacy>privacy policy</privacy>"
232
+ * <Trans
233
+ * t={t}
234
+ * i18nKey="legal"
235
+ * components={{
236
+ * terms: (children) => <a href="/terms">{children}</a>,
237
+ * privacy: (children) => <a href="/privacy">{children}</a>,
238
+ * }}
239
+ * />
240
+ */
241
+ declare function Trans(props: TransProps): VNode | string;
377
242
  //#endregion
378
- export { I18nContext, I18nProvider, Trans, createI18n, interpolate, parseRichText, resolvePluralCategory, useI18n };
379
- //# sourceMappingURL=index.d.ts.map
243
+ export { I18nContext, type I18nInstance, type I18nOptions, I18nProvider, type I18nProviderProps, type InterpolationValues, type NamespaceLoader, type PluralRules, Trans, type TransProps, type TranslationDictionary, type TranslationMessages, createI18n, interpolate, parseRichText, resolvePluralCategory, useI18n };
244
+ //# sourceMappingURL=index2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/context.ts","../../src/interpolation.ts","../../src/pluralization.ts","../../src/create-i18n.ts","../../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../../src/trans.tsx"],"x_google_ignoreList":[4],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/types.ts","../../../src/context.ts","../../../src/create-i18n.ts","../../../src/interpolation.ts","../../../src/pluralization.ts","../../../src/trans.tsx"],"mappings":";;;;;;KAGY,qBAAA;EAAA,CACT,GAAA,oBAAuB,qBAAA;AAAA;AAD1B;AAAA,KAKY,mBAAA,GAAsB,MAAA,SAAe,qBAAA;;;;AAAjD;KAMY,eAAA,IACV,MAAA,UACA,SAAA,aACG,OAAA,CAAQ,qBAAA;;KAGD,mBAAA,GAAsB,MAAA;;KAGtB,WAAA,GAAc,MAAA,UAAgB,KAAA;;UAGzB,WAAA;EATL;EAWV,MAAA;EAZA;EAcA,cAAA;EAbW;EAeX,QAAA,GAAW,MAAA,SAAe,qBAAA;EAfM;AAGlC;;;EAiBE,MAAA,GAAS,eAAA;EAjB6B;AAGxC;;;EAmBE,gBAAA;EAnBqD;AAGvD;;;EAqBE,WAAA,GAAc,WAAA;EAfH;;;;EAoBX,YAAA,IACE,MAAA,UACA,GAAA,UACA,SAAA;AAAA;;UAKa,YAAA;EA5BJ;;;;;;;;;;EAuCX,CAAA,GAAI,GAAA,UAAa,MAAA,GAAS,mBAAA;EAhBN;EAmBpB,MAAA,EAAQ,MAAA;EAdO;;;;EAoBf,aAAA,GAAgB,SAAA,UAAmB,MAAA,cAAoB,OAAA;EAAA;;;EAKvD,SAAA,EAAW,QAAA;EAkBC;;;EAbZ,gBAAA,EAAkB,QAAA,CAAS,GAAA;EAnB3B;;;EAwBA,MAAA,GAAS,GAAA;EArBT;;;;EA2BA,WAAA,GACE,MAAA,UACA,QAAA,EAAU,qBAAA,EACV,SAAA;EAxBqD;;;EA8BvD,gBAAA,EAAkB,QAAA;AAAA;;;cC1GP,WAAA,EAAW,aAAA,CAAA,OAAA,CAAA,YAAA;AAAA,UAEP,iBAAA,SAA0B,KAAA;EACzC,QAAA,EAAU,YAAA;EACV,QAAA,GAAW,UAAA;AAAA;;;;ADAb;;;;;AAMA;;;iBCQgB,YAAA,CAAa,KAAA,EAAO,iBAAA,GAAoB,KAAA;;;;;;;ADFxD;;;;iBCmBgB,OAAA,CAAA,GAAW,YAAA;;;;;;;ADpC3B;;;;;AAKA;;;;;AAMA;;;;;;;;;;AAMA;;;;;AAGA;iBEgEgB,UAAA,CAAW,OAAA,EAAS,WAAA,GAAc,YAAA;;;;;;;AFpFlD;iBGMgB,WAAA,CACd,QAAA,UACA,MAAA,GAAS,mBAAA;;;;;;;AHRX;;iBIKgB,qBAAA,CACd,MAAA,UACA,KAAA,UACA,WAAA,GAAc,WAAA;;;UCNN,QAAA;EACR,GAAA;EACA,QAAA;AAAA;;;;;ALCF;;;iBKSgB,aAAA,CAAc,IAAA,qBAAyB,QAAA;AAAA,UAiBtC,UAAA,SAAmB,KAAA;ELpBxB;EKsBV,OAAA;;EAEA,MAAA,GAAS,mBAAA;ELvBT;;;;;;AAKF;;;;;AAGA;EK4BE,UAAA,GAAa,MAAA,UAAgB,QAAA;;;;ALzB/B;EK8BE,CAAA,GAAI,GAAA,UAAa,MAAA,GAAS,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;ALI5B;;;;;;;;;iBK8BgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,KAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/i18n",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Reactive internationalization for Pyreon with async namespace loading",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,30 +0,0 @@
1
- //#region src/devtools.d.ts
2
- /**
3
- * @pyreon/i18n devtools introspection API.
4
- * Import: `import { ... } from "@pyreon/i18n/devtools"`
5
- */
6
- /**
7
- * Register an i18n instance for devtools inspection.
8
- *
9
- * @example
10
- * const i18n = createI18n({ ... })
11
- * registerI18n("app", i18n)
12
- */
13
- declare function registerI18n(name: string, instance: object): void;
14
- /** Unregister an i18n instance. */
15
- declare function unregisterI18n(name: string): void;
16
- /** Get all registered i18n instance names. Cleans up garbage-collected instances. */
17
- declare function getActiveI18nInstances(): string[];
18
- /** Get an i18n instance by name (or undefined if GC'd or not registered). */
19
- declare function getI18nInstance(name: string): object | undefined;
20
- /**
21
- * Get a snapshot of an i18n instance's state.
22
- */
23
- declare function getI18nSnapshot(name: string): Record<string, unknown> | undefined;
24
- /** Subscribe to i18n registry changes. Returns unsubscribe function. */
25
- declare function onI18nChange(listener: () => void): () => void;
26
- /** @internal — reset devtools registry (for tests). */
27
- declare function _resetDevtools(): void;
28
- //#endregion
29
- export { _resetDevtools, getActiveI18nInstances, getI18nInstance, getI18nSnapshot, onI18nChange, registerI18n, unregisterI18n };
30
- //# sourceMappingURL=devtools2.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools2.d.ts","names":[],"sources":["../../src/devtools.ts"],"mappings":";;AAmBA;;;;;AAMA;;;;;iBANgB,YAAA,CAAa,IAAA,UAAc,QAAA;;iBAM3B,cAAA,CAAe,IAAA;;iBAMf,sBAAA,CAAA;AAQhB;AAAA,iBAAgB,eAAA,CAAgB,IAAA;;;;iBA4BhB,eAAA,CACd,IAAA,WACC,MAAA;;iBAaa,YAAA,CAAa,QAAA;;iBAQb,cAAA,CAAA"}
@@ -1,244 +0,0 @@
1
- import * as _pyreon_core0 from "@pyreon/core";
2
- import { Props, VNode, VNodeChild } from "@pyreon/core";
3
- import { Computed, Signal } from "@pyreon/reactivity";
4
-
5
- //#region src/types.d.ts
6
- /** A nested dictionary of translation strings. */
7
- type TranslationDictionary = {
8
- [key: string]: string | TranslationDictionary;
9
- };
10
- /** Map of locale → dictionary (or namespace → dictionary). */
11
- type TranslationMessages = Record<string, TranslationDictionary>;
12
- /**
13
- * Async function that loads translations for a locale and namespace.
14
- * Return the dictionary for that namespace, or undefined if not found.
15
- */
16
- type NamespaceLoader = (locale: string, namespace: string) => Promise<TranslationDictionary | undefined>;
17
- /** Interpolation values for translation strings. */
18
- type InterpolationValues = Record<string, string | number>;
19
- /** Pluralization rules map — locale → function that picks the plural form. */
20
- type PluralRules = Record<string, (count: number) => string>;
21
- /** Options for creating an i18n instance. */
22
- interface I18nOptions {
23
- /** The initial locale (e.g. "en"). */
24
- locale: string;
25
- /** Fallback locale used when a key is missing in the active locale. */
26
- fallbackLocale?: string;
27
- /** Static messages keyed by locale. */
28
- messages?: Record<string, TranslationDictionary>;
29
- /**
30
- * Async loader for namespace-based translation loading.
31
- * Called with (locale, namespace) when `loadNamespace()` is invoked.
32
- */
33
- loader?: NamespaceLoader;
34
- /**
35
- * Default namespace used when `t()` is called without a namespace prefix.
36
- * Defaults to "common".
37
- */
38
- defaultNamespace?: string;
39
- /**
40
- * Custom plural rules per locale.
41
- * If not provided, uses `Intl.PluralRules` where available.
42
- */
43
- pluralRules?: PluralRules;
44
- /**
45
- * Missing key handler — called when a translation key is not found.
46
- * Useful for logging, reporting, or returning a custom fallback.
47
- */
48
- onMissingKey?: (locale: string, key: string, namespace?: string) => string | undefined;
49
- }
50
- /** The public i18n instance returned by `createI18n()`. */
51
- interface I18nInstance {
52
- /**
53
- * Translate a key with optional interpolation.
54
- * Reads the current locale reactively — re-evaluates in effects/computeds.
55
- *
56
- * Key format: "key" (uses default namespace) or "namespace:key".
57
- * Nested keys use dots: "user.greeting" or "auth:errors.invalid".
58
- *
59
- * Interpolation: "Hello {{name}}" + { name: "Alice" } → "Hello Alice"
60
- * Pluralization: key with "_one", "_other" etc. suffixes + { count: N }
61
- */
62
- t: (key: string, values?: InterpolationValues) => string;
63
- /** Current locale (reactive signal). */
64
- locale: Signal<string>;
65
- /**
66
- * Load a namespace's translations for the given locale (or current locale).
67
- * Returns a promise that resolves when loading is complete.
68
- */
69
- loadNamespace: (namespace: string, locale?: string) => Promise<void>;
70
- /**
71
- * Whether any namespace is currently being loaded.
72
- */
73
- isLoading: Computed<boolean>;
74
- /**
75
- * Set of namespaces that have been loaded for the current locale.
76
- */
77
- loadedNamespaces: Computed<Set<string>>;
78
- /**
79
- * Check if a translation key exists in the current locale.
80
- */
81
- exists: (key: string) => boolean;
82
- /**
83
- * Add translations for a locale (merged with existing).
84
- * Useful for adding translations at runtime without async loading.
85
- */
86
- addMessages: (locale: string, messages: TranslationDictionary, namespace?: string) => void;
87
- /**
88
- * Get all available locales (those with any registered messages).
89
- */
90
- availableLocales: Computed<string[]>;
91
- }
92
- //#endregion
93
- //#region src/context.d.ts
94
- declare const I18nContext: _pyreon_core0.Context<I18nInstance | null>;
95
- interface I18nProviderProps extends Props {
96
- instance: I18nInstance;
97
- children?: VNodeChild;
98
- }
99
- /**
100
- * Provide an i18n instance to the component tree.
101
- *
102
- * @example
103
- * const i18n = createI18n({ locale: 'en', messages: { en: { hello: 'Hello' } } })
104
- *
105
- * // In JSX:
106
- * <I18nProvider instance={i18n}>
107
- * <App />
108
- * </I18nProvider>
109
- */
110
- declare function I18nProvider(props: I18nProviderProps): VNode;
111
- /**
112
- * Access the i18n instance from the nearest I18nProvider.
113
- * Must be called within a component tree wrapped by I18nProvider.
114
- *
115
- * @example
116
- * function Greeting() {
117
- * const { t, locale } = useI18n()
118
- * return <h1>{t('greeting', { name: 'World' })}</h1>
119
- * }
120
- */
121
- declare function useI18n(): I18nInstance;
122
- //#endregion
123
- //#region src/create-i18n.d.ts
124
- /**
125
- * Create a reactive i18n instance.
126
- *
127
- * @example
128
- * const i18n = createI18n({
129
- * locale: 'en',
130
- * fallbackLocale: 'en',
131
- * messages: {
132
- * en: { greeting: 'Hello {{name}}!' },
133
- * de: { greeting: 'Hallo {{name}}!' },
134
- * },
135
- * })
136
- *
137
- * // Reactive translation — re-evaluates on locale change
138
- * i18n.t('greeting', { name: 'Alice' }) // "Hello Alice!"
139
- * i18n.locale.set('de')
140
- * i18n.t('greeting', { name: 'Alice' }) // "Hallo Alice!"
141
- *
142
- * @example
143
- * // Async namespace loading
144
- * const i18n = createI18n({
145
- * locale: 'en',
146
- * loader: async (locale, namespace) => {
147
- * const mod = await import(`./locales/${locale}/${namespace}.json`)
148
- * return mod.default
149
- * },
150
- * })
151
- * await i18n.loadNamespace('auth')
152
- * i18n.t('auth:errors.invalid') // looks up "errors.invalid" in "auth" namespace
153
- */
154
- declare function createI18n(options: I18nOptions): I18nInstance;
155
- //#endregion
156
- //#region src/interpolation.d.ts
157
- /**
158
- * Replace `{{key}}` placeholders in a string with values from the given record.
159
- * Supports optional whitespace inside braces: `{{ name }}` works too.
160
- * Unmatched placeholders are left as-is.
161
- */
162
- declare function interpolate(template: string, values?: InterpolationValues): string;
163
- //#endregion
164
- //#region src/pluralization.d.ts
165
- /**
166
- * Resolve the plural category for a given count and locale.
167
- *
168
- * Uses custom rules if provided, otherwise falls back to `Intl.PluralRules`.
169
- * Returns CLDR plural categories: "zero", "one", "two", "few", "many", "other".
170
- */
171
- declare function resolvePluralCategory(locale: string, count: number, customRules?: PluralRules): string;
172
- //#endregion
173
- //#region src/trans.d.ts
174
- interface RichPart {
175
- tag: string;
176
- children: string;
177
- }
178
- /**
179
- * Parse a translated string into an array of plain text and rich tag segments.
180
- *
181
- * @example
182
- * parseRichText("Hello <bold>world</bold>, click <link>here</link>")
183
- * // → ["Hello ", { tag: "bold", children: "world" }, ", click ", { tag: "link", children: "here" }]
184
- */
185
- declare function parseRichText(text: string): (string | RichPart)[];
186
- interface TransProps extends Props {
187
- /** Translation key (supports namespace:key syntax). */
188
- i18nKey: string;
189
- /** Interpolation values for {{placeholder}} syntax. */
190
- values?: InterpolationValues;
191
- /**
192
- * Component map for rich interpolation.
193
- * Keys match tag names in the translation string.
194
- * Values are component functions: `(children: any) => VNode`
195
- *
196
- * @example
197
- * // Translation: "Read the <terms>terms</terms> and <privacy>policy</privacy>"
198
- * components={{
199
- * terms: (children) => <a href="/terms">{children}</a>,
200
- * privacy: (children) => <a href="/privacy">{children}</a>,
201
- * }}
202
- */
203
- components?: Record<string, (children: any) => any>;
204
- /**
205
- * The i18n instance's `t` function.
206
- * Can be obtained from `useI18n()` or passed directly.
207
- */
208
- t: (key: string, values?: InterpolationValues) => string;
209
- }
210
- /**
211
- * Rich JSX interpolation component for translations.
212
- *
213
- * Allows embedding JSX components within translated strings using XML-like tags.
214
- * The `t` function resolves the translation and interpolates `{{values}}` first,
215
- * then `<tag>content</tag>` patterns are mapped to the provided components.
216
- *
217
- * @example
218
- * // Translation: "You have <bold>{{count}}</bold> unread messages"
219
- * const { t } = useI18n()
220
- * <Trans
221
- * t={t}
222
- * i18nKey="messages.unread"
223
- * values={{ count: 5 }}
224
- * components={{
225
- * bold: (children) => <strong>{children}</strong>,
226
- * }}
227
- * />
228
- * // Renders: You have <strong>5</strong> unread messages
229
- *
230
- * @example
231
- * // Translation: "Read our <terms>terms of service</terms> and <privacy>privacy policy</privacy>"
232
- * <Trans
233
- * t={t}
234
- * i18nKey="legal"
235
- * components={{
236
- * terms: (children) => <a href="/terms">{children}</a>,
237
- * privacy: (children) => <a href="/privacy">{children}</a>,
238
- * }}
239
- * />
240
- */
241
- declare function Trans(props: TransProps): VNode | string;
242
- //#endregion
243
- export { I18nContext, type I18nInstance, type I18nOptions, I18nProvider, type I18nProviderProps, type InterpolationValues, type NamespaceLoader, type PluralRules, Trans, type TransProps, type TranslationDictionary, type TranslationMessages, createI18n, interpolate, parseRichText, resolvePluralCategory, useI18n };
244
- //# sourceMappingURL=index2.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/context.ts","../../src/create-i18n.ts","../../src/interpolation.ts","../../src/pluralization.ts","../../src/trans.tsx"],"mappings":";;;;;;KAGY,qBAAA;EAAA,CACT,GAAA,oBAAuB,qBAAA;AAAA;AAD1B;AAAA,KAKY,mBAAA,GAAsB,MAAA,SAAe,qBAAA;;;;AAAjD;KAMY,eAAA,IACV,MAAA,UACA,SAAA,aACG,OAAA,CAAQ,qBAAA;;KAGD,mBAAA,GAAsB,MAAA;;KAGtB,WAAA,GAAc,MAAA,UAAgB,KAAA;;UAGzB,WAAA;EATL;EAWV,MAAA;EAZA;EAcA,cAAA;EAbW;EAeX,QAAA,GAAW,MAAA,SAAe,qBAAA;EAfM;AAGlC;;;EAiBE,MAAA,GAAS,eAAA;EAjB6B;AAGxC;;;EAmBE,gBAAA;EAnBqD;AAGvD;;;EAqBE,WAAA,GAAc,WAAA;EAfH;;;;EAoBX,YAAA,IACE,MAAA,UACA,GAAA,UACA,SAAA;AAAA;;UAKa,YAAA;EA5BJ;;;;;;;;;;EAuCX,CAAA,GAAI,GAAA,UAAa,MAAA,GAAS,mBAAA;EAhBN;EAmBpB,MAAA,EAAQ,MAAA;EAdO;;;;EAoBf,aAAA,GAAgB,SAAA,UAAmB,MAAA,cAAoB,OAAA;EAAA;;;EAKvD,SAAA,EAAW,QAAA;EAkBC;;;EAbZ,gBAAA,EAAkB,QAAA,CAAS,GAAA;EAnB3B;;;EAwBA,MAAA,GAAS,GAAA;EArBT;;;;EA2BA,WAAA,GACE,MAAA,UACA,QAAA,EAAU,qBAAA,EACV,SAAA;EAxBqD;;;EA8BvD,gBAAA,EAAkB,QAAA;AAAA;;;cC1GP,WAAA,EAAW,aAAA,CAAA,OAAA,CAAA,YAAA;AAAA,UAEP,iBAAA,SAA0B,KAAA;EACzC,QAAA,EAAU,YAAA;EACV,QAAA,GAAW,UAAA;AAAA;;;;ADAb;;;;;AAMA;;;iBCQgB,YAAA,CAAa,KAAA,EAAO,iBAAA,GAAoB,KAAA;;;;;;;ADFxD;;;;iBCmBgB,OAAA,CAAA,GAAW,YAAA;;;;;;;ADpC3B;;;;;AAKA;;;;;AAMA;;;;;;;;;;AAMA;;;;;AAGA;iBEgEgB,UAAA,CAAW,OAAA,EAAS,WAAA,GAAc,YAAA;;;;;;;AFpFlD;iBGMgB,WAAA,CACd,QAAA,UACA,MAAA,GAAS,mBAAA;;;;;;;AHRX;;iBIKgB,qBAAA,CACd,MAAA,UACA,KAAA,UACA,WAAA,GAAc,WAAA;;;UCNN,QAAA;EACR,GAAA;EACA,QAAA;AAAA;;;;;ALCF;;;iBKSgB,aAAA,CAAc,IAAA,qBAAyB,QAAA;AAAA,UAiBtC,UAAA,SAAmB,KAAA;ELpBxB;EKsBV,OAAA;;EAEA,MAAA,GAAS,mBAAA;ELvBT;;;;;;AAKF;;;;;AAGA;EK4BE,UAAA,GAAa,MAAA,UAAgB,QAAA;;;;ALzB/B;EK8BE,CAAA,GAAI,GAAA,UAAa,MAAA,GAAS,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;ALI5B;;;;;;;;;iBK8BgB,KAAA,CAAM,KAAA,EAAO,UAAA,GAAa,KAAA"}