@fluenti/vue 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/components/DateTime.d.ts +1 -1
- package/dist/components/DateTime.d.ts.map +1 -1
- package/dist/components/NumberFormat.d.ts +1 -1
- package/dist/components/NumberFormat.d.ts.map +1 -1
- package/dist/components/Plural.d.ts +12 -13
- package/dist/components/Plural.d.ts.map +1 -1
- package/dist/components/Select.d.ts +12 -13
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Trans.d.ts +7 -7
- package/dist/components/Trans.d.ts.map +1 -1
- package/dist/components/rich-text.d.ts +0 -6
- package/dist/components/rich-text.d.ts.map +1 -1
- package/dist/hooks/__useI18n.d.ts +2 -2
- package/dist/hooks/__useI18n.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +155 -169
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +25 -14
- package/dist/plugin.d.ts.map +1 -1
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +33 -13
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +54 -0
- package/dist/server.js.map +1 -0
- package/dist/use-i18n.d.ts +3 -3
- package/dist/use-i18n.d.ts.map +1 -1
- package/dist/vite-plugin.cjs +1 -111
- package/dist/vite-plugin.cjs.map +1 -1
- package/dist/vite-plugin.js +18 -126
- package/dist/vite-plugin.js.map +1 -1
- package/dist/vue-runtime.d.ts.map +1 -1
- package/llms-full.txt +220 -0
- package/llms-migration.txt +199 -0
- package/llms.txt +82 -0
- package/package.json +17 -5
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Migrating to @fluenti/vue from vue-i18n
|
|
2
|
+
|
|
3
|
+
> Step-by-step guide to migrate a Vue 3 app from vue-i18n (v9/v10) to Fluenti.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Fluenti is a **compile-time** i18n library — translations are compiled to optimized JS at build time, resulting in zero runtime overhead and smaller bundles. vue-i18n is a runtime library that parses messages on every render.
|
|
8
|
+
|
|
9
|
+
Key differences:
|
|
10
|
+
- Fluenti uses ICU MessageFormat; vue-i18n uses its own syntax
|
|
11
|
+
- Fluenti requires a Vite plugin for build-time compilation
|
|
12
|
+
- Fluenti catalog files use PO (gettext) or JSON format, managed by the CLI
|
|
13
|
+
- No runtime parser needed — messages become plain strings or template functions
|
|
14
|
+
|
|
15
|
+
## Gradual Migration with @fluenti/vue-i18n-compat
|
|
16
|
+
|
|
17
|
+
For large projects, use the compatibility bridge to run both libraries side by side:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @fluenti/vue-i18n-compat @fluenti/core @fluenti/vue
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createI18n } from 'vue-i18n'
|
|
25
|
+
import { createFluenti } from '@fluenti/vue'
|
|
26
|
+
import { createFluentBridge } from '@fluenti/vue-i18n-compat'
|
|
27
|
+
|
|
28
|
+
const i18n = createI18n({ legacy: false, locale: 'en', messages: { en: legacyMessages } })
|
|
29
|
+
const fluenti = createFluenti({ locale: 'en', fallbackLocale: 'en', messages: { en: newMessages } })
|
|
30
|
+
const bridge = createFluentBridge({ vueI18n: i18n, fluenti, priority: 'fluenti-first' })
|
|
31
|
+
|
|
32
|
+
app.use(bridge) // installs both, syncs locale, falls through on lookups
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then migrate messages one at a time. When done, remove the bridge and use @fluenti/vue directly.
|
|
36
|
+
|
|
37
|
+
## Step-by-step Migration (Direct)
|
|
38
|
+
|
|
39
|
+
### 1. Install Fluenti packages
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm add @fluenti/core @fluenti/vue
|
|
43
|
+
pnpm add -D @fluenti/cli
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Update Vite config
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// vite.config.ts
|
|
50
|
+
import vue from '@vitejs/plugin-vue'
|
|
51
|
+
import fluentiVue from '@fluenti/vue/vite-plugin'
|
|
52
|
+
|
|
53
|
+
export default {
|
|
54
|
+
plugins: [vue(), fluentiVue()],
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Replace plugin setup
|
|
59
|
+
|
|
60
|
+
Before (vue-i18n):
|
|
61
|
+
```ts
|
|
62
|
+
import { createI18n } from 'vue-i18n'
|
|
63
|
+
const i18n = createI18n({ locale: 'en', messages: { en, ja } })
|
|
64
|
+
app.use(i18n)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
After (Fluenti):
|
|
68
|
+
```ts
|
|
69
|
+
import { createFluenti } from '@fluenti/vue'
|
|
70
|
+
const fluent = createFluenti({ locale: 'en', fallbackLocale: 'en', messages: { en, ja } })
|
|
71
|
+
app.use(fluent)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. Update composable usage
|
|
75
|
+
|
|
76
|
+
Before (vue-i18n):
|
|
77
|
+
```ts
|
|
78
|
+
import { useI18n } from 'vue-i18n'
|
|
79
|
+
const { t, locale } = useI18n()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
After (Fluenti):
|
|
83
|
+
```ts
|
|
84
|
+
import { useI18n } from '@fluenti/vue'
|
|
85
|
+
const { t, locale, setLocale } = useI18n()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 5. Convert message syntax
|
|
89
|
+
|
|
90
|
+
vue-i18n named interpolation → ICU MessageFormat:
|
|
91
|
+
```
|
|
92
|
+
# vue-i18n
|
|
93
|
+
"hello": "Hello, {name}!"
|
|
94
|
+
|
|
95
|
+
# Fluenti (same for simple cases)
|
|
96
|
+
"hello": "Hello, {name}!"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
vue-i18n pluralization → ICU plural:
|
|
100
|
+
```
|
|
101
|
+
# vue-i18n (pipe syntax)
|
|
102
|
+
"items": "no items | one item | {count} items"
|
|
103
|
+
|
|
104
|
+
# Fluenti (ICU MessageFormat)
|
|
105
|
+
"items": "{count, plural, =0 {no items} one {one item} other {{count} items}}"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
vue-i18n linked messages → not supported (use message functions):
|
|
109
|
+
```
|
|
110
|
+
# vue-i18n
|
|
111
|
+
"greeting": "@:hello, welcome!"
|
|
112
|
+
|
|
113
|
+
# Fluenti — inline the full message or use code
|
|
114
|
+
"greeting": "Hello, {name}, welcome!"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 6. Update template syntax
|
|
118
|
+
|
|
119
|
+
Before (vue-i18n):
|
|
120
|
+
```vue
|
|
121
|
+
<template>
|
|
122
|
+
<p>{{ $t('hello', { name: 'World' }) }}</p>
|
|
123
|
+
<i18n-t keypath="terms" tag="p">
|
|
124
|
+
<template #link><a href="/terms">terms</a></template>
|
|
125
|
+
</i18n-t>
|
|
126
|
+
</template>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After (Fluenti):
|
|
130
|
+
```vue
|
|
131
|
+
<template>
|
|
132
|
+
<p>{{ t('hello', { name: 'World' }) }}</p>
|
|
133
|
+
<Trans message="Read the {0}terms{1}">
|
|
134
|
+
<template #0><a href="/terms"></template>
|
|
135
|
+
<template #1></a></template>
|
|
136
|
+
</Trans>
|
|
137
|
+
<!-- Or use v-t directive for simple text -->
|
|
138
|
+
<p v-t>Hello</p>
|
|
139
|
+
</template>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 7. Remove vue-i18n
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
pnpm remove vue-i18n
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## API Mapping Table
|
|
149
|
+
|
|
150
|
+
| vue-i18n | Fluenti |
|
|
151
|
+
|----------|---------|
|
|
152
|
+
| `createI18n()` | `createFluenti()` |
|
|
153
|
+
| `useI18n()` | `useI18n()` |
|
|
154
|
+
| `t(key, values)` | `t(key, values)` |
|
|
155
|
+
| `tc(key, count)` | `t(key, { count })` (ICU plural) |
|
|
156
|
+
| `te(key)` | `te(key)` |
|
|
157
|
+
| `tm(key)` | `tm(key)` |
|
|
158
|
+
| `d(value, format)` | `d(value, style)` |
|
|
159
|
+
| `n(value, format)` | `n(value, style)` |
|
|
160
|
+
| `locale.value = 'ja'` | `setLocale('ja')` |
|
|
161
|
+
| `$t()` in template | `t()` in template (via useI18n) |
|
|
162
|
+
| `<i18n-t>` component | `<Trans>` component |
|
|
163
|
+
| `v-t` directive | `v-t` directive (same syntax) |
|
|
164
|
+
| `@:key` linked messages | Not supported — inline messages |
|
|
165
|
+
| Pipe plurals `a \| b \| c` | ICU `{n, plural, ...}` |
|
|
166
|
+
| `numberFormats` option | `numberFormats` option |
|
|
167
|
+
| `datetimeFormats` option | `dateFormats` option |
|
|
168
|
+
|
|
169
|
+
## Translation File Conversion
|
|
170
|
+
|
|
171
|
+
Use the Fluenti CLI to manage catalogs:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Create config
|
|
175
|
+
cat > fluenti.config.ts << 'EOF'
|
|
176
|
+
export default {
|
|
177
|
+
sourceLocale: 'en',
|
|
178
|
+
locales: ['en', 'ja'],
|
|
179
|
+
catalogDir: './locales',
|
|
180
|
+
format: 'po',
|
|
181
|
+
include: ['./src/**/*.{vue,ts}'],
|
|
182
|
+
compileOutDir: './locales/compiled',
|
|
183
|
+
}
|
|
184
|
+
EOF
|
|
185
|
+
|
|
186
|
+
# Extract messages from source
|
|
187
|
+
npx fluenti extract
|
|
188
|
+
|
|
189
|
+
# Compile catalogs to JS
|
|
190
|
+
npx fluenti compile
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Key Behavioral Differences
|
|
194
|
+
|
|
195
|
+
1. **No runtime parser** — messages are compiled at build time, so syntax errors are caught early
|
|
196
|
+
2. **No lazy locale loading by default** — use `lazyLocaleLoading: true` with a `chunkLoader` for dynamic locale chunks
|
|
197
|
+
3. **No global `$t`** — use `useI18n()` composable or `v-t` directive
|
|
198
|
+
4. **ICU MessageFormat** — standard plural/select/number/date formatting, not custom vue-i18n syntax
|
|
199
|
+
5. **PO file support** — compatible with professional translation tools (Poedit, Crowdin, Weblate)
|
package/llms.txt
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# @fluenti/vue
|
|
2
|
+
|
|
3
|
+
> Vue 3 bindings for Fluenti — compile-time `t`, `v-t`, runtime-capable components, and a `useI18n()` composable.
|
|
4
|
+
|
|
5
|
+
@fluenti/vue provides the Vue-side runtime for Fluenti. The recommended authoring path is:
|
|
6
|
+
|
|
7
|
+
- compile-time: `import { t } from '@fluenti/vue'`
|
|
8
|
+
- runtime / imperative usage: `useI18n()`
|
|
9
|
+
- template authoring: `v-t`, `<Trans>`, `<Plural>`, `<Select>`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @fluenti/core @fluenti/vue @fluenti/vite-plugin
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createFluenti } from '@fluenti/vue'
|
|
21
|
+
|
|
22
|
+
const fluent = createFluenti({
|
|
23
|
+
locale: 'en',
|
|
24
|
+
fallbackLocale: 'en',
|
|
25
|
+
messages: { en, ja },
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
app.use(fluent)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Main Exports
|
|
32
|
+
|
|
33
|
+
- `createFluenti(options)` — Vue plugin factory
|
|
34
|
+
- `useI18n()` — composable returning the full i18n context
|
|
35
|
+
- `t` — compile-time-only authoring API for tagged templates and descriptors
|
|
36
|
+
- `Trans`, `Plural`, `Select`, `DateTime`, `NumberFormat` — runtime-capable components
|
|
37
|
+
- `FluentiTransProps`, `FluentiPluralProps`, `FluentiSelectProps`, `FluentiDateTimeProps`, `FluentiNumberFormatProps` — component prop types
|
|
38
|
+
- `msg` — lazy message descriptor helper
|
|
39
|
+
- `FLUENTI_KEY` — injection key
|
|
40
|
+
|
|
41
|
+
## Plugin Options
|
|
42
|
+
|
|
43
|
+
| Option | Type | Default | Description |
|
|
44
|
+
|--------|------|---------|-------------|
|
|
45
|
+
| `locale` | `string` | — | Active locale (required) |
|
|
46
|
+
| `messages` | `Record<string, Messages>` | — | Message catalogs (required) |
|
|
47
|
+
| `fallbackLocale` | `string` | — | Fallback locale |
|
|
48
|
+
| `fallbackChain` | `Record<string, string[]>` | — | Locale-specific fallback chains |
|
|
49
|
+
| `dateFormats` | `Record<string, DateTimeFormatOptions \| 'relative'>` | — | Named date presets |
|
|
50
|
+
| `numberFormats` | `Record<string, NumberFormatOptions>` | — | Named number presets |
|
|
51
|
+
| `missing` | `(locale, id) => string \| undefined` | — | Missing handler |
|
|
52
|
+
| `componentPrefix` | `string` | `''` | Prefix for registered components |
|
|
53
|
+
| `lazyLocaleLoading` | `boolean` | `false` | Enable async locale loading |
|
|
54
|
+
| `chunkLoader` | `(locale) => Promise<Messages \| { default: Messages }>` | — | Async loader used with `lazyLocaleLoading` |
|
|
55
|
+
|
|
56
|
+
## Important Boundaries
|
|
57
|
+
|
|
58
|
+
- `t` imported from `@fluenti/vue` is compile-time only and requires the Fluenti plugin / loader
|
|
59
|
+
- `useI18n().t()` is the full runtime API for lookup and imperative formatting
|
|
60
|
+
- `<Trans>`, `<Plural>`, `<Select>`, `<DateTime>`, and `<NumberFormat>` remain runtime-capable even without the build plugin
|
|
61
|
+
|
|
62
|
+
## Preferred Usage (compile-time first)
|
|
63
|
+
|
|
64
|
+
1. `v-t` directive — `<p v-t>Hello {name}</p>` (Vue templates, zero runtime cost)
|
|
65
|
+
2. t\`\` tagged template — t\`Hello {name}\` (primary compile-time API)
|
|
66
|
+
3. `<Trans>` / `<Plural>` / `<Select>` — rich text with inline markup
|
|
67
|
+
4. `msg` tagged template — outside components (route meta, stores)
|
|
68
|
+
5. `useI18n().t()` — runtime fallback for dynamic keys only
|
|
69
|
+
|
|
70
|
+
❌ AVOID: `t('some.key')` as the default — this is a legacy i18n pattern.
|
|
71
|
+
|
|
72
|
+
## Server Subpath: `@fluenti/vue/server`
|
|
73
|
+
|
|
74
|
+
Server-side utilities for SSR:
|
|
75
|
+
|
|
76
|
+
- `createServerI18n(config)` — request-scoped runtime helpers for server rendering
|
|
77
|
+
- Re-exports from `@fluenti/core`: `detectLocale`, `getSSRLocaleScript`, `getHydratedLocale`, `isRTL`, `getDirection`
|
|
78
|
+
|
|
79
|
+
## Docs
|
|
80
|
+
|
|
81
|
+
- Full docs: https://fluenti.dev
|
|
82
|
+
- Source: https://github.com/usefluenti/fluenti
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluenti/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vue 3 compile-time i18n — v-t directive, Trans/Plural/Select components, useI18n composable",
|
|
6
6
|
"homepage": "https://fluenti.dev",
|
|
@@ -41,6 +41,16 @@
|
|
|
41
41
|
"default": "./dist/index.cjs"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
+
"./server": {
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/server.d.ts",
|
|
47
|
+
"default": "./dist/server.js"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/server.d.ts",
|
|
51
|
+
"default": "./dist/server.cjs"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
44
54
|
"./vite-plugin": {
|
|
45
55
|
"import": {
|
|
46
56
|
"types": "./dist/vite-plugin.d.ts",
|
|
@@ -53,7 +63,8 @@
|
|
|
53
63
|
}
|
|
54
64
|
},
|
|
55
65
|
"files": [
|
|
56
|
-
"dist"
|
|
66
|
+
"dist",
|
|
67
|
+
"llms*.txt"
|
|
57
68
|
],
|
|
58
69
|
"peerDependencies": {
|
|
59
70
|
"vue": "^3.5",
|
|
@@ -65,8 +76,8 @@
|
|
|
65
76
|
}
|
|
66
77
|
},
|
|
67
78
|
"dependencies": {
|
|
68
|
-
"@fluenti/core": "0.
|
|
69
|
-
"@fluenti/vite-plugin": "0.
|
|
79
|
+
"@fluenti/core": "0.3.0",
|
|
80
|
+
"@fluenti/vite-plugin": "0.3.0"
|
|
70
81
|
},
|
|
71
82
|
"devDependencies": {
|
|
72
83
|
"typescript": "^5.9",
|
|
@@ -82,6 +93,7 @@
|
|
|
82
93
|
"build": "vite build",
|
|
83
94
|
"dev": "vite build --watch",
|
|
84
95
|
"test": "vitest run",
|
|
85
|
-
"typecheck": "tsc --noEmit"
|
|
96
|
+
"typecheck": "tsc --noEmit",
|
|
97
|
+
"bench": "vitest bench"
|
|
86
98
|
}
|
|
87
99
|
}
|