@comvi/vue 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Comvi (https://comvi.io)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,277 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="../../.github/assets/header-logo-dark.png">
4
+ <img alt="Comvi" src="../../.github/assets/header-logo-light.png" width="860">
5
+ </picture>
6
+ </p>
7
+
8
+ <h1 align="center">@comvi/vue</h1>
9
+
10
+ <p align="center">Vue 3 binding for Comvi i18n โ€” plugin, composable, and <code>&lt;T&gt;</code> component.</p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/@comvi/vue"><img src="https://img.shields.io/npm/v/@comvi/vue?color=blue" alt="npm"></a>
14
+ <a href="https://bundlejs.com/?q=%40comvi%2Fvue"><img src="https://deno.bundlejs.com/?q=@comvi/vue&badge=&badge-style=flat&badge-raster" alt="Bundle size"></a>
15
+ <a href="https://github.com/comvi-io/comvi-js/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
16
+ </p>
17
+
18
+ ---
19
+
20
+ `@comvi/vue` wraps [`@comvi/core`](../core) for Vue 3. `app.use(i18n)` installs `$t` and `$i18n` global properties; `useI18n()` returns reactive refs that integrate with Vue's reactivity system.
21
+
22
+ Same `t()` and `<T>` API as the [React](../react), [SolidJS](../solid), and [Svelte](../svelte) bindings โ€” switch frameworks without relearning your i18n layer.
23
+
24
+ For Nuxt 3, use [`@comvi/nuxt`](../nuxt) โ€” it adds SSR, locale routing, and auto-imports on top of this package.
25
+
26
+ ๐Ÿ“– **Documentation:** https://comvi.io/docs/i18n/vue/
27
+
28
+ ## Why Comvi i18n?
29
+
30
+ Comvi i18n is a modern, framework-agnostic internationalization library built on three principles: type-safe translations, real ICU MessageFormat, and zero compromises on bundle size or security.
31
+
32
+ - **Rich text without XSS.** Embed components inside translation strings (`Click <link>here</link>`) โ€” translators see clean markup, you decide what each tag renders to. No raw HTML, no unsafe DOM injection, no splitting a sentence across template fragments.
33
+ - **Real ICU MessageFormat.** Plurals, ordinals, and select all follow locale-correct grammar via `Intl.PluralRules` โ€” Polish, Ukrainian, Arabic, Welsh, and the rest. Same syntax every major TMS (Crowdin, Lokalise, Phrase) already speaks.
34
+ - **Locale-aware formatters built in.** `formatNumber`, `formatDate`, `formatCurrency`, and `formatRelativeTime` follow the active locale via native `Intl`, with reactive updates in every framework binding.
35
+ - **~8 kB gzipped, zero runtime dependencies.** No `eval` or `new Function` anywhere โ€” runs under a strict CSP without `unsafe-eval`. Safe for Chrome extensions, Cloudflare Workers, and locked-down enterprise apps.
36
+ - **Pluggable, not monolithic.** Translation loading (CDN/API), locale detection, and in-context editing are opt-in plugins via `@comvi/plugin-fetch-loader`, `@comvi/plugin-locale-detector`, and `@comvi/plugin-in-context-editor`. You only ship what you use.
37
+ - **Same API across 6 frameworks.** `useI18n()` and `<T>` look the same in [Vue](https://www.npmjs.com/package/@comvi/vue), [React](https://www.npmjs.com/package/@comvi/react), [SolidJS](https://www.npmjs.com/package/@comvi/solid), [Svelte](https://www.npmjs.com/package/@comvi/svelte), [Next.js](https://www.npmjs.com/package/@comvi/next), and [Nuxt](https://www.npmjs.com/package/@comvi/nuxt) โ€” switch frameworks without relearning your i18n layer.
38
+
39
+ ## Why @comvi/vue?
40
+
41
+ - **Reactivity first.** `useI18n()` returns Vue refs and computed properties โ€” changes to language or translations trigger precise re-renders without manual store subscriptions.
42
+ - **Template-native API.** `<T>` component uses named slots for tag interpolation; `$t` template helper and `$i18n` global property eliminate boilerplate in Options API code.
43
+ - **Single plugin, both APIs.** One `app.use(i18n)` install works seamlessly with Composition API, Options API, and component templates.
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ npm install @comvi/vue
49
+ # Peer: vue ^3.0.0
50
+ ```
51
+
52
+ ## Quick start
53
+
54
+ ```ts
55
+ // main.ts
56
+ import { createApp } from "vue";
57
+ import { createI18n } from "@comvi/vue";
58
+ import App from "./App.vue";
59
+
60
+ const i18n = createI18n({
61
+ locale: "en",
62
+ fallbackLocale: "en",
63
+ translation: {
64
+ en: { greeting: "Hello, {name}!" },
65
+ uk: { greeting: "ะŸั€ะธะฒั–ั‚, {name}!" },
66
+ },
67
+ });
68
+
69
+ createApp(App).use(i18n).mount("#app");
70
+ ```
71
+
72
+ ```vue
73
+ <!-- App.vue -->
74
+ <script setup lang="ts">
75
+ import { useI18n } from "@comvi/vue";
76
+ const { t, locale, setLocale } = useI18n();
77
+ </script>
78
+
79
+ <template>
80
+ <h1>{{ t("greeting", { name: "Alice" }) }}</h1>
81
+ <select :value="locale" @change="setLocale(($event.target as HTMLSelectElement).value)">
82
+ <option value="en">English</option>
83
+ <option value="uk">ะฃะบั€ะฐั—ะฝััŒะบะฐ</option>
84
+ </select>
85
+ </template>
86
+ ```
87
+
88
+ For the `<T>` component (rich text with slot-based tag interpolation), `$t` template helper, type-safe keys, and the full composable API, see the [documentation](https://comvi.io/docs/i18n/vue/).
89
+
90
+ ## Rich text with `<T>`
91
+
92
+ Embed components inside translation strings without raw HTML, without unsafe DOM injection. Translators see clean markup; you control the rendering via named slots.
93
+
94
+ ```json
95
+ { "help": "Read <link>our docs</link> or <bold>contact us</bold>." }
96
+ ```
97
+
98
+ ```vue
99
+ <script setup lang="ts">
100
+ import { T } from "@comvi/vue";
101
+ </script>
102
+
103
+ <template>
104
+ <T i18nKey="help">
105
+ <template #link="{ children }">
106
+ <a href="/docs">{{ children }}</a>
107
+ </template>
108
+ <template #bold="{ children }">
109
+ <strong>{{ children }}</strong>
110
+ </template>
111
+ </T>
112
+ </template>
113
+ ```
114
+
115
+ Alternatively, use the `components` prop for programmatic tag handling. Pass `tagInterpolation: { strict: "warn" }` to `createI18n` to catch translations referencing tags you forgot to handle before they ship.
116
+
117
+ ## ICU MessageFormat โ€” locale-correct grammar, not just singular/plural
118
+
119
+ `count === 1 ? "item" : "items"` works in English. It silently ships broken grammar in Polish, Ukrainian, Arabic, Welsh, and 30+ other locales โ€” those languages have 3, 4, sometimes 6 distinct plural categories that a binary if/else can't express. [ICU MessageFormat](https://unicode-org.github.io/icu/userguide/format_parse/messages/) is the standard syntax for handling them โ€” the same syntax Crowdin, Lokalise, Phrase, and every major TMS already speak. Comvi i18n parses it via native [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules), so every CLDR plural category is correct by default.
120
+
121
+ ### Plurals across languages
122
+
123
+ ```json
124
+ {
125
+ "en": { "messages": "{count, plural, one {# message} other {# messages}}" },
126
+ "uk": {
127
+ "messages": "{count, plural, one {# ะฟะพะฒั–ะดะพะผะปะตะฝะฝั} few {# ะฟะพะฒั–ะดะพะผะปะตะฝะฝั} many {# ะฟะพะฒั–ะดะพะผะปะตะฝัŒ} other {# ะฟะพะฒั–ะดะพะผะปะตะฝะฝั}}"
128
+ },
129
+ "ar": {
130
+ "messages": "{count, plural, zero {ู„ุง ุชูˆุฌุฏ ุฑุณุงุฆู„} one {ุฑุณุงู„ุฉ ูˆุงุญุฏุฉ} two {ุฑุณุงู„ุชุงู†} few {# ุฑุณุงุฆู„} many {# ุฑุณุงู„ุฉ} other {# ุฑุณุงู„ุฉ}}"
131
+ }
132
+ }
133
+ ```
134
+
135
+ ```ts
136
+ t("messages", { count: 0 }); // ar: "ู„ุง ุชูˆุฌุฏ ุฑุณุงุฆู„" (zero form)
137
+ t("messages", { count: 1 }); // en: "1 message" uk: "1 ะฟะพะฒั–ะดะพะผะปะตะฝะฝั"
138
+ t("messages", { count: 5 }); // en: "5 messages" uk: "5 ะฟะพะฒั–ะดะพะผะปะตะฝัŒ" ar: "5 ุฑุณุงุฆู„"
139
+ t("messages", { count: 22 }); // uk: "22 ะฟะพะฒั–ะดะพะผะปะตะฝะฝั" โ† the "few" form, NOT the "many" form
140
+ ```
141
+
142
+ A naive English-style `count === 1 ? singular : plural` picks one Ukrainian form and ships it for every count โ€” grammatically wrong for half your traffic.
143
+
144
+ ### Ordinals (1st, 2nd, 3rdโ€ฆ)
145
+
146
+ ```json
147
+ { "rank": "{place, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}" }
148
+ ```
149
+
150
+ ```ts
151
+ t("rank", { place: 1 }); // "1st"
152
+ t("rank", { place: 22 }); // "22nd"
153
+ t("rank", { place: 113 }); // "113th"
154
+ ```
155
+
156
+ ### Select (gender, role, status)
157
+
158
+ ```json
159
+ { "greeting": "{gender, select, female {Welcome, madam} male {Welcome, sir} other {Welcome}}" }
160
+ ```
161
+
162
+ ```ts
163
+ t("greeting", { gender: "female" }); // "Welcome, madam"
164
+ t("greeting", { gender: "male" }); // "Welcome, sir"
165
+ t("greeting", { gender: "other" }); // "Welcome"
166
+ ```
167
+
168
+ ### Locale-aware Intl formatters
169
+
170
+ Numbers, dates, currency, and relative time follow the active locale via native `Intl` โ€” reactive in your framework binding:
171
+
172
+ ```vue
173
+ <script setup lang="ts">
174
+ import { useI18n } from "@comvi/vue";
175
+
176
+ const { t, locale, setLocale, formatCurrency, formatRelativeTime, formatDate } = useI18n();
177
+ </script>
178
+
179
+ <template>
180
+ <div>
181
+ <!-- Locale-aware plurals -->
182
+ <p>{{ t("items", { count: 5 }) }}</p>
183
+
184
+ <!-- Locale-aware Intl formatters โ€” re-render when setLocale() is called -->
185
+ <p>Price: {{ formatCurrency(99.99, "USD") }}</p>
186
+ <p>Posted {{ formatRelativeTime(-2, "hour") }}</p>
187
+ <p>Date: {{ formatDate(new Date(), { dateStyle: "long" }) }}</p>
188
+
189
+ <select :value="locale" @change="setLocale(($event.target as HTMLSelectElement).value)">
190
+ <option value="en">English</option>
191
+ <option value="fr">Franรงais</option>
192
+ </select>
193
+ </div>
194
+ </template>
195
+ ```
196
+
197
+ Switching locale via `setLocale()` re-renders all formatters automatically through Vue's reactivity.
198
+
199
+ ## Type-safe translation keys
200
+
201
+ Declaration merging on `TranslationKeys` provides autocomplete and parameter validation per key. Generated automatically via `@comvi/cli` (TMS) or `@comvi/vite-plugin` (local JSON).
202
+
203
+ ```typescript
204
+ // src/types/i18n.d.ts
205
+ declare module "@comvi/core" {
206
+ interface TranslationKeys {
207
+ welcome: { name: string };
208
+ greeting: never;
209
+ "errors:NOT_FOUND": never;
210
+ }
211
+ }
212
+ ```
213
+
214
+ ```vue
215
+ <script setup lang="ts">
216
+ import { useI18n } from "@comvi/vue";
217
+
218
+ const { t } = useI18n();
219
+
220
+ // โœ“ Autocomplete works, params required
221
+ t("welcome", { name: "Alice" });
222
+
223
+ // โœ“ No params needed
224
+ t("greeting");
225
+
226
+ // โœ“ Namespaced keys use the ns option
227
+ t("NOT_FOUND", { ns: "errors" });
228
+ </script>
229
+ ```
230
+
231
+ **What TypeScript catches:**
232
+
233
+ ```ts
234
+ // โœ— Expected 2 arguments, but got 1
235
+ t("welcome");
236
+
237
+ // โœ— Property 'name' is missing in type '{ age: number }'
238
+ t("welcome", { age: 5 });
239
+
240
+ // โœ— Type 'number' is not assignable to type 'string'
241
+ t("welcome", { name: 42 });
242
+
243
+ // โœ— Argument of type '"typo"' is not assignable to parameter
244
+ t("typo", { name: "Alice" });
245
+ ```
246
+
247
+ ## Loading translations from the Comvi platform
248
+
249
+ Pair with `@comvi/plugin-fetch-loader` to load translations from a CDN or API. No redeploy needed to ship a translation:
250
+
251
+ ```ts
252
+ // main.ts
253
+ import { createApp } from "vue";
254
+ import { createI18n } from "@comvi/vue";
255
+ import { FetchLoader } from "@comvi/plugin-fetch-loader";
256
+ import App from "./App.vue";
257
+
258
+ const i18n = createI18n({
259
+ locale: "en",
260
+ defaultNs: "common",
261
+ });
262
+
263
+ // CDN for production, API for dev/staging
264
+ i18n.use(
265
+ FetchLoader({
266
+ cdnUrl: "https://cdn.comvi.io/your-distribution-id",
267
+ }),
268
+ );
269
+
270
+ createApp(App).use(i18n).mount("#app");
271
+ ```
272
+
273
+ See [`@comvi/plugin-fetch-loader`](https://github.com/comvi-io/comvi-js/tree/main/packages/plugin-fetch-loader) for full options and API endpoints.
274
+
275
+ ## License
276
+
277
+ [MIT](https://github.com/comvi-io/comvi-js/blob/main/LICENSE) ยฉ Comvi
@@ -0,0 +1,96 @@
1
+ import { I18n, I18nOptions, FlattenedTranslations, TranslationParams, TranslationResult, TranslationValue, I18nPlugin, I18nEvent, I18nEventData } from '@comvi/core';
2
+ import { Ref, App } from 'vue';
3
+ /**
4
+ * Vue-specific i18n options extending core options
5
+ */
6
+ export interface VueI18nOptions extends I18nOptions {
7
+ /** @deprecated Use locale. */
8
+ language?: string;
9
+ /**
10
+ * Initial locale for SSR hydration.
11
+ * Use this to prevent hydration mismatches when server renders with a different
12
+ * locale than what the client would detect.
13
+ */
14
+ ssrLanguage?: string;
15
+ }
16
+ /**
17
+ * Vue-specific wrapper around the core I18n using composition
18
+ * Provides Vue reactivity integration and plugin installation
19
+ */
20
+ export declare class VueI18n {
21
+ private _core;
22
+ private _locale;
23
+ private _localeComputed?;
24
+ private _isLoading;
25
+ private _isInitializing;
26
+ private _cacheRevision;
27
+ private _translationCacheRef;
28
+ private _unsubscribers;
29
+ private _requestedLocale;
30
+ private _localeQueue;
31
+ private _isLocaleQueueIdle;
32
+ private _isDestroyed;
33
+ addTranslations: (translations: Record<string, Record<string, TranslationValue>>) => void;
34
+ addActiveNamespace: (namespace: string) => Promise<void>;
35
+ clearTranslations: (language?: string, namespace?: string) => void;
36
+ reloadTranslations: (language?: string, namespace?: string) => Promise<void>;
37
+ registerLoader: (loader: Parameters<I18n["registerLoader"]>[0]) => void;
38
+ registerLocaleDetector: (detector: () => string | Promise<string>) => void;
39
+ registerPostProcessor: (processor: (result: TranslationResult, key: string, namespace: string, params?: TranslationParams) => TranslationResult) => void;
40
+ onMissingKey: (callback: (key: string, locale: string, namespace: string) => TranslationResult | void) => () => void;
41
+ onLoadError: (callback: (locale: string, namespace: string, error: Error) => void) => () => void;
42
+ on: <E extends I18nEvent>(event: E, callback: (payload: I18nEventData[E]) => void) => () => void;
43
+ hasLocale: (locale: string, namespace?: string) => boolean;
44
+ hasTranslation: (key: string, locale?: string, namespace?: string, checkFallbacks?: boolean) => boolean;
45
+ getLoadedLocales: () => string[];
46
+ setFallbackLocale: (locales: string | string[]) => void;
47
+ getDefaultNamespace: () => string;
48
+ reportError: (error: unknown, context?: Parameters<I18n["reportError"]>[1]) => void;
49
+ getActiveNamespaces: () => string[];
50
+ formatNumber: I18n["formatNumber"];
51
+ formatDate: I18n["formatDate"];
52
+ formatCurrency: I18n["formatCurrency"];
53
+ formatRelativeTime: I18n["formatRelativeTime"];
54
+ constructor(options: VueI18nOptions);
55
+ get locale(): Ref<string>;
56
+ set locale(value: string);
57
+ private _dirComputed?;
58
+ /** Text direction for the current locale, as a reactive computed ref */
59
+ get dir(): import('vue').ComputedRef<"ltr" | "rtl">;
60
+ setLocale(locale: string): Promise<void>;
61
+ get translationCache(): Readonly<Ref<Readonly<ReadonlyMap<string, FlattenedTranslations>>>>;
62
+ get isLoading(): Readonly<Ref<boolean>>;
63
+ get isInitializing(): Readonly<Ref<boolean>>;
64
+ /** Raw translation result for rich text renderers and advanced integrations. */
65
+ tRaw<NS extends import('@comvi/core').Namespaces, K extends import('@comvi/core').NamespacedKeys<NS>>(key: K, ...params: import('@comvi/core').NamespacedParamsArg<NS, K>): TranslationResult;
66
+ /** Raw translation result for typed keys. */
67
+ tRaw<K extends import('@comvi/core').DefaultNsKeys>(key: K, ...params: import('@comvi/core').ParamsArg<K>): TranslationResult;
68
+ /** Raw translation result for permissive keys. */
69
+ tRaw(key: import('@comvi/core').PermissiveKey, params?: import('@comvi/core').TranslationParams): TranslationResult;
70
+ /**
71
+ * Translate a namespaced key (when ns is provided). Always returns plain text.
72
+ */
73
+ t<NS extends import('@comvi/core').Namespaces, K extends import('@comvi/core').NamespacedKeys<NS>>(key: K, ...params: import('@comvi/core').NamespacedParamsArg<NS, K>): string;
74
+ /**
75
+ * Translate a key with Vue reactivity tracking - typed keys. Always returns plain text.
76
+ */
77
+ t<K extends import('@comvi/core').DefaultNsKeys>(key: K, ...params: import('@comvi/core').ParamsArg<K>): string;
78
+ /**
79
+ * Permissive overload - only active when TranslationKeys is empty. Always returns plain text.
80
+ */
81
+ t(key: import('@comvi/core').PermissiveKey, params?: import('@comvi/core').TranslationParams): string;
82
+ init(): Promise<this>;
83
+ use(plugin: I18nPlugin, options?: Parameters<I18n["use"]>[1]): this;
84
+ destroy(): void;
85
+ private _installedApps;
86
+ install(app: App): void;
87
+ }
88
+ export declare function createI18n(options: VueI18nOptions): VueI18n;
89
+ declare module "vue" {
90
+ interface ComponentCustomProperties {
91
+ $t: VueI18n["t"];
92
+ $tRaw: VueI18n["tRaw"];
93
+ $i18n: VueI18n;
94
+ }
95
+ }
96
+ //# sourceMappingURL=VueI18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VueI18n.d.ts","sourceRoot":"","sources":["../src/VueI18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ import { PropType, Component, VNode } from 'vue';
2
+ /**
3
+ * Component handler types for the `components` prop
4
+ */
5
+ type ComponentHandler = string | Component | {
6
+ component: string | Component;
7
+ props?: Record<string, unknown>;
8
+ };
9
+ /**
10
+ * Components prop type for tag interpolation
11
+ */
12
+ type ComponentsMap = Record<string, ComponentHandler>;
13
+ /**
14
+ * Translation component for Vue
15
+ * Renders translated content with support for slots and components prop as tag handlers
16
+ *
17
+ * @example
18
+ * ```vue
19
+ * <!-- Simple usage -->
20
+ * <T i18nKey="greeting" />
21
+ *
22
+ * <!-- With parameters -->
23
+ * <T i18nKey="welcome" :params="{ name: 'John' }" />
24
+ *
25
+ * <!-- With tag interpolation using slots -->
26
+ * <T i18nKey="welcome_link">
27
+ * <template #link="{ children }">
28
+ * <a href="/help">{{ children }}</a>
29
+ * </template>
30
+ * </T>
31
+ *
32
+ * <!-- With tag interpolation using components prop -->
33
+ * <T
34
+ * i18nKey="welcome_link"
35
+ * :components="{
36
+ * link: { component: 'a', props: { href: '/help' } },
37
+ * bold: 'strong'
38
+ * }"
39
+ * />
40
+ *
41
+ * <!-- With specific namespace -->
42
+ * <T i18nKey="button.submit" ns="forms" />
43
+ *
44
+ * <!-- With specific locale -->
45
+ * <T i18nKey="greeting" locale="fr" />
46
+ * ```
47
+ */
48
+ export declare const T: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
49
+ /**
50
+ * Translation key to look up
51
+ */
52
+ i18nKey: {
53
+ type: StringConstructor;
54
+ required: true;
55
+ };
56
+ /**
57
+ * Parameters for interpolation
58
+ * These will be merged with slot content
59
+ */
60
+ params: {
61
+ type: PropType<Record<string, unknown>>;
62
+ default: () => {};
63
+ };
64
+ /**
65
+ * Namespace to use (optional)
66
+ * If not specified, uses the default namespace
67
+ */
68
+ ns: {
69
+ type: StringConstructor;
70
+ default: undefined;
71
+ };
72
+ /**
73
+ * Specific locale to use (optional)
74
+ * If not specified, uses the current locale
75
+ */
76
+ locale: {
77
+ type: StringConstructor;
78
+ default: undefined;
79
+ };
80
+ /**
81
+ * Fallback text to display if translation is missing (optional)
82
+ * If not specified, returns the key itself
83
+ */
84
+ fallback: {
85
+ type: StringConstructor;
86
+ default: undefined;
87
+ };
88
+ /**
89
+ * Skip post-processing (optional)
90
+ * When true, prevents post-processors like IncontextEditor from adding invisible marker characters
91
+ */
92
+ raw: {
93
+ type: BooleanConstructor;
94
+ default: undefined;
95
+ };
96
+ /**
97
+ * Components map for tag interpolation (optional)
98
+ * Maps tag names to their handlers (string tag name, component, or config object)
99
+ *
100
+ * @example
101
+ * {
102
+ * bold: 'strong', // HTML tag name
103
+ * link: { component: 'a', props: { href: '#' } }, // With props
104
+ * btn: MyButton // Vue component
105
+ * }
106
+ */
107
+ components: {
108
+ type: PropType<ComponentsMap>;
109
+ default: undefined;
110
+ };
111
+ }>, () => string | (string | VNode<import('vue').RendererNode, import('vue').RendererElement, {
112
+ [key: string]: any;
113
+ }>)[], {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
114
+ /**
115
+ * Translation key to look up
116
+ */
117
+ i18nKey: {
118
+ type: StringConstructor;
119
+ required: true;
120
+ };
121
+ /**
122
+ * Parameters for interpolation
123
+ * These will be merged with slot content
124
+ */
125
+ params: {
126
+ type: PropType<Record<string, unknown>>;
127
+ default: () => {};
128
+ };
129
+ /**
130
+ * Namespace to use (optional)
131
+ * If not specified, uses the default namespace
132
+ */
133
+ ns: {
134
+ type: StringConstructor;
135
+ default: undefined;
136
+ };
137
+ /**
138
+ * Specific locale to use (optional)
139
+ * If not specified, uses the current locale
140
+ */
141
+ locale: {
142
+ type: StringConstructor;
143
+ default: undefined;
144
+ };
145
+ /**
146
+ * Fallback text to display if translation is missing (optional)
147
+ * If not specified, returns the key itself
148
+ */
149
+ fallback: {
150
+ type: StringConstructor;
151
+ default: undefined;
152
+ };
153
+ /**
154
+ * Skip post-processing (optional)
155
+ * When true, prevents post-processors like IncontextEditor from adding invisible marker characters
156
+ */
157
+ raw: {
158
+ type: BooleanConstructor;
159
+ default: undefined;
160
+ };
161
+ /**
162
+ * Components map for tag interpolation (optional)
163
+ * Maps tag names to their handlers (string tag name, component, or config object)
164
+ *
165
+ * @example
166
+ * {
167
+ * bold: 'strong', // HTML tag name
168
+ * link: { component: 'a', props: { href: '#' } }, // With props
169
+ * btn: MyButton // Vue component
170
+ * }
171
+ */
172
+ components: {
173
+ type: PropType<ComponentsMap>;
174
+ default: undefined;
175
+ };
176
+ }>> & Readonly<{}>, {
177
+ locale: string;
178
+ params: Record<string, unknown>;
179
+ ns: string;
180
+ fallback: string;
181
+ raw: boolean;
182
+ components: ComponentsMap;
183
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
184
+ export {};
185
+ //# sourceMappingURL=T.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"T.d.ts","sourceRoot":"","sources":["../../src/components/T.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,KAAK,EACX,MAAM,KAAK,CAAC;AAiBb;;GAEG;AACH,KAAK,gBAAgB,GACjB,MAAM,GACN,SAAS,GACT;IACE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEN;;GAEG;AACH,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAYtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,CAAC;IAGV;;OAEG;;;;;IAMH;;;OAGG;;cAEe,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;IAInD;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;;;;;;;;OAUG;;cAEe,QAAQ,CAAC,aAAa,CAAC;;;;;;IAjEzC;;OAEG;;;;;IAMH;;;OAGG;;cAEe,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;IAInD;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;OAGG;;;;;IAMH;;;;;;;;;;OAUG;;cAEe,QAAQ,CAAC,aAAa,CAAC;;;;;;;;;;4EAqJ3C,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { Ref } from 'vue';
2
+ import { TranslationParams, TranslationResult, FlattenedTranslations, TranslationValue, I18nEvent, I18nEventData, I18n } from '@comvi/core';
3
+ export interface UseI18nReturn {
4
+ /** Translation function - namespaced keys (when ns is provided). Always returns plain text. */
5
+ t<NS extends import('@comvi/core').Namespaces, K extends import('@comvi/core').NamespacedKeys<NS>>(key: K, ...params: import('@comvi/core').NamespacedParamsArg<NS, K>): string;
6
+ /** Translation function - typed keys (default namespace only, use ns option for others). */
7
+ t<K extends import('@comvi/core').DefaultNsKeys>(key: K, ...params: import('@comvi/core').ParamsArg<K>): string;
8
+ /** Permissive overload - only active when TranslationKeys is empty */
9
+ t(key: import('@comvi/core').PermissiveKey, params?: TranslationParams): string;
10
+ /** Raw translation result for rich text renderers and advanced integrations. */
11
+ tRaw<NS extends import('@comvi/core').Namespaces, K extends import('@comvi/core').NamespacedKeys<NS>>(key: K, ...params: import('@comvi/core').NamespacedParamsArg<NS, K>): TranslationResult;
12
+ /** Raw translation result for typed keys. */
13
+ tRaw<K extends import('@comvi/core').DefaultNsKeys>(key: K, ...params: import('@comvi/core').ParamsArg<K>): TranslationResult;
14
+ /** Raw translation result for permissive keys. */
15
+ tRaw(key: import('@comvi/core').PermissiveKey, params?: TranslationParams): TranslationResult;
16
+ /** Current locale (reactive Vue Ref) */
17
+ locale: Ref<string>;
18
+ /** Set locale asynchronously */
19
+ setLocale: (locale: string) => Promise<void>;
20
+ /** Translation cache (stable readonly ref with manual triggers, no cloning) */
21
+ translationCache: Readonly<Ref<Readonly<ReadonlyMap<string, FlattenedTranslations>>>>;
22
+ /** Loading state (readonly reactive Vue Ref) */
23
+ isLoading: Readonly<Ref<boolean>>;
24
+ /** Initializing state (readonly reactive Vue Ref) */
25
+ isInitializing: Readonly<Ref<boolean>>;
26
+ /** Add translations programmatically at runtime */
27
+ addTranslations: (translations: Record<string, Record<string, TranslationValue>>) => void;
28
+ /** Load a new namespace dynamically */
29
+ addActiveNamespace: (namespace: string) => Promise<void>;
30
+ /** Configure fallback locale chain */
31
+ setFallbackLocale: (locales: string | string[]) => void;
32
+ /** Register callback for missing keys */
33
+ onMissingKey: (callback: (key: string, locale: string, namespace: string) => TranslationResult | void) => () => void;
34
+ /** Register callback for load errors */
35
+ onLoadError: (callback: (locale: string, namespace: string, error: Error) => void) => () => void;
36
+ /** Clear translations from cache */
37
+ clearTranslations: (locale?: string, namespace?: string) => void;
38
+ /** Force reload translations from loader */
39
+ reloadTranslations: (locale?: string, namespace?: string) => Promise<void>;
40
+ /** Check if a locale is loaded for a namespace */
41
+ hasLocale: (locale: string, namespace?: string) => boolean;
42
+ /** Check if a translation exists */
43
+ hasTranslation: (key: string, locale?: string, namespace?: string, checkFallbacks?: boolean) => boolean;
44
+ /** Get list of all loaded locale codes */
45
+ getLoadedLocales: () => string[];
46
+ /** Get list of active namespaces */
47
+ getActiveNamespaces: () => string[];
48
+ /** Get default namespace */
49
+ getDefaultNamespace: () => string;
50
+ /** Subscribe to i18n events */
51
+ on: <E extends I18nEvent>(event: E, callback: (payload: I18nEventData[E]) => void) => () => void;
52
+ /** Report an error to the configured onError handler */
53
+ reportError: I18n["reportError"];
54
+ /** Format a number using the current language locale */
55
+ formatNumber: I18n["formatNumber"];
56
+ /** Format a date using the current language locale */
57
+ formatDate: I18n["formatDate"];
58
+ /** Format a number as currency using the current language locale */
59
+ formatCurrency: I18n["formatCurrency"];
60
+ /** Format a relative time ("2 hours ago", "in 3 days") using the current language locale */
61
+ formatRelativeTime: I18n["formatRelativeTime"];
62
+ /** Text direction for the current language, as a reactive computed ref */
63
+ dir: import('vue').ComputedRef<"ltr" | "rtl">;
64
+ /** Cleanup resources (call when i18n instance is no longer needed) */
65
+ destroy: () => void;
66
+ }
67
+ /**
68
+ * Vue composable to access the i18n instance
69
+ * Must be used within a component that has access to the i18n plugin
70
+ *
71
+ * @param ns - Optional namespace to scope translations to
72
+ * @returns Object with translation function, reactive state, and i18n methods
73
+ */
74
+ export declare function useI18n(ns?: string): UseI18nReturn;
75
+ //# sourceMappingURL=useI18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useI18n.d.ts","sourceRoot":"","sources":["../../src/composables/useI18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@comvi/core`),t=require(`vue`);var n=Symbol(`i18n`);function r(e){if(e.type===`text`)return e.text;let t=``;for(let n of e.children)t+=typeof n==`string`?n:r(n);return t}function i(e){if(typeof e==`string`)return e;let t=``;for(let n of e)t+=typeof n==`string`?n:r(n);return t}var a=[`addTranslations`,`addActiveNamespace`,`clearTranslations`,`reloadTranslations`,`registerLoader`,`registerPostProcessor`,`onMissingKey`,`onLoadError`,`on`,`hasLocale`,`hasTranslation`,`setFallbackLocale`,`getDefaultNamespace`,`reportError`,`getActiveNamespaces`,`formatNumber`,`formatDate`,`formatCurrency`,`formatRelativeTime`],o=class{constructor(n){this._unsubscribers=[],this._localeQueue=Promise.resolve(),this._isLocaleQueueIdle=!0,this._isDestroyed=!1,this._installedApps=new WeakSet;let r=n.ssrLanguage??n.locale??n.language;this._core=new e.I18n({...n,locale:r}),this._locale=(0,t.shallowRef)(r),this._requestedLocale=r,this._isLoading=(0,t.shallowRef)(this._core.isLoading),this._isInitializing=(0,t.shallowRef)(this._core.isInitializing),this._cacheRevision=(0,t.shallowRef)(this._core.translationCache.getRevision()),this._translationCacheRef=(0,t.shallowRef)(this._core.translationCache.getInternalMap());let i=()=>{this._cacheRevision.value=this._core.translationCache.getRevision(),this._translationCacheRef.value=this._core.translationCache.getInternalMap(),(0,t.triggerRef)(this._translationCacheRef)};this._unsubscribers.push(this._core.on(`localeChanged`,({to:e})=>{this._locale.value=e,this._requestedLocale=e}),this._core.on(`namespaceLoaded`,i),this._core.on(`loadingStateChanged`,({isLoading:e,isInitializing:t})=>{this._isLoading.value=e,this._isInitializing.value=t}),this._core.on(`initialized`,()=>{this._locale.value=this._core.locale,i(),this._isLoading.value=this._core.isLoading,this._isInitializing.value=this._core.isInitializing}),this._core.on(`translationsCleared`,i));let o=this._core;for(let e of a)this[e]=(...t)=>o[e](...t);this.registerLocaleDetector=e=>o.registerLocaleDetector(e),this.getLoadedLocales=()=>o.getLoadedLocales(),this.t=this.t.bind(this),this.tRaw=this.tRaw.bind(this),this.setLocale=this.setLocale.bind(this),this.destroy=this.destroy.bind(this)}get locale(){return this._localeComputed||(this._localeComputed=(0,t.computed)({get:()=>this._locale.value,set:e=>{this._requestedLocale!==e&&this.setLocale(e).catch(e=>{})}})),this._localeComputed}set locale(e){this.setLocale(e).catch(e=>{})}get dir(){return this._dirComputed||(this._dirComputed=(0,t.computed)(()=>this._core.dir)),this._dirComputed}async setLocale(e){let t=e;this._requestedLocale=t;let n=async()=>{this._core.locale!==t&&await this._core.setLocaleAsync(t)},r=this._isLocaleQueueIdle?n():this._localeQueue.then(n,n);this._isLocaleQueueIdle=!1;let i=r.catch(()=>{});this._localeQueue=i,i.finally(()=>{this._localeQueue===i&&(this._isLocaleQueueIdle=!0)});try{await r}catch(e){throw this._requestedLocale===t&&(this._requestedLocale=this._core.locale),e}}get translationCache(){return this._translationCacheRef}get isLoading(){return(0,t.readonly)(this._isLoading)}get isInitializing(){return(0,t.readonly)(this._isInitializing)}tRaw(e,...t){return this._core.tRaw(e,...t)}t(e,...t){return i(this.tRaw(e,...t))}async init(){return await this._core.init(),this}use(e,t){return this._core.use(e,t),this}destroy(){this._isDestroyed||(this._isDestroyed=!0,this._unsubscribers.reverse().forEach(e=>e()),this._unsubscribers.length=0,this._core.destroy().catch(e=>{this._core.reportError(e,{source:`plugin-cleanup`})}))}install(e){this._installedApps.has(e)||(this._installedApps.add(e),!this._core.isInitialized&&!this._core.isInitializing&&this.init().catch(e=>{this._core.reportError(e instanceof Error?e:Error(String(e)),{source:`init`})}),e.provide(n,this),e.config.globalProperties.$i18n=this,e.config.globalProperties.$t=this.t,e.config.globalProperties.$tRaw=this.tRaw)}};function s(e){return new o(e)}var c=[`locale`,`setLocale`,`translationCache`,`isLoading`,`isInitializing`,`addTranslations`,`addActiveNamespace`,`setFallbackLocale`,`onMissingKey`,`onLoadError`,`clearTranslations`,`reloadTranslations`,`hasLocale`,`hasTranslation`,`getLoadedLocales`,`getActiveNamespaces`,`getDefaultNamespace`,`on`,`reportError`,`formatNumber`,`formatDate`,`formatCurrency`,`formatRelativeTime`,`dir`,`destroy`];function l(r){let a=(0,t.inject)(n);if(!a)throw Error(`[i18n] useI18n must be used within a Vue app with i18n plugin installed. Make sure you called app.use(i18n) before using this composable.`);let o=(0,e.createBoundTranslation)(a,r),s={t:((e,t)=>i(o(e,t))),tRaw:o};for(let e of c)s[e]=a[e];return s}var u=`__vue_handler_`,d=`__`;function f(e){return typeof e==`string`?e?[e]:[]:e}var p=(0,t.defineComponent)({name:`T`,props:{i18nKey:{type:String,required:!0},params:{type:Object,default:()=>({})},ns:{type:String,default:void 0},locale:{type:String,default:void 0},fallback:{type:String,default:void 0},raw:{type:Boolean,default:void 0},components:{type:Object,default:void 0}},setup(r,{slots:i}){let a=(0,t.inject)(n);if(!a)throw Error(`[i18n] <T> component must be used within a Vue app with i18n plugin installed`);return()=>{let n=r.i18nKey,o=new Map,s={},c=(n,r)=>{o.set(n,e=>{try{return r(e)}catch(r){return a.reportError(r,{source:`translation`,tagName:n}),(0,t.h)(`span`,{},e)}}),s[n]=({children:t})=>(0,e.createElement)(`${u}${n}${d}`,{},f(t))},l=e=>e.length===1&&typeof e[0]==`string`?e[0]:e;if(r.components)for(let[n,i]of Object.entries(r.components))if(typeof i==`string`)s[n]=({children:t})=>(0,e.createElement)(i,{},f(t));else if(typeof i==`object`&&i&&`component`in i){let r=i.component,a=i.props||{};typeof r==`string`?s[n]=({children:t})=>(0,e.createElement)(r,a,f(t)):c(n,e=>(0,t.h)(r,a,{default:()=>l(e)}))}else c(n,e=>(0,t.h)(i,{},{default:()=>l(e)}));for(let[e,n]of Object.entries(i))n&&!(e in s)&&c(e,e=>{let r=n({children:l(e)}),i=Array.isArray(r)?r:[r];return i.length<=1?i.length===0?(0,t.h)(t.Fragment,{},[]):i[0]:(0,t.h)(t.Fragment,{},i)});let p={...r.params,...s};r.ns!==void 0&&(p.ns=r.ns),r.locale!==void 0&&(p.locale=r.locale),r.fallback!==void 0&&(p.fallback=r.fallback),r.raw!==void 0&&(p.raw=r.raw);let m=a.tRaw(n,p);if(typeof m==`string`)return m;let h=e=>typeof e==`string`?e?[e]:[]:e.map(e=>typeof e==`string`?e:g(e)),g=e=>{if(e.type===`text`)return e.text;if(e.type===`fragment`)return(0,t.h)(t.Fragment,{key:e.key},h(e.children));let n=e.tag,r=h(e.children);if(n.startsWith(u)&&n.endsWith(d)){let e=n.slice(14,-2),i=o.get(e);if(i)try{return i(r)}catch(n){return a.reportError(n,{source:`translation`,tagName:e}),(0,t.h)(`span`,{},r)}}return(0,t.h)(n,e.props,r)};return m.map(e=>typeof e==`string`?e:g(e))}}});exports.I18N_INJECTION_KEY=n,exports.T=p,exports.VueI18n=o,exports.createI18n=s,exports.useI18n=l,Object.keys(e).forEach(function(t){t!==`default`&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
@@ -0,0 +1 @@
1
+ import{I18n as e,createBoundTranslation as t,createElement as n}from"@comvi/core";import{Fragment as r,computed as i,defineComponent as a,h as o,inject as s,readonly as c,shallowRef as l,triggerRef as u}from"vue";export*from"@comvi/core";var d=Symbol(`i18n`);function f(e){if(e.type===`text`)return e.text;let t=``;for(let n of e.children)t+=typeof n==`string`?n:f(n);return t}function p(e){if(typeof e==`string`)return e;let t=``;for(let n of e)t+=typeof n==`string`?n:f(n);return t}var m=[`addTranslations`,`addActiveNamespace`,`clearTranslations`,`reloadTranslations`,`registerLoader`,`registerPostProcessor`,`onMissingKey`,`onLoadError`,`on`,`hasLocale`,`hasTranslation`,`setFallbackLocale`,`getDefaultNamespace`,`reportError`,`getActiveNamespaces`,`formatNumber`,`formatDate`,`formatCurrency`,`formatRelativeTime`],h=class{constructor(t){this._unsubscribers=[],this._localeQueue=Promise.resolve(),this._isLocaleQueueIdle=!0,this._isDestroyed=!1,this._installedApps=new WeakSet;let n=t.ssrLanguage??t.locale??t.language;this._core=new e({...t,locale:n}),this._locale=l(n),this._requestedLocale=n,this._isLoading=l(this._core.isLoading),this._isInitializing=l(this._core.isInitializing),this._cacheRevision=l(this._core.translationCache.getRevision()),this._translationCacheRef=l(this._core.translationCache.getInternalMap());let r=()=>{this._cacheRevision.value=this._core.translationCache.getRevision(),this._translationCacheRef.value=this._core.translationCache.getInternalMap(),u(this._translationCacheRef)};this._unsubscribers.push(this._core.on(`localeChanged`,({to:e})=>{this._locale.value=e,this._requestedLocale=e}),this._core.on(`namespaceLoaded`,r),this._core.on(`loadingStateChanged`,({isLoading:e,isInitializing:t})=>{this._isLoading.value=e,this._isInitializing.value=t}),this._core.on(`initialized`,()=>{this._locale.value=this._core.locale,r(),this._isLoading.value=this._core.isLoading,this._isInitializing.value=this._core.isInitializing}),this._core.on(`translationsCleared`,r));let i=this._core;for(let e of m)this[e]=(...t)=>i[e](...t);this.registerLocaleDetector=e=>i.registerLocaleDetector(e),this.getLoadedLocales=()=>i.getLoadedLocales(),this.t=this.t.bind(this),this.tRaw=this.tRaw.bind(this),this.setLocale=this.setLocale.bind(this),this.destroy=this.destroy.bind(this)}get locale(){return this._localeComputed||(this._localeComputed=i({get:()=>this._locale.value,set:e=>{this._requestedLocale!==e&&this.setLocale(e).catch(e=>{})}})),this._localeComputed}set locale(e){this.setLocale(e).catch(e=>{})}get dir(){return this._dirComputed||(this._dirComputed=i(()=>this._core.dir)),this._dirComputed}async setLocale(e){let t=e;this._requestedLocale=t;let n=async()=>{this._core.locale!==t&&await this._core.setLocaleAsync(t)},r=this._isLocaleQueueIdle?n():this._localeQueue.then(n,n);this._isLocaleQueueIdle=!1;let i=r.catch(()=>{});this._localeQueue=i,i.finally(()=>{this._localeQueue===i&&(this._isLocaleQueueIdle=!0)});try{await r}catch(e){throw this._requestedLocale===t&&(this._requestedLocale=this._core.locale),e}}get translationCache(){return this._translationCacheRef}get isLoading(){return c(this._isLoading)}get isInitializing(){return c(this._isInitializing)}tRaw(e,...t){return this._core.tRaw(e,...t)}t(e,...t){return p(this.tRaw(e,...t))}async init(){return await this._core.init(),this}use(e,t){return this._core.use(e,t),this}destroy(){this._isDestroyed||(this._isDestroyed=!0,this._unsubscribers.reverse().forEach(e=>e()),this._unsubscribers.length=0,this._core.destroy().catch(e=>{this._core.reportError(e,{source:`plugin-cleanup`})}))}install(e){this._installedApps.has(e)||(this._installedApps.add(e),!this._core.isInitialized&&!this._core.isInitializing&&this.init().catch(e=>{this._core.reportError(e instanceof Error?e:Error(String(e)),{source:`init`})}),e.provide(d,this),e.config.globalProperties.$i18n=this,e.config.globalProperties.$t=this.t,e.config.globalProperties.$tRaw=this.tRaw)}};function g(e){return new h(e)}var _=[`locale`,`setLocale`,`translationCache`,`isLoading`,`isInitializing`,`addTranslations`,`addActiveNamespace`,`setFallbackLocale`,`onMissingKey`,`onLoadError`,`clearTranslations`,`reloadTranslations`,`hasLocale`,`hasTranslation`,`getLoadedLocales`,`getActiveNamespaces`,`getDefaultNamespace`,`on`,`reportError`,`formatNumber`,`formatDate`,`formatCurrency`,`formatRelativeTime`,`dir`,`destroy`];function v(e){let n=s(d);if(!n)throw Error(`[i18n] useI18n must be used within a Vue app with i18n plugin installed. Make sure you called app.use(i18n) before using this composable.`);let r=t(n,e),i={t:((e,t)=>p(r(e,t))),tRaw:r};for(let e of _)i[e]=n[e];return i}var y=`__vue_handler_`,b=`__`;function x(e){return typeof e==`string`?e?[e]:[]:e}var S=a({name:`T`,props:{i18nKey:{type:String,required:!0},params:{type:Object,default:()=>({})},ns:{type:String,default:void 0},locale:{type:String,default:void 0},fallback:{type:String,default:void 0},raw:{type:Boolean,default:void 0},components:{type:Object,default:void 0}},setup(e,{slots:t}){let i=s(d);if(!i)throw Error(`[i18n] <T> component must be used within a Vue app with i18n plugin installed`);return()=>{let a=e.i18nKey,s=new Map,c={},l=(e,t)=>{s.set(e,n=>{try{return t(n)}catch(t){return i.reportError(t,{source:`translation`,tagName:e}),o(`span`,{},n)}}),c[e]=({children:t})=>n(`${y}${e}${b}`,{},x(t))},u=e=>e.length===1&&typeof e[0]==`string`?e[0]:e;if(e.components)for(let[t,r]of Object.entries(e.components))if(typeof r==`string`)c[t]=({children:e})=>n(r,{},x(e));else if(typeof r==`object`&&r&&`component`in r){let e=r.component,i=r.props||{};typeof e==`string`?c[t]=({children:t})=>n(e,i,x(t)):l(t,t=>o(e,i,{default:()=>u(t)}))}else l(t,e=>o(r,{},{default:()=>u(e)}));for(let[e,n]of Object.entries(t))n&&!(e in c)&&l(e,e=>{let t=n({children:u(e)}),i=Array.isArray(t)?t:[t];return i.length<=1?i.length===0?o(r,{},[]):i[0]:o(r,{},i)});let d={...e.params,...c};e.ns!==void 0&&(d.ns=e.ns),e.locale!==void 0&&(d.locale=e.locale),e.fallback!==void 0&&(d.fallback=e.fallback),e.raw!==void 0&&(d.raw=e.raw);let f=i.tRaw(a,d);if(typeof f==`string`)return f;let p=e=>typeof e==`string`?e?[e]:[]:e.map(e=>typeof e==`string`?e:m(e)),m=e=>{if(e.type===`text`)return e.text;if(e.type===`fragment`)return o(r,{key:e.key},p(e.children));let t=e.tag,n=p(e.children);if(t.startsWith(y)&&t.endsWith(b)){let e=t.slice(14,-2),r=s.get(e);if(r)try{return r(n)}catch(t){return i.reportError(t,{source:`translation`,tagName:e}),o(`span`,{},n)}}return o(t,e.props,n)};return f.map(e=>typeof e==`string`?e:m(e))}}});export{d as I18N_INJECTION_KEY,S as T,h as VueI18n,g as createI18n,v as useI18n};
@@ -0,0 +1,7 @@
1
+ export * from '@comvi/core';
2
+ export { VueI18n, createI18n } from './VueI18n';
3
+ export { useI18n } from './composables/useI18n';
4
+ export { T } from './components/T';
5
+ export { I18N_INJECTION_KEY } from './keys';
6
+ export type { VueI18n as I18nInstance, VueI18nOptions } from './VueI18n';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAC;AAG5B,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,gBAAgB,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAG5C,YAAY,EAAE,OAAO,IAAI,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { InjectionKey } from 'vue';
2
+ import { VueI18n } from './VueI18n';
3
+ /**
4
+ * Injection key for Vue's provide/inject pattern
5
+ * Used to inject the i18n instance into Vue components
6
+ */
7
+ export declare const I18N_INJECTION_KEY: InjectionKey<VueI18n>;
8
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,YAAY,CAAC,OAAO,CAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { TranslationResult } from '@comvi/core';
2
+ export declare function translationResultToString(result: TranslationResult): string;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAe,MAAM,aAAa,CAAC;AAclE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAU3E"}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@comvi/vue",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Vue 3 integration for Comvi โ€” composables, components, and type-safe translations",
6
+ "license": "MIT",
7
+ "author": "Comvi <hello@comvi.io> (https://comvi.io)",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/comvi-io/comvi-js.git",
11
+ "directory": "packages/vue"
12
+ },
13
+ "homepage": "https://comvi.io",
14
+ "bugs": {
15
+ "url": "https://github.com/comvi-io/comvi-js/issues"
16
+ },
17
+ "keywords": [
18
+ "i18n",
19
+ "internationalization",
20
+ "localization",
21
+ "vue",
22
+ "vue3",
23
+ "vue-i18n",
24
+ "composition-api",
25
+ "typescript",
26
+ "type-safe",
27
+ "comvi",
28
+ "translation",
29
+ "ssr",
30
+ "ssg",
31
+ "server-components"
32
+ ],
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "main": "./dist/comvi-vue.cjs",
37
+ "module": "./dist/comvi-vue.js",
38
+ "types": "./dist/index.d.ts",
39
+ "exports": {
40
+ ".": {
41
+ "types": "./dist/index.d.ts",
42
+ "import": "./dist/comvi-vue.js",
43
+ "require": "./dist/comvi-vue.cjs"
44
+ }
45
+ },
46
+ "sideEffects": false,
47
+ "dependencies": {
48
+ "@comvi/core": "0.1.0"
49
+ },
50
+ "peerDependencies": {
51
+ "vue": "^3.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^22.13.0",
55
+ "@typescript-eslint/eslint-plugin": "^8.58.0",
56
+ "@typescript-eslint/parser": "^8.58.0",
57
+ "@vitest/coverage-v8": "^4.1.2",
58
+ "@vue/test-utils": "^2.4.6",
59
+ "eslint": "^10.1.0",
60
+ "eslint-config-prettier": "^10.1.8",
61
+ "eslint-plugin-vue": "^10.8.0",
62
+ "happy-dom": "^20.8.9",
63
+ "prettier": "^3.8.1",
64
+ "typescript": "~6.0.2",
65
+ "vite": "^8.0.3",
66
+ "vite-plugin-dts": "^4.5.4",
67
+ "vitest": "^4.1.2",
68
+ "vue": "^3.5.32",
69
+ "vue-eslint-parser": "^10.4.0",
70
+ "vue-tsc": "^3.2.6",
71
+ "@comvi/vite-config": "0.1.0"
72
+ },
73
+ "scripts": {
74
+ "dev": "vite build --watch",
75
+ "build": "vue-tsc && vite build",
76
+ "typecheck": "vue-tsc --noEmit",
77
+ "test": "vitest run",
78
+ "test:watch": "vitest",
79
+ "test:coverage": "vitest run --coverage",
80
+ "lint": "eslint . --max-warnings=0",
81
+ "format": "prettier --write src/",
82
+ "lint:fix": "eslint . --fix"
83
+ }
84
+ }