@fluenti/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 Fluenti Contributors
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,380 @@
1
+ # @fluenti/vue
2
+
3
+ **Compile-time i18n for Vue 3. Zero runtime parsing. Type-safe templates.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@fluenti/vue?color=4f46e5&label=npm)](https://www.npmjs.com/package/@fluenti/vue)
6
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@fluenti/vue?color=16a34a&label=size)](https://bundlephobia.com/package/@fluenti/vue)
7
+ [![license](https://img.shields.io/npm/l/@fluenti/vue?color=64748b)](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
8
+
9
+ Your translations are compiled at build time into optimized functions — no ICU parser ships to the browser, no runtime overhead, just fast string lookups. Write natural language in your templates; Fluenti handles the rest.
10
+
11
+ ---
12
+
13
+ ## The Magic: Write Natural Language, Ship Optimized Code
14
+
15
+ ### The `v-t` directive (compiled away at build time)
16
+
17
+ `v-t` is not a runtime directive. It is a **Vue compiler transform** that rewrites your templates during build. What you write and what ships to production are two different things:
18
+
19
+ ```vue
20
+ <!-- What you write -->
21
+ <template>
22
+ <h1 v-t>Welcome to our app!</h1>
23
+ <p v-t>Hello, {name}!</p>
24
+ <p v-t.plural="count">one apple | {count} apples</p>
25
+ <img v-t.alt alt="Hero banner" src="/hero.png" />
26
+ </template>
27
+ ```
28
+
29
+ ```vue
30
+ <!-- What ships to the browser (conceptual) -->
31
+ <template>
32
+ <h1>{{ $t('a1b2c3') }}</h1>
33
+ <p>{{ $t('d4e5f6', { name }) }}</p>
34
+ <p>{{ $t('{count, plural, one {# apple} other {# apples}}', { count }) }}</p>
35
+ <img :alt="$t('f7g8h9')" src="/hero.png" />
36
+ </template>
37
+ ```
38
+
39
+ No parsing. No interpretation. Just a hash lookup into a pre-compiled catalog. This is what compile-time i18n means.
40
+
41
+ ### The `t` tagged template (in `<script setup>`)
42
+
43
+ For programmatic translations outside of templates, use `msg` with `useI18n()`:
44
+
45
+ ```vue
46
+ <script setup lang="ts">
47
+ import { useI18n } from '@fluenti/vue'
48
+
49
+ const { t } = useI18n()
50
+
51
+ const greeting = t('Hello, {name}!', { name: 'World' })
52
+ const formatted = t('You have {count} items', { count: 42 })
53
+ </script>
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Quick Start
59
+
60
+ ### 1. Install
61
+
62
+ ```bash
63
+ pnpm add @fluenti/core @fluenti/vue @fluenti/vite-plugin
64
+ ```
65
+
66
+ ### 2. Configure Vite
67
+
68
+ ```ts
69
+ // vite.config.ts
70
+ import vue from '@vitejs/plugin-vue'
71
+ import fluenti from '@fluenti/vite-plugin'
72
+
73
+ export default {
74
+ plugins: [vue(), fluenti({ framework: 'vue' })],
75
+ }
76
+ ```
77
+
78
+ ### 3. Create the plugin
79
+
80
+ ```ts
81
+ // main.ts
82
+ import { createApp } from 'vue'
83
+ import { createFluentVue } from '@fluenti/vue'
84
+ import App from './App.vue'
85
+ import en from './locales/compiled/en'
86
+ import ja from './locales/compiled/ja'
87
+
88
+ const fluent = createFluentVue({
89
+ locale: 'en',
90
+ fallbackLocale: 'en',
91
+ messages: { en, ja },
92
+ })
93
+
94
+ const app = createApp(App)
95
+ app.use(fluent)
96
+ app.mount('#app')
97
+ ```
98
+
99
+ ### 4. Use in your SFC
100
+
101
+ ```vue
102
+ <script setup>
103
+ import { useI18n } from '@fluenti/vue'
104
+
105
+ const { locale, setLocale } = useI18n()
106
+ </script>
107
+
108
+ <template>
109
+ <h1 v-t>Hello, world!</h1>
110
+ <p v-t>Welcome to our application.</p>
111
+
112
+ <button @click="setLocale('ja')">日本語</button>
113
+ </template>
114
+ ```
115
+
116
+ That's it. Four files, zero boilerplate.
117
+
118
+ ---
119
+
120
+ ## Components
121
+
122
+ ### `<Trans>` — Rich Text with HTML and Components
123
+
124
+ Translate text that contains inline HTML elements or Vue components. Child elements are preserved through the translation round-trip:
125
+
126
+ ```vue
127
+ <template>
128
+ <Trans>Read the <a href="/docs">documentation</a></Trans>
129
+ <Trans>Click <RouterLink to="/next">here</RouterLink> to continue.</Trans>
130
+ </template>
131
+ ```
132
+
133
+ | Prop | Type | Default | Description |
134
+ |-------|----------|----------|-----------------|
135
+ | `tag` | `string` | `'span'` | Wrapper element |
136
+
137
+ ### `<Plural>` — Plural Forms
138
+
139
+ Full ICU plural support as a component. Use string props for simple cases, or named slots for rich text:
140
+
141
+ ```vue
142
+ <template>
143
+ <!-- Simple: string props -->
144
+ <Plural :value="count" zero="No items" one="1 item" other="{count} items" />
145
+
146
+ <!-- Rich: named slots -->
147
+ <Plural :value="count">
148
+ <template #zero>No <strong>items</strong> left</template>
149
+ <template #one><em>1</em> item remaining</template>
150
+ <template #other><strong>{{ count }}</strong> items remaining</template>
151
+ </Plural>
152
+ </template>
153
+ ```
154
+
155
+ | Prop | Type | Default | Description |
156
+ |---------|----------|----------|--------------------------------------|
157
+ | `value` | `number` | required | The count to pluralize on |
158
+ | `zero` | `string` | -- | Text for zero items (ICU `=0`) |
159
+ | `one` | `string` | -- | Singular form |
160
+ | `two` | `string` | -- | Dual form |
161
+ | `few` | `string` | -- | Few form (some languages) |
162
+ | `many` | `string` | -- | Many form (some languages) |
163
+ | `other` | `string` | `''` | Default/fallback form |
164
+ | `tag` | `string` | `'span'` | Wrapper element |
165
+
166
+ Slots: `#zero`, `#one`, `#two`, `#few`, `#many`, `#other` -- each receives `{ count }` as slot props.
167
+
168
+ ### `<Select>` — Gender / Option Selection
169
+
170
+ ICU select patterns as a component:
171
+
172
+ ```vue
173
+ <template>
174
+ <!-- String props -->
175
+ <Select :value="gender" male="He liked this" female="She liked this" other="They liked this" />
176
+
177
+ <!-- Options map (recommended for dynamic keys) -->
178
+ <Select :value="role" :options="{ admin: 'Administrator', editor: 'Editor' }" other="Viewer" />
179
+
180
+ <!-- Rich text via slots -->
181
+ <Select :value="gender">
182
+ <template #male><strong>He</strong> liked this</template>
183
+ <template #female><strong>She</strong> liked this</template>
184
+ <template #other><em>They</em> liked this</template>
185
+ </Select>
186
+ </template>
187
+ ```
188
+
189
+ | Prop | Type | Default | Description |
190
+ |-----------|---------------------------|----------|------------------------------------|
191
+ | `value` | `string` | required | The value to match against |
192
+ | `options` | `Record<string, string>` | -- | Named options map |
193
+ | `other` | `string` | `''` | Fallback when no option matches |
194
+ | `tag` | `string` | `'span'` | Wrapper element |
195
+
196
+ Slots: Named slots matching option keys, each receives `{ value }` as slot props.
197
+
198
+ ---
199
+
200
+ ## `v-t` Directive Reference
201
+
202
+ | Modifier | Effect |
203
+ |----------------|-----------------------------------|
204
+ | _(none)_ | Translates text content |
205
+ | `.plural` | Enables plural forms (pipe syntax)|
206
+ | `.alt` | Translates the `alt` attribute |
207
+ | `.placeholder` | Translates the `placeholder` attribute |
208
+ | `.title` | Translates the `title` attribute |
209
+ | `.{attr}` | Translates any named attribute |
210
+
211
+ ```vue
212
+ <template>
213
+ <h1 v-t>Hello, world!</h1>
214
+ <p v-t.plural="count">one apple | {count} apples</p>
215
+ <img v-t.alt alt="Welcome banner" src="banner.png" />
216
+ <input v-t.placeholder placeholder="Search..." />
217
+ </template>
218
+ ```
219
+
220
+ ---
221
+
222
+ ## `useI18n()` Composable
223
+
224
+ The full API surface, available inside any component with the plugin installed:
225
+
226
+ ```vue
227
+ <script setup>
228
+ import { useI18n } from '@fluenti/vue'
229
+
230
+ const { t, d, n, locale, setLocale } = useI18n()
231
+ </script>
232
+
233
+ <template>
234
+ <p>{{ t('Hello, {name}!', { name: 'World' }) }}</p>
235
+ <p>{{ d(new Date(), 'long') }}</p>
236
+ <p>{{ n(1234.5, 'currency') }}</p>
237
+ <button @click="setLocale('ja')">日本語</button>
238
+ </template>
239
+ ```
240
+
241
+ | Method | Signature | Description |
242
+ |-----------------|----------------------------------------------------------------|----------------------------------------------------------|
243
+ | `t` | `(id: string \| MessageDescriptor, values?) => string` | Translate a key with optional interpolation |
244
+ | `d` | `(value: Date \| number, style?) => string` | Format a date using `dateFormats` presets or Intl |
245
+ | `n` | `(value: number, style?) => string` | Format a number using `numberFormats` presets or Intl |
246
+ | `format` | `(message: string, values?) => string` | Format an ICU message string directly (no catalog lookup)|
247
+ | `te` | `(key: string, locale?) => boolean` | Check if a translation key exists |
248
+ | `tm` | `(key: string, locale?) => CompiledMessage \| undefined` | Get the raw compiled message without interpolation |
249
+ | `locale` | `Ref<string>` (readonly) | Reactive ref for the current locale |
250
+ | `setLocale` | `(locale: string) => Promise<void>` | Change locale (async when lazy locale loading is enabled) |
251
+ | `loadMessages` | `(locale: string, messages: Messages) => void` | Dynamically add messages for a locale at runtime |
252
+ | `getLocales` | `() => string[]` | Get all locales that have loaded messages |
253
+ | `preloadLocale` | `(locale: string) => void` | Preload a locale chunk in the background |
254
+ | `isLoading` | `Ref<boolean>` (readonly) | Whether a locale chunk is currently being loaded |
255
+ | `loadedLocales` | `Ref<ReadonlySet<string>>` (readonly) | Set of locales whose messages have been loaded |
256
+
257
+ ---
258
+
259
+ ## Plugin Options
260
+
261
+ ```ts
262
+ const fluent = createFluentVue({
263
+ // Required
264
+ locale: 'en',
265
+ messages: { en, ja, zh },
266
+
267
+ // Optional
268
+ fallbackLocale: 'en',
269
+ fallbackChain: { 'zh-TW': ['zh', 'en'], '*': ['en'] },
270
+ dateFormats: {
271
+ short: { year: 'numeric', month: 'short', day: 'numeric' },
272
+ long: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' },
273
+ relative: 'relative',
274
+ },
275
+ numberFormats: {
276
+ currency: { style: 'currency', currency: 'USD' },
277
+ percent: { style: 'percent', minimumFractionDigits: 1 },
278
+ },
279
+ missing: (locale, id) => `[missing: ${id}]`,
280
+ componentPrefix: 'I18n', // registers I18nTrans, I18nPlural, I18nSelect
281
+ lazyLocaleLoading: true,
282
+ chunkLoader: (locale) => import(`./locales/${locale}.js`),
283
+
284
+ // Post-translation transform applied to every resolved message
285
+ transform: (result, id, locale) => result,
286
+
287
+ // Callback fired whenever the locale changes
288
+ onLocaleChange: (newLocale, prevLocale) => {
289
+ document.documentElement.lang = newLocale
290
+ },
291
+
292
+ // Custom ICU function formatters (e.g. {items, list})
293
+ formatters: {
294
+ list: (value, style, locale) =>
295
+ new Intl.ListFormat(locale, { type: style || 'conjunction' }).format(value),
296
+ },
297
+ })
298
+ ```
299
+
300
+ | Option | Type | Default | Description |
301
+ |-------------------|------------------------------------|---------|----------------------------------------------------------|
302
+ | `locale` | `string` | -- | Active locale code (required) |
303
+ | `messages` | `Record<string, Messages>` | -- | Pre-loaded message catalogs (required) |
304
+ | `fallbackLocale` | `string` | -- | Locale to try when a key is missing |
305
+ | `fallbackChain` | `Record<string, string[]>` | -- | Locale-specific fallback chains (`'*'` for default) |
306
+ | `dateFormats` | `Record<string, DateTimeFormatOptions \| 'relative'>` | -- | Named date format presets for `d()` |
307
+ | `numberFormats` | `Record<string, NumberFormatOptions>` | -- | Named number format presets for `n()` |
308
+ | `missing` | `(locale, id) => string \| undefined` | -- | Handler called when a translation key is not found |
309
+ | `componentPrefix` | `string` | `''` | Prefix for globally registered components |
310
+ | `lazyLocaleLoading` | `boolean` | `false` | Enable async locale loading through `chunkLoader` |
311
+ | `chunkLoader` | `(locale) => Promise<Messages>` | -- | Async loader for locale chunks (requires `lazyLocaleLoading`) |
312
+ | `transform` | `(result: string, id: string, locale: string) => string` | -- | Post-interpolation hook applied to every resolved message |
313
+ | `onLocaleChange` | `(newLocale: string, prevLocale: string) => void` | -- | Callback fired whenever the locale changes via `setLocale()` |
314
+ | `formatters` | `Record<string, CustomFormatter>` | -- | Custom ICU function formatters keyed by function name |
315
+
316
+ ---
317
+
318
+ ## Code Splitting
319
+
320
+ For large apps, load locale messages on demand instead of bundling everything upfront:
321
+
322
+ ```ts
323
+ const fluent = createFluentVue({
324
+ locale: 'en',
325
+ messages: { en }, // only the default locale is bundled
326
+ lazyLocaleLoading: true,
327
+ chunkLoader: (locale) => import(`./locales/compiled/${locale}.js`),
328
+ })
329
+
330
+ // Later: switching locale triggers async loading
331
+ await fluent.global.setLocale('ja') // loads ja chunk, then switches
332
+ ```
333
+
334
+ Preload locales in the background for instant switching:
335
+
336
+ ```vue
337
+ <script setup>
338
+ const { setLocale, isLoading, preloadLocale } = useI18n()
339
+ </script>
340
+
341
+ <template>
342
+ <button @mouseenter="preloadLocale('ja')" @click="setLocale('ja')" :disabled="isLoading">
343
+ {{ isLoading ? 'Loading...' : '日本語' }}
344
+ </button>
345
+ </template>
346
+ ```
347
+
348
+ ---
349
+
350
+ ## SSR / SSG Support
351
+
352
+ `createFluentVue()` creates entirely fresh state per call -- no module-level singletons. Call it once per SSR request to avoid locale leaking between users.
353
+
354
+ For server-side i18n in Nuxt or custom Vue SSR setups, use the dedicated server utilities:
355
+
356
+ ```ts
357
+ import { createServerI18n, detectLocale, getSSRLocaleScript } from '@fluenti/vue/server'
358
+
359
+ const { setLocale, getI18n } = createServerI18n({
360
+ loadMessages: (locale) => import(`./locales/compiled/${locale}.js`),
361
+ fallbackLocale: 'en',
362
+ })
363
+ ```
364
+
365
+ SSR utilities included:
366
+ - `createServerI18n()` -- per-request i18n with lazy message loading and caching
367
+ - `detectLocale()` -- locale detection from cookies, headers, path, or query
368
+ - `getSSRLocaleScript()` -- inline script tag for hydration
369
+ - `getHydratedLocale()` -- read the hydrated locale on the client
370
+ - `isRTL()` / `getDirection()` -- RTL/LTR detection
371
+
372
+ ---
373
+
374
+ ## Documentation
375
+
376
+ Full documentation at [fluenti.dev](https://fluenti.dev).
377
+
378
+ ## License
379
+
380
+ [MIT](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
@@ -0,0 +1,3 @@
1
+ import { CompileTimeT } from '@fluenti/core';
2
+ export declare const t: CompileTimeT;
3
+ //# sourceMappingURL=compile-time-t.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-time-t.d.ts","sourceRoot":"","sources":["../src/compile-time-t.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,eAAO,MAAM,CAAC,EAAE,YAME,CAAA"}
@@ -0,0 +1,60 @@
1
+ import { ExtractPropTypes, PropType } from 'vue';
2
+ /**
3
+ * `<DateTime>` component for formatting dates according to locale.
4
+ *
5
+ * @example
6
+ * ```vue
7
+ * <DateTime :value="new Date()" />
8
+ * <DateTime :value="Date.now()" style="short" />
9
+ * <DateTime :value="event.date" style="long" tag="time" />
10
+ * ```
11
+ */
12
+ declare const dateTimeProps: {
13
+ readonly value: {
14
+ readonly type: PropType<Date | number>;
15
+ readonly required: true;
16
+ };
17
+ readonly style: {
18
+ readonly type: StringConstructor;
19
+ readonly default: undefined;
20
+ };
21
+ readonly tag: {
22
+ readonly type: StringConstructor;
23
+ readonly default: "span";
24
+ };
25
+ };
26
+ export type DateTimeProps = Readonly<ExtractPropTypes<typeof dateTimeProps>>;
27
+ export declare const DateTime: import('vue').DefineComponent<ExtractPropTypes<{
28
+ readonly value: {
29
+ readonly type: PropType<Date | number>;
30
+ readonly required: true;
31
+ };
32
+ readonly style: {
33
+ readonly type: StringConstructor;
34
+ readonly default: undefined;
35
+ };
36
+ readonly tag: {
37
+ readonly type: StringConstructor;
38
+ readonly default: "span";
39
+ };
40
+ }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
41
+ [key: string]: any;
42
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ExtractPropTypes<{
43
+ readonly value: {
44
+ readonly type: PropType<Date | number>;
45
+ readonly required: true;
46
+ };
47
+ readonly style: {
48
+ readonly type: StringConstructor;
49
+ readonly default: undefined;
50
+ };
51
+ readonly tag: {
52
+ readonly type: StringConstructor;
53
+ readonly default: "span";
54
+ };
55
+ }>> & Readonly<{}>, {
56
+ readonly style: string;
57
+ readonly tag: string;
58
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
59
+ export {};
60
+ //# sourceMappingURL=DateTime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateTime.d.ts","sourceRoot":"","sources":["../../src/components/DateTime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AAGrD;;;;;;;;;GASG;AACH,QAAA,MAAM,aAAa;;uBACgB,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;;;;;;;;;;;CAGhD,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,aAAa,CAAC,CAAC,CAAA;AAE5E,eAAO,MAAM,QAAQ;;uBAPc,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;;;;;;;;;;;;;;;uBAAvB,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;;;;;;;;;;;;;;4EAcxD,CAAA"}
@@ -0,0 +1,60 @@
1
+ import { ExtractPropTypes } from 'vue';
2
+ /**
3
+ * `<NumberFormat>` component for formatting numbers according to locale.
4
+ *
5
+ * @example
6
+ * ```vue
7
+ * <NumberFormat :value="1234.56" />
8
+ * <NumberFormat :value="0.75" style="percent" />
9
+ * <NumberFormat :value="99.99" style="currency" tag="strong" />
10
+ * ```
11
+ */
12
+ declare const numberFormatProps: {
13
+ readonly value: {
14
+ readonly type: NumberConstructor;
15
+ readonly required: true;
16
+ };
17
+ readonly style: {
18
+ readonly type: StringConstructor;
19
+ readonly default: undefined;
20
+ };
21
+ readonly tag: {
22
+ readonly type: StringConstructor;
23
+ readonly default: "span";
24
+ };
25
+ };
26
+ export type NumberFormatProps = Readonly<ExtractPropTypes<typeof numberFormatProps>>;
27
+ export declare const NumberFormat: import('vue').DefineComponent<ExtractPropTypes<{
28
+ readonly value: {
29
+ readonly type: NumberConstructor;
30
+ readonly required: true;
31
+ };
32
+ readonly style: {
33
+ readonly type: StringConstructor;
34
+ readonly default: undefined;
35
+ };
36
+ readonly tag: {
37
+ readonly type: StringConstructor;
38
+ readonly default: "span";
39
+ };
40
+ }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
41
+ [key: string]: any;
42
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ExtractPropTypes<{
43
+ readonly value: {
44
+ readonly type: NumberConstructor;
45
+ readonly required: true;
46
+ };
47
+ readonly style: {
48
+ readonly type: StringConstructor;
49
+ readonly default: undefined;
50
+ };
51
+ readonly tag: {
52
+ readonly type: StringConstructor;
53
+ readonly default: "span";
54
+ };
55
+ }>> & Readonly<{}>, {
56
+ readonly style: string;
57
+ readonly tag: string;
58
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
59
+ export {};
60
+ //# sourceMappingURL=NumberFormat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumberFormat.d.ts","sourceRoot":"","sources":["../../src/components/NumberFormat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAG3C;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;CAIb,CAAA;AAEV,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAA;AAEpF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4EAOvB,CAAA"}
@@ -0,0 +1,138 @@
1
+ import { ExtractPropTypes } from 'vue';
2
+ /**
3
+ * `<Plural>` component — shorthand for ICU plural patterns.
4
+ *
5
+ * Plural form props (`zero`, `one`, `two`, `few`, `many`, `other`) are treated
6
+ * as source-language messages. The component builds an ICU plural message,
7
+ * looks it up via `t()` in the catalog, and interpolates the translated result.
8
+ *
9
+ * When no catalog translation exists, the component falls back to interpolating
10
+ * the source-language ICU message directly via the `message` field of the
11
+ * MessageDescriptor.
12
+ *
13
+ * Rich text is supported via named slots:
14
+ * ```vue
15
+ * <Plural :value="count">
16
+ * <template #zero>No <strong>items</strong></template>
17
+ * <template #one><em>1</em> item</template>
18
+ * <template #other><strong>{{ count }}</strong> items</template>
19
+ * </Plural>
20
+ * ```
21
+ *
22
+ * String props still work (backward compatible):
23
+ * ```vue
24
+ * <Plural :value="count" zero="No items" one="# item" other="# items" />
25
+ * ```
26
+ */
27
+ declare const pluralProps: {
28
+ /** The numeric value to pluralise on */
29
+ readonly value: {
30
+ readonly type: NumberConstructor;
31
+ readonly required: true;
32
+ };
33
+ /** Override the auto-generated synthetic ICU message id */
34
+ readonly id: StringConstructor;
35
+ /** Message context used for identity and translator disambiguation */
36
+ readonly context: StringConstructor;
37
+ /** Translator-facing note preserved in extraction catalogs */
38
+ readonly comment: StringConstructor;
39
+ /** Text for zero items (maps to `=0`) */
40
+ readonly zero: StringConstructor;
41
+ /** Text for singular (maps to `one`) */
42
+ readonly one: StringConstructor;
43
+ /** Text for dual (maps to `two`) */
44
+ readonly two: StringConstructor;
45
+ /** Text for few (maps to `few`) */
46
+ readonly few: StringConstructor;
47
+ /** Text for many (maps to `many`) */
48
+ readonly many: StringConstructor;
49
+ /** Text for the default/other category */
50
+ readonly other: {
51
+ readonly type: StringConstructor;
52
+ readonly default: undefined;
53
+ };
54
+ /** Offset from value before selecting form */
55
+ readonly offset: NumberConstructor;
56
+ /** Wrapper element tag name (default: `span`) */
57
+ readonly tag: {
58
+ readonly type: StringConstructor;
59
+ readonly default: "span";
60
+ };
61
+ };
62
+ export type PluralProps = Readonly<ExtractPropTypes<typeof pluralProps>>;
63
+ export declare const Plural: import('vue').DefineComponent<ExtractPropTypes<{
64
+ /** The numeric value to pluralise on */
65
+ readonly value: {
66
+ readonly type: NumberConstructor;
67
+ readonly required: true;
68
+ };
69
+ /** Override the auto-generated synthetic ICU message id */
70
+ readonly id: StringConstructor;
71
+ /** Message context used for identity and translator disambiguation */
72
+ readonly context: StringConstructor;
73
+ /** Translator-facing note preserved in extraction catalogs */
74
+ readonly comment: StringConstructor;
75
+ /** Text for zero items (maps to `=0`) */
76
+ readonly zero: StringConstructor;
77
+ /** Text for singular (maps to `one`) */
78
+ readonly one: StringConstructor;
79
+ /** Text for dual (maps to `two`) */
80
+ readonly two: StringConstructor;
81
+ /** Text for few (maps to `few`) */
82
+ readonly few: StringConstructor;
83
+ /** Text for many (maps to `many`) */
84
+ readonly many: StringConstructor;
85
+ /** Text for the default/other category */
86
+ readonly other: {
87
+ readonly type: StringConstructor;
88
+ readonly default: undefined;
89
+ };
90
+ /** Offset from value before selecting form */
91
+ readonly offset: NumberConstructor;
92
+ /** Wrapper element tag name (default: `span`) */
93
+ readonly tag: {
94
+ readonly type: StringConstructor;
95
+ readonly default: "span";
96
+ };
97
+ }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
98
+ [key: string]: any;
99
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ExtractPropTypes<{
100
+ /** The numeric value to pluralise on */
101
+ readonly value: {
102
+ readonly type: NumberConstructor;
103
+ readonly required: true;
104
+ };
105
+ /** Override the auto-generated synthetic ICU message id */
106
+ readonly id: StringConstructor;
107
+ /** Message context used for identity and translator disambiguation */
108
+ readonly context: StringConstructor;
109
+ /** Translator-facing note preserved in extraction catalogs */
110
+ readonly comment: StringConstructor;
111
+ /** Text for zero items (maps to `=0`) */
112
+ readonly zero: StringConstructor;
113
+ /** Text for singular (maps to `one`) */
114
+ readonly one: StringConstructor;
115
+ /** Text for dual (maps to `two`) */
116
+ readonly two: StringConstructor;
117
+ /** Text for few (maps to `few`) */
118
+ readonly few: StringConstructor;
119
+ /** Text for many (maps to `many`) */
120
+ readonly many: StringConstructor;
121
+ /** Text for the default/other category */
122
+ readonly other: {
123
+ readonly type: StringConstructor;
124
+ readonly default: undefined;
125
+ };
126
+ /** Offset from value before selecting form */
127
+ readonly offset: NumberConstructor;
128
+ /** Wrapper element tag name (default: `span`) */
129
+ readonly tag: {
130
+ readonly type: StringConstructor;
131
+ readonly default: "span";
132
+ };
133
+ }>> & Readonly<{}>, {
134
+ readonly other: string;
135
+ readonly tag: string;
136
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
137
+ export {};
138
+ //# sourceMappingURL=Plural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plural.d.ts","sourceRoot":"","sources":["../../src/components/Plural.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAA4B,MAAM,KAAK,CAAA;AAsCrE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,QAAA,MAAM,WAAW;IACf,wCAAwC;;;;;IAExC,2DAA2D;;IAE3D,sEAAsE;;IAEtE,8DAA8D;;IAE9D,yCAAyC;;IAEzC,wCAAwC;;IAExC,oCAAoC;;IAEpC,mCAAmC;;IAEnC,qCAAqC;;IAErC,0CAA0C;;;;;IAE1C,8CAA8C;;IAE9C,iDAAiD;;;;;CAEzC,CAAA;AAEV,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;AAExE,eAAO,MAAM,MAAM;IA5BjB,wCAAwC;;;;;IAExC,2DAA2D;;IAE3D,sEAAsE;;IAEtE,8DAA8D;;IAE9D,yCAAyC;;IAEzC,wCAAwC;;IAExC,oCAAoC;;IAEpC,mCAAmC;;IAEnC,qCAAqC;;IAErC,0CAA0C;;;;;IAE1C,8CAA8C;;IAE9C,iDAAiD;;;;;;;;IAtBjD,wCAAwC;;;;;IAExC,2DAA2D;;IAE3D,sEAAsE;;IAEtE,8DAA8D;;IAE9D,yCAAyC;;IAEzC,wCAAwC;;IAExC,oCAAoC;;IAEpC,mCAAmC;;IAEnC,qCAAqC;;IAErC,0CAA0C;;;;;IAE1C,8CAA8C;;IAE9C,iDAAiD;;;;;;;;4EAuDjD,CAAA"}