@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 +21 -0
- package/README.md +277 -0
- package/dist/VueI18n.d.ts +96 -0
- package/dist/VueI18n.d.ts.map +1 -0
- package/dist/components/T.d.ts +185 -0
- package/dist/components/T.d.ts.map +1 -0
- package/dist/composables/useI18n.d.ts +75 -0
- package/dist/composables/useI18n.d.ts.map +1 -0
- package/dist/comvi-vue.cjs +1 -0
- package/dist/comvi-vue.js +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/keys.d.ts +8 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +84 -0
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><T></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":"AAAA,OAAO,EAAU,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAIvC,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,IAAI,EACL,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,aAAa;IAC5B,+FAA+F;IAC/F,CAAC,CACC,EAAE,SAAS,OAAO,aAAa,EAAE,UAAU,EAC3C,CAAC,SAAS,OAAO,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC,EAElD,GAAG,EAAE,CAAC,EACN,GAAG,MAAM,EAAE,OAAO,aAAa,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC,GAC1D,MAAM,CAAC;IAEV,4FAA4F;IAC5F,CAAC,CAAC,CAAC,SAAS,OAAO,aAAa,EAAE,aAAa,EAC7C,GAAG,EAAE,CAAC,EACN,GAAG,MAAM,EAAE,OAAO,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,GAC5C,MAAM,CAAC;IAEV,sEAAsE;IACtE,CAAC,CAAC,GAAG,EAAE,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAEhF,gFAAgF;IAChF,IAAI,CACF,EAAE,SAAS,OAAO,aAAa,EAAE,UAAU,EAC3C,CAAC,SAAS,OAAO,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC,EAElD,GAAG,EAAE,CAAC,EACN,GAAG,MAAM,EAAE,OAAO,aAAa,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC,GAC1D,iBAAiB,CAAC;IAErB,6CAA6C;IAC7C,IAAI,CAAC,CAAC,SAAS,OAAO,aAAa,EAAE,aAAa,EAChD,GAAG,EAAE,CAAC,EACN,GAAG,MAAM,EAAE,OAAO,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,GAC5C,iBAAiB,CAAC;IAErB,kDAAkD;IAClD,IAAI,CAAC,GAAG,EAAE,OAAO,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;IAE9F,wCAAwC;IACxC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEpB,gCAAgC;IAChC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,+EAA+E;IAC/E,gBAAgB,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtF,gDAAgD;IAChD,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAElC,qDAAqD;IACrD,cAAc,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAEvC,mDAAmD;IACnD,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,KAAK,IAAI,CAAC;IAE1F,uCAAuC;IACvC,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD,sCAAsC;IACtC,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAExD,yCAAyC;IACzC,YAAY,EAAE,CACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,KACnF,MAAM,IAAI,CAAC;IAEhB,wCAAwC;IACxC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAEjG,oCAAoC;IACpC,iBAAiB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEjE,4CAA4C;IAC5C,kBAAkB,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E,kDAAkD;IAClD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAE3D,oCAAoC;IACpC,cAAc,EAAE,CACd,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,OAAO,KACrB,OAAO,CAAC;IAEb,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,MAAM,EAAE,CAAC;IAEjC,oCAAoC;IACpC,mBAAmB,EAAE,MAAM,MAAM,EAAE,CAAC;IAEpC,4BAA4B;IAC5B,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAElC,+BAA+B;IAC/B,EAAE,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAEjG,wDAAwD;IACxD,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAEjC,wDAAwD;IACxD,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAEnC,sDAAsD;IACtD,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAE/B,oEAAoE;IACpE,cAAc,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEvC,4FAA4F;IAC5F,kBAAkB,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE/C,0EAA0E;IAC1E,GAAG,EAAE,OAAO,KAAK,EAAE,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IAE9C,sEAAsE;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA+BD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,CAmBlD"}
|
|
@@ -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};
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -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
|
+
}
|