@fluenti/react 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 +244 -0
- package/dist/__tests__/DateTime.test.d.ts +2 -0
- package/dist/__tests__/DateTime.test.d.ts.map +1 -0
- package/dist/__tests__/Number.test.d.ts +2 -0
- package/dist/__tests__/Number.test.d.ts.map +1 -0
- package/dist/__tests__/Plural.test.d.ts +2 -0
- package/dist/__tests__/Plural.test.d.ts.map +1 -0
- package/dist/__tests__/Select.test.d.ts +2 -0
- package/dist/__tests__/Select.test.d.ts.map +1 -0
- package/dist/__tests__/Trans.test.d.ts +2 -0
- package/dist/__tests__/Trans.test.d.ts.map +1 -0
- package/dist/__tests__/locale-switch.test.d.ts +2 -0
- package/dist/__tests__/locale-switch.test.d.ts.map +1 -0
- package/dist/__tests__/plural-core.test.d.ts +2 -0
- package/dist/__tests__/plural-core.test.d.ts.map +1 -0
- package/dist/__tests__/provider.test.d.ts +2 -0
- package/dist/__tests__/provider.test.d.ts.map +1 -0
- package/dist/__tests__/server.test.d.ts +2 -0
- package/dist/__tests__/server.test.d.ts.map +1 -0
- package/dist/__tests__/trans-core.test.d.ts +2 -0
- package/dist/__tests__/trans-core.test.d.ts.map +1 -0
- package/dist/compile-time-t.d.ts +3 -0
- package/dist/compile-time-t.d.ts.map +1 -0
- package/dist/components/DateTime.d.ts +16 -0
- package/dist/components/DateTime.d.ts.map +1 -0
- package/dist/components/Number.d.ts +16 -0
- package/dist/components/Number.d.ts.map +1 -0
- package/dist/components/Plural.d.ts +35 -0
- package/dist/components/Plural.d.ts.map +1 -0
- package/dist/components/Select.d.ts +32 -0
- package/dist/components/Select.d.ts.map +1 -0
- package/dist/components/Trans.d.ts +29 -0
- package/dist/components/Trans.d.ts.map +1 -0
- package/dist/components/icu-rich.d.ts +22 -0
- package/dist/components/icu-rich.d.ts.map +1 -0
- package/dist/components/plural-core.d.ts +15 -0
- package/dist/components/plural-core.d.ts.map +1 -0
- package/dist/components/trans-core.d.ts +28 -0
- package/dist/components/trans-core.d.ts.map +1 -0
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/global-registry.d.ts +18 -0
- package/dist/global-registry.d.ts.map +1 -0
- package/dist/hooks/__useI18n.d.ts +12 -0
- package/dist/hooks/__useI18n.d.ts.map +1 -0
- package/dist/hooks/useI18n.d.ts +11 -0
- package/dist/hooks/useI18n.d.ts.map +1 -0
- package/dist/icu-rich-DBeWY1k6.js +108 -0
- package/dist/icu-rich-DBeWY1k6.js.map +1 -0
- package/dist/icu-rich-XY1SdM5K.cjs +2 -0
- package/dist/icu-rich-XY1SdM5K.cjs.map +1 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +200 -0
- package/dist/index.js.map +1 -0
- package/dist/msg.d.ts +2 -0
- package/dist/msg.d.ts.map +1 -0
- package/dist/provider.d.ts +3 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +240 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +122 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +82 -0
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,244 @@
|
|
|
1
|
+
# @fluenti/react
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@fluenti/react)
|
|
4
|
+
[](https://bundlephobia.com/package/@fluenti/react)
|
|
5
|
+
[](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
**Compile-time i18n for React.** Zero runtime parsing. RSC-ready. React 19 compatible.
|
|
8
|
+
|
|
9
|
+
Fluenti compiles your translations at build time so your production bundle ships pre-resolved messages instead of an ICU parser. The result: smaller bundles, faster renders, and a DX that feels native to React.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Zero runtime parsing** -- ICU MessageFormat compiled away at build time
|
|
16
|
+
- **React Server Components** -- first-class RSC support via `@fluenti/react/server`
|
|
17
|
+
- **Streaming SSR & Suspense** -- works with `React.Suspense` and streamed responses out of the box
|
|
18
|
+
- **React 19 compatible** -- tested against React 19, works with 18+
|
|
19
|
+
- **Tagged template literals** -- write `t`\`Hello, {name}!\`` directly in JSX
|
|
20
|
+
- **Rich text components** -- `<Trans>`, `<Plural>`, `<Select>`, `<DateTime>`, `<NumberFormat>`
|
|
21
|
+
- **Lazy loading** -- load locale catalogs on demand with dynamic imports
|
|
22
|
+
- **Type-safe** -- full TypeScript support with strict types
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### 1. Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add @fluenti/core @fluenti/react
|
|
32
|
+
pnpm add -D @fluenti/cli @fluenti/vite-plugin
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Configure Vite
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// vite.config.ts
|
|
39
|
+
import react from '@vitejs/plugin-react'
|
|
40
|
+
import fluenti from '@fluenti/vite-plugin'
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
plugins: [
|
|
44
|
+
fluenti({ framework: 'react' }),
|
|
45
|
+
react(),
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Wrap your app with `I18nProvider`
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { I18nProvider } from '@fluenti/react'
|
|
54
|
+
import en from './locales/compiled/en'
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return (
|
|
58
|
+
<I18nProvider
|
|
59
|
+
locale="en"
|
|
60
|
+
fallbackLocale="en"
|
|
61
|
+
messages={{ en }}
|
|
62
|
+
loadMessages={(locale) => import(`./locales/compiled/${locale}.js`)}
|
|
63
|
+
>
|
|
64
|
+
<MyApp />
|
|
65
|
+
</I18nProvider>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 4. Translate
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { t, useI18n, Trans, Plural, Select } from '@fluenti/react'
|
|
74
|
+
|
|
75
|
+
function Dashboard() {
|
|
76
|
+
const { d, n, locale, setLocale } = useI18n()
|
|
77
|
+
const name = 'Alice'
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div>
|
|
81
|
+
{/* Compile-time tagged template */}
|
|
82
|
+
<h1>{t`Welcome back, ${name}!`}</h1>
|
|
83
|
+
|
|
84
|
+
{/* Rich text with embedded components */}
|
|
85
|
+
<Trans>Read the <a href="/docs">documentation</a></Trans>
|
|
86
|
+
|
|
87
|
+
{/* Locale-aware pluralization */}
|
|
88
|
+
<Plural value={count} one="# item in cart" other="# items in cart" />
|
|
89
|
+
|
|
90
|
+
{/* Gender / categorical selection */}
|
|
91
|
+
<Select value={role} admin="Full access" editor="Edit access" other="Read only" />
|
|
92
|
+
|
|
93
|
+
{/* Date & number formatting */}
|
|
94
|
+
<p>{d(new Date(), 'long')}</p>
|
|
95
|
+
<p>{n(9999.99, 'currency')}</p>
|
|
96
|
+
|
|
97
|
+
{/* Switch locale at runtime */}
|
|
98
|
+
<button onClick={() => setLocale('ja')}>日本語</button>
|
|
99
|
+
</div>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Compile-Time Transform
|
|
107
|
+
|
|
108
|
+
Fluenti transforms your source code at build time. What you write:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<Trans>Read the <a href="/docs">documentation</a></Trans>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
What ships to production:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// Pre-resolved message, no parser needed at runtime
|
|
118
|
+
<>Read the <a href="/docs">ドキュメント</a></>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The ICU parser is a dev dependency only -- it never reaches your users.
|
|
122
|
+
|
|
123
|
+
## Direct-Import `t`
|
|
124
|
+
|
|
125
|
+
`import { t } from '@fluenti/react'` is Fluenti's primary compile-time API.
|
|
126
|
+
|
|
127
|
+
It supports:
|
|
128
|
+
|
|
129
|
+
- `` t`Hello ${name}` ``
|
|
130
|
+
- `t({ message: 'Hello {name}', context: 'hero' }, { name })`
|
|
131
|
+
|
|
132
|
+
It does not support ID lookup. For `t('message.id')`, locale switching, formatting helpers, or other imperative runtime APIs, use `useI18n()`.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## React Server Components (RSC)
|
|
137
|
+
|
|
138
|
+
For Next.js App Router and other RSC-capable frameworks, use `@fluenti/react/server`:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
// lib/i18n.server.ts
|
|
142
|
+
import { createServerI18n } from '@fluenti/react/server'
|
|
143
|
+
|
|
144
|
+
export const { setLocale, getI18n, Trans, Plural, DateTime, NumberFormat } =
|
|
145
|
+
createServerI18n({
|
|
146
|
+
loadMessages: (locale) => import(`../locales/compiled/${locale}.js`),
|
|
147
|
+
fallbackLocale: 'en',
|
|
148
|
+
resolveLocale: async () => {
|
|
149
|
+
const { cookies } = await import('next/headers')
|
|
150
|
+
return (await cookies()).get('locale')?.value ?? 'en'
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
// app/layout.tsx -- set locale once per request
|
|
157
|
+
import { setLocale } from '@/lib/i18n.server'
|
|
158
|
+
|
|
159
|
+
export default async function Layout({ params, children }) {
|
|
160
|
+
const { locale } = await params
|
|
161
|
+
setLocale(locale)
|
|
162
|
+
return <html lang={locale}><body>{children}</body></html>
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
// app/page.tsx -- use components directly, no prop drilling
|
|
168
|
+
import { Trans, Plural, DateTime, NumberFormat } from '@/lib/i18n.server'
|
|
169
|
+
|
|
170
|
+
export default async function Page() {
|
|
171
|
+
return (
|
|
172
|
+
<div>
|
|
173
|
+
<Trans>Read the <a href="/docs">documentation</a>.</Trans>
|
|
174
|
+
<Plural value={5} one="# item" other="# items" />
|
|
175
|
+
<DateTime value={new Date()} style="long" />
|
|
176
|
+
<NumberFormat value={1234.56} />
|
|
177
|
+
</div>
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Server components are async and use `React.cache()` for request-scoped state -- no Context needed. The API mirrors client components exactly.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## API Reference
|
|
187
|
+
|
|
188
|
+
### Components
|
|
189
|
+
|
|
190
|
+
| Component | Description |
|
|
191
|
+
|-----------|-------------|
|
|
192
|
+
| `I18nProvider` | Provides i18n context to the component tree |
|
|
193
|
+
| `Trans` | Rich text with embedded component interpolation |
|
|
194
|
+
| `Plural` | Locale-aware pluralization via `Intl.PluralRules` |
|
|
195
|
+
| `Select` | Categorical value selection (gender, role, status) |
|
|
196
|
+
| `DateTime` | Date formatting via `Intl.DateTimeFormat` |
|
|
197
|
+
| `NumberFormat` | Number formatting via `Intl.NumberFormat` |
|
|
198
|
+
|
|
199
|
+
### Hooks
|
|
200
|
+
|
|
201
|
+
| Hook | Returns |
|
|
202
|
+
|------|---------|
|
|
203
|
+
| `useI18n()` | `{ t, d, n, format, loadMessages, getLocales, i18n, locale, setLocale, ... }` |
|
|
204
|
+
|
|
205
|
+
`useI18n().t` remains the full runtime API for ID lookup, descriptor lookup, and imperative usage. Convenience methods `d()`, `n()`, `format()`, `loadMessages()`, `getLocales()` are also available directly. The `i18n` object is retained as an escape hatch.
|
|
206
|
+
|
|
207
|
+
### Server API (`@fluenti/react/server`)
|
|
208
|
+
|
|
209
|
+
| Export | Description |
|
|
210
|
+
|--------|-------------|
|
|
211
|
+
| `createServerI18n(config)` | Create request-scoped i18n for RSC |
|
|
212
|
+
| `setLocale(locale)` | Set locale for the current request |
|
|
213
|
+
| `getI18n()` | Get the i18n instance (async) |
|
|
214
|
+
| `Trans`, `Plural`, `DateTime`, `NumberFormat` | Async server components |
|
|
215
|
+
|
|
216
|
+
### Utilities
|
|
217
|
+
|
|
218
|
+
| Export | Entry point | Description |
|
|
219
|
+
|--------|-------------|-------------|
|
|
220
|
+
| `msg` | `@fluenti/react` | Tag for lazy message definitions outside the component tree |
|
|
221
|
+
| `detectLocale(options)` | `@fluenti/react/server` | SSR locale detection (cookie, query, path, headers) |
|
|
222
|
+
| `getSSRLocaleScript()` | `@fluenti/react/server` | Inline `<script>` for hydration without flash |
|
|
223
|
+
| `isRTL(locale)` | `@fluenti/react/server` | Check if a locale is right-to-left |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Framework Compatibility
|
|
228
|
+
|
|
229
|
+
Works with any React-based framework:
|
|
230
|
+
|
|
231
|
+
- **React SPA** (Vite)
|
|
232
|
+
- **Next.js** (App Router + Pages Router)
|
|
233
|
+
- **React Router** / Remix
|
|
234
|
+
- **TanStack Start**
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Documentation
|
|
239
|
+
|
|
240
|
+
Full docs, guides, and examples at [fluenti.dev](https://fluenti.dev).
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
[MIT](https://github.com/usefluenti/fluenti/blob/main/LICENSE)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTime.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/DateTime.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Number.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Number.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plural.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Plural.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Select.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Trans.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Trans.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale-switch.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/locale-switch.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plural-core.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plural-core.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/provider.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/server.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trans-core.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/trans-core.test.ts"],"names":[],"mappings":""}
|
|
@@ -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,16 @@
|
|
|
1
|
+
export interface DateTimeProps {
|
|
2
|
+
/** Date value to format */
|
|
3
|
+
value: Date | number;
|
|
4
|
+
/** Named format style */
|
|
5
|
+
style?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* `<DateTime>` — formatting component using Intl APIs.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <DateTime value={new Date()} style="long" />
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function DateTime({ value, style }: DateTimeProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=DateTime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTime.d.ts","sourceRoot":"","sources":["../../src/components/DateTime.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;IACpB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,aAAa,2CAMvD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface NumberProps {
|
|
2
|
+
/** Number value to format */
|
|
3
|
+
value: number;
|
|
4
|
+
/** Named format style */
|
|
5
|
+
style?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* `<Number>` — number formatting component using Intl APIs.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <Number value={1234.56} style="currency" />
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function NumberFormat({ value, style }: NumberProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=Number.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Number.d.ts","sourceRoot":"","sources":["../../src/components/Number.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,2CAMzD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface PluralProps {
|
|
3
|
+
/** The count value */
|
|
4
|
+
value: number;
|
|
5
|
+
/** Override the auto-generated synthetic ICU message id */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Message context used for identity and translator disambiguation */
|
|
8
|
+
context?: string;
|
|
9
|
+
/** Translator-facing note preserved in extraction catalogs */
|
|
10
|
+
comment?: string;
|
|
11
|
+
/** Text for zero (if language supports) */
|
|
12
|
+
zero?: ReactNode;
|
|
13
|
+
/** Singular form. `#` replaced with value */
|
|
14
|
+
one?: ReactNode;
|
|
15
|
+
/** Dual form (Arabic, etc.) */
|
|
16
|
+
two?: ReactNode;
|
|
17
|
+
/** Few form (Slavic languages, etc.) */
|
|
18
|
+
few?: ReactNode;
|
|
19
|
+
/** Many form */
|
|
20
|
+
many?: ReactNode;
|
|
21
|
+
/** Default plural form */
|
|
22
|
+
other: ReactNode;
|
|
23
|
+
/** Offset from value before selecting form */
|
|
24
|
+
offset?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* `<Plural>` — ICU plural handling as a component.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <Plural value={count} zero="No messages" one="# message" other="# messages" />
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare const Plural: import('react').NamedExoticComponent<PluralProps>;
|
|
35
|
+
//# sourceMappingURL=Plural.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plural.d.ts","sourceRoot":"","sources":["../../src/components/Plural.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMxD,MAAM,WAAW,WAAW;IAC1B,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,+BAA+B;IAC/B,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,wCAAwC;IACxC,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,gBAAgB;IAChB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,0BAA0B;IAC1B,KAAK,EAAE,SAAS,CAAA;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,mDA+CjB,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface SelectProps {
|
|
3
|
+
/** The selector value */
|
|
4
|
+
value: string;
|
|
5
|
+
/** Override the auto-generated synthetic ICU message id */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Message context used for identity and translator disambiguation */
|
|
8
|
+
context?: string;
|
|
9
|
+
/** Translator-facing note preserved in extraction catalogs */
|
|
10
|
+
comment?: string;
|
|
11
|
+
/** Default case */
|
|
12
|
+
other: ReactNode;
|
|
13
|
+
/** Type-safe named options. Takes precedence over direct case props. */
|
|
14
|
+
options?: Record<string, ReactNode>;
|
|
15
|
+
/** Named cases — any string key maps to a ReactNode */
|
|
16
|
+
[key: string]: ReactNode | Record<string, ReactNode> | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `<Select>` — ICU select for gender, role, or other categorical values.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* <Select
|
|
24
|
+
* value={gender}
|
|
25
|
+
* male="He liked your post"
|
|
26
|
+
* female="She liked your post"
|
|
27
|
+
* other="They liked your post"
|
|
28
|
+
* />
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function Select(props: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
//# sourceMappingURL=Select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/components/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKlD,MAAM,WAAW,WAAW;IAC1B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mBAAmB;IACnB,KAAK,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACnC,uDAAuD;IACvD,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,CAAA;CACjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2CAyCxC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
export interface TransProps {
|
|
3
|
+
/** Source text with embedded components */
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
/** Override auto-generated hash ID */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Message context used for identity and translator disambiguation */
|
|
8
|
+
context?: string;
|
|
9
|
+
/** Context comment for translators */
|
|
10
|
+
comment?: string;
|
|
11
|
+
/** Custom render wrapper */
|
|
12
|
+
render?: (translation: ReactNode) => ReactNode;
|
|
13
|
+
/** @internal Pre-computed message ID from build plugin */
|
|
14
|
+
__id?: string;
|
|
15
|
+
/** @internal Pre-computed ICU message from build plugin */
|
|
16
|
+
__message?: string;
|
|
17
|
+
/** @internal Pre-computed component list from build plugin */
|
|
18
|
+
__components?: ReactElement[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `<Trans>` component for rich-text translations containing nested React elements.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* <Trans>Read the <a href="/docs">documentation</a> for more info.</Trans>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const Trans: import('react').NamedExoticComponent<TransProps>;
|
|
29
|
+
//# sourceMappingURL=Trans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Trans.d.ts","sourceRoot":"","sources":["../../src/components/Trans.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAId,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,EAAE,SAAS,CAAA;IACnB,sCAAsC;IACtC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,KAAK,SAAS,CAAA;IAC9C,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,YAAY,EAAE,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,kDAwChB,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MessageDescriptor } from '@fluenti/core';
|
|
2
|
+
import { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { PluralCategory } from './plural-core';
|
|
4
|
+
export interface RichMessagePart {
|
|
5
|
+
message: string;
|
|
6
|
+
components: ReactElement[];
|
|
7
|
+
}
|
|
8
|
+
export declare function buildICUPluralMessage(forms: Partial<Record<PluralCategory, string>> & {
|
|
9
|
+
other: string;
|
|
10
|
+
}, offset?: number): string;
|
|
11
|
+
export declare function buildICUSelectMessage(forms: Record<string, string>): string;
|
|
12
|
+
export declare function normalizeSelectForms(forms: Record<string, string>): {
|
|
13
|
+
forms: Record<string, string>;
|
|
14
|
+
valueMap: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
export declare function serializeRichNode(node: ReactNode): RichMessagePart;
|
|
17
|
+
export declare function serializeRichForms<T extends string>(keys: readonly T[], forms: Partial<Record<T, ReactNode>> & Record<string, ReactNode | undefined>): {
|
|
18
|
+
messages: Partial<Record<T, string>> & Record<string, string>;
|
|
19
|
+
components: ReactElement[];
|
|
20
|
+
};
|
|
21
|
+
export declare function renderRichTranslation(descriptor: MessageDescriptor, values: Record<string, unknown> | undefined, translate: (descriptor: MessageDescriptor, values?: Record<string, unknown>) => string, components: ReactElement[]): ReactNode;
|
|
22
|
+
//# sourceMappingURL=icu-rich.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icu-rich.d.ts","sourceRoot":"","sources":["../../src/components/icu-rich.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAEtE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,YAAY,EAAE,CAAA;CAC3B;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAClE,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CASR;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,MAAM,CAGR;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B;IACD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,CAqBA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CAMlE;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,GAC3E;IACD,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7D,UAAU,EAAE,YAAY,EAAE,CAAA;CAC3B,CAoBA;AAED,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,SAAS,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,EACtF,UAAU,EAAE,YAAY,EAAE,GACzB,SAAS,CAGX"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export declare const PLURAL_CATEGORIES: readonly ["zero", "one", "two", "few", "many", "other"];
|
|
3
|
+
export type PluralCategory = (typeof PLURAL_CATEGORIES)[number];
|
|
4
|
+
/**
|
|
5
|
+
* Resolve which plural category to use.
|
|
6
|
+
* Checks for exact =0 match first, then falls back to CLDR rules.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveCategory(value: number, locale: string, available: Record<string, boolean>): PluralCategory;
|
|
10
|
+
/**
|
|
11
|
+
* Replace `#` with the formatted value in a ReactNode.
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare function replaceHash(node: ReactNode, formatted: string): ReactNode;
|
|
15
|
+
//# sourceMappingURL=plural-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plural-core.d.ts","sourceRoot":"","sources":["../../src/components/plural-core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,eAAO,MAAM,iBAAiB,yDAA0D,CAAA;AACxF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,cAAc,CAKhB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAKzE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactNode, ReactElement } from 'react';
|
|
2
|
+
import { hashMessage } from '@fluenti/core';
|
|
3
|
+
export { hashMessage };
|
|
4
|
+
/**
|
|
5
|
+
* Extract a message string and component list from React children.
|
|
6
|
+
*
|
|
7
|
+
* Converts:
|
|
8
|
+
* <Trans>Hello <b>{name}</b>, welcome!</Trans>
|
|
9
|
+
* Into:
|
|
10
|
+
* message: "Hello <0>{name}</0>, welcome!"
|
|
11
|
+
* components: [<b>{name}</b>]
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractMessage(children: ReactNode): {
|
|
16
|
+
message: string;
|
|
17
|
+
components: ReactElement[];
|
|
18
|
+
};
|
|
19
|
+
export declare function offsetIndices(message: string, offset: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* Reconstruct a translated message string back into React elements.
|
|
22
|
+
*
|
|
23
|
+
* Parses "<0>content</0>" tags and replaces them with cloned components.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function reconstruct(translated: string, components: ReactElement[]): ReactNode;
|
|
28
|
+
//# sourceMappingURL=trans-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trans-core.d.ts","sourceRoot":"","sources":["../../src/components/trans-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,EAAE,WAAW,EAAE,CAAA;AAEtB;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,GAAG;IACnD,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,YAAY,EAAE,CAAA;CAC3B,CAwBA;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKrE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,YAAY,EAAE,GACzB,SAAS,CAqCX"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,eAAO,MAAM,WAAW,kDAA+C,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FluentInstanceExtended } from '@fluenti/core';
|
|
2
|
+
/**
|
|
3
|
+
* Global i18n instance registry.
|
|
4
|
+
*
|
|
5
|
+
* Used by `@fluenti/next` webpack loader and `@fluenti/vite-plugin` to access
|
|
6
|
+
* the i18n instance from module-level code via a Proxy. The instance is set by
|
|
7
|
+
* `<I18nProvider>` on mount.
|
|
8
|
+
*/
|
|
9
|
+
declare global {
|
|
10
|
+
var __fluenti_i18n: FluentInstanceExtended | undefined;
|
|
11
|
+
}
|
|
12
|
+
/** Get the global i18n instance (set by `<I18nProvider>`). */
|
|
13
|
+
export declare function getGlobalI18n(): FluentInstanceExtended | undefined;
|
|
14
|
+
/** Set the global i18n instance. Called by `<I18nProvider>` on mount. */
|
|
15
|
+
export declare function setGlobalI18n(instance: FluentInstanceExtended): void;
|
|
16
|
+
/** Clear the global i18n instance. Primarily for testing. */
|
|
17
|
+
export declare function clearGlobalI18n(): void;
|
|
18
|
+
//# sourceMappingURL=global-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-registry.d.ts","sourceRoot":"","sources":["../src/global-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE3D;;;;;;GAMG;AAEH,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,cAAc,EAAE,sBAAsB,GAAG,SAAS,CAAA;CACvD;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,IAAI,sBAAsB,GAAG,SAAS,CAElE;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI,CAEpE;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FluentInstanceExtended } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Internal hook used by the Vite plugin's compiled output.
|
|
4
|
+
* Returns the i18n instance for direct t() calls.
|
|
5
|
+
*
|
|
6
|
+
* **Not part of the public API.** Users never write this — the Vite plugin
|
|
7
|
+
* generates imports of this hook automatically.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function __useI18n(): FluentInstanceExtended;
|
|
12
|
+
//# sourceMappingURL=__useI18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"__useI18n.d.ts","sourceRoot":"","sources":["../../src/hooks/__useI18n.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAEtD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,sBAAsB,CASlD"}
|