@better-i18n/use-intl 0.4.0 → 0.4.1
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 +146 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,7 +20,50 @@ bun add @better-i18n/use-intl use-intl
|
|
|
20
20
|
|
|
21
21
|
## Quick Start
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### Vite App (Recommended — Zero Config)
|
|
24
|
+
|
|
25
|
+
Pair with [`@better-i18n/vite`](https://www.npmjs.com/package/@better-i18n/vite) for the best experience — zero FOUC, automatic locale detection, no props needed:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @better-i18n/vite @better-i18n/use-intl use-intl
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
// vite.config.ts
|
|
33
|
+
import { betterI18n } from "@better-i18n/vite";
|
|
34
|
+
|
|
35
|
+
export default defineConfig({
|
|
36
|
+
plugins: [
|
|
37
|
+
betterI18n({ project: "acme/dashboard", localeCookie: "locale" }),
|
|
38
|
+
react(),
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
// App.tsx — no project/locale/messages props needed
|
|
45
|
+
import { BetterI18nProvider, useTranslations, LocaleDropdown } from "@better-i18n/use-intl";
|
|
46
|
+
|
|
47
|
+
function App() {
|
|
48
|
+
return (
|
|
49
|
+
<BetterI18nProvider>
|
|
50
|
+
<LocaleDropdown />
|
|
51
|
+
<HomePage />
|
|
52
|
+
</BetterI18nProvider>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function HomePage() {
|
|
57
|
+
const t = useTranslations("home");
|
|
58
|
+
return <h1>{t("title")}</h1>;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The Vite plugin injects project, locale, messages, languages, and cookie config into the HTML — the provider reads it all automatically.
|
|
63
|
+
|
|
64
|
+
### Client-Side (Manual Config)
|
|
65
|
+
|
|
66
|
+
Without the Vite plugin, pass `project` and `locale` as props:
|
|
24
67
|
|
|
25
68
|
```tsx
|
|
26
69
|
import { BetterI18nProvider, useTranslations } from '@better-i18n/use-intl'
|
|
@@ -215,13 +258,109 @@ function LanguageSwitcher() {
|
|
|
215
258
|
}
|
|
216
259
|
```
|
|
217
260
|
|
|
218
|
-
##
|
|
261
|
+
## Router Integration
|
|
262
|
+
|
|
263
|
+
### TanStack Router
|
|
264
|
+
|
|
265
|
+
Detected automatically. `useLocaleRouter()` uses TanStack Router's `router.navigate()` for SPA navigation — no extra setup needed.
|
|
266
|
+
|
|
267
|
+
See our [TanStack Start guide](https://docs.better-i18n.com/frameworks/tanstack-start) for a complete example with locale middleware, URL-based locale detection, SEO-friendly routing, and hydration without mismatches.
|
|
268
|
+
|
|
269
|
+
### React Router (`react-router-dom`)
|
|
270
|
+
|
|
271
|
+
The provider's built-in URL update uses `history.replaceState`, which doesn't notify React Router. Add a `LocaleSync` component to bridge locale state with the router:
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
import { useEffect } from "react";
|
|
275
|
+
import { BrowserRouter, Routes, Route, useNavigate, useLocation } from "react-router-dom";
|
|
276
|
+
import { BetterI18nProvider, useLocale } from "@better-i18n/use-intl";
|
|
277
|
+
|
|
278
|
+
// Syncs locale state → URL using react-router-dom's navigate
|
|
279
|
+
function LocaleSync() {
|
|
280
|
+
const { locale } = useLocale();
|
|
281
|
+
const navigate = useNavigate();
|
|
282
|
+
const location = useLocation();
|
|
283
|
+
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
const segments = location.pathname.split("/").filter(Boolean);
|
|
286
|
+
const first = segments[0];
|
|
287
|
+
if (first && /^[a-z]{2}$/i.test(first) && first !== locale) {
|
|
288
|
+
segments[0] = locale;
|
|
289
|
+
navigate("/" + segments.join("/"), { replace: true });
|
|
290
|
+
}
|
|
291
|
+
}, [locale, location.pathname, navigate]);
|
|
292
|
+
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export default function App() {
|
|
297
|
+
return (
|
|
298
|
+
<BrowserRouter>
|
|
299
|
+
<BetterI18nProvider>
|
|
300
|
+
<LocaleSync />
|
|
301
|
+
<Routes>
|
|
302
|
+
<Route path="/:locale" element={<HomePage />} />
|
|
303
|
+
</Routes>
|
|
304
|
+
</BetterI18nProvider>
|
|
305
|
+
</BrowserRouter>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### No Router (Plain SPA)
|
|
311
|
+
|
|
312
|
+
Works out of the box. On locale switch, the provider calls `history.replaceState` to update the URL prefix automatically.
|
|
313
|
+
|
|
314
|
+
## Locale Prefix Strategy
|
|
315
|
+
|
|
316
|
+
Control how locale codes appear in URLs via the `localePrefix` prop:
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
<BetterI18nProvider localePrefix="always">
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
| Strategy | Default Locale | Other Locales | Best For |
|
|
323
|
+
|----------|---------------|---------------|----------|
|
|
324
|
+
| `"as-needed"` (default) | `/about` (no prefix) | `/tr/about` | SEO — default locale has clean URLs |
|
|
325
|
+
| `"always"` | `/en/about` | `/tr/about` | Apps with `/:locale` route pattern |
|
|
326
|
+
|
|
327
|
+
**`"as-needed"`** — Default locale has no URL prefix. Non-default locales get a prefix. Best for SEO because your primary language has clean URLs.
|
|
328
|
+
|
|
329
|
+
**`"always"`** — Every locale gets a prefix, including the default. Use this when your router has a `/:locale` parameter in every route (e.g., TanStack Router's `$locale/` layout routes or React Router's `/:locale/*` pattern).
|
|
330
|
+
|
|
331
|
+
## Components
|
|
332
|
+
|
|
333
|
+
### `<LocaleDropdown />`
|
|
334
|
+
|
|
335
|
+
Pre-built, styled locale switcher with flags, keyboard navigation, and dark mode support.
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
import { LocaleDropdown } from "@better-i18n/use-intl";
|
|
339
|
+
|
|
340
|
+
// Zero config — styled mode
|
|
341
|
+
<LocaleDropdown />
|
|
342
|
+
|
|
343
|
+
// Unstyled mode for full custom styling via data attributes
|
|
344
|
+
<LocaleDropdown variant="unstyled" className="my-dropdown" />
|
|
345
|
+
|
|
346
|
+
// Custom placement
|
|
347
|
+
<LocaleDropdown placement="top" />
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Customizable via CSS custom properties:
|
|
351
|
+
|
|
352
|
+
| Property | Controls |
|
|
353
|
+
|----------|----------|
|
|
354
|
+
| `--better-locale-text` | Text color |
|
|
355
|
+
| `--better-locale-menu-bg` | Menu background |
|
|
356
|
+
| `--better-locale-border` | Border color |
|
|
357
|
+
| `--better-locale-hover-bg` | Hover state |
|
|
358
|
+
| `--better-locale-trigger-bg` | Trigger background |
|
|
359
|
+
| `--better-locale-accent` | Checkmark/accent color |
|
|
360
|
+
|
|
361
|
+
## Documentation
|
|
219
362
|
|
|
220
|
-
|
|
221
|
-
- Locale middleware
|
|
222
|
-
- URL-based locale detection
|
|
223
|
-
- SEO-friendly routing
|
|
224
|
-
- Hydration without mismatches
|
|
363
|
+
Full documentation at [docs.better-i18n.com/frameworks/vite](https://docs.better-i18n.com/frameworks/vite)
|
|
225
364
|
|
|
226
365
|
## License
|
|
227
366
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-i18n/use-intl",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Better i18n integration for use-intl (React, TanStack Start)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"prepublishOnly": "bun run build"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@better-i18n/core": "^0.
|
|
65
|
+
"@better-i18n/core": "^0.4.0",
|
|
66
66
|
"@floating-ui/react": "^0.27.19"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|