@comvi/next 0.1.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 +58 -2
- package/dist/client/I18nProvider.d.ts.map +1 -1
- package/dist/client/I18nProvider.js +25 -9
- package/dist/client.d.ts +2 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -2
- package/dist/routing/Link.js +2 -2
- package/dist/routing/hooks.js +3 -3
- package/package.json +13 -17
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/client/I18nProvider.cjs +0 -101
- package/dist/client/index.d.ts +0 -5
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client.cjs +0 -31
- package/dist/createNextI18n.cjs +0 -153
- package/dist/index.cjs +0 -17
- package/dist/middleware/createMiddleware.cjs +0 -185
- package/dist/middleware.cjs +0 -3
- package/dist/navigation.cjs +0 -8
- package/dist/routing/Link.cjs +0 -42
- package/dist/routing/context.cjs +0 -21
- package/dist/routing/defineRouting.cjs +0 -141
- package/dist/routing/hooks.cjs +0 -104
- package/dist/routing/utils.cjs +0 -94
- package/dist/routing.cjs +0 -5
- package/dist/server/cache.cjs +0 -69
- package/dist/server/ensureInitialized.cjs +0 -19
- package/dist/server/getI18n.cjs +0 -115
- package/dist/server/getLocale.cjs +0 -37
- package/dist/server/loadTranslations.cjs +0 -54
- package/dist/server/setRequestLocale.cjs +0 -31
- package/dist/server.cjs +0 -11
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
13
13
|
<a href="https://www.npmjs.com/package/@comvi/next"><img src="https://img.shields.io/npm/v/@comvi/next?color=blue" alt="npm"></a>
|
|
14
|
-
<a href="https://
|
|
14
|
+
<a href="https://bundlephobia.com/package/@comvi/next"><img src="https://img.shields.io/bundlephobia/minzip/@comvi/next?label=minzip" alt="Bundle size"></a>
|
|
15
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
16
|
</p>
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ Comvi i18n is a modern, framework-agnostic internationalization library built on
|
|
|
30
30
|
- **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.
|
|
31
31
|
- **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.
|
|
32
32
|
- **Locale-aware formatters built in.** `formatNumber`, `formatDate`, `formatCurrency`, and `formatRelativeTime` follow the active locale via native `Intl`, with reactive updates in every framework binding.
|
|
33
|
-
- **~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.
|
|
33
|
+
- **~8 kB minified + gzipped (as bundled by your app), 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.
|
|
34
34
|
- **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.
|
|
35
35
|
- **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.
|
|
36
36
|
- **First-class SSR.** `@comvi/next` and `@comvi/nuxt` ship server-side translation loading, locale-routed layouts, and middleware for redirect-on-detect — no flash of untranslated content.
|
|
@@ -48,6 +48,8 @@ npm install @comvi/next
|
|
|
48
48
|
# Peers: next ^14 || ^15, react ^18 || ^19
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
Upgrading from v0.2.x? See the [CHANGELOG](./CHANGELOG.md).
|
|
52
|
+
|
|
51
53
|
## Quick start
|
|
52
54
|
|
|
53
55
|
```ts
|
|
@@ -114,6 +116,60 @@ export const config = { matcher: ["/((?!api|_next|.*\\..*).*)"] };
|
|
|
114
116
|
|
|
115
117
|
The full setup also includes a `[locale]/layout.tsx` that imports the server registration once, calls `loadTranslations(locale)`, and renders the client wrapper above. See the [documentation](https://comvi.io/docs/i18n/next/) for locale-aware `<Link>`, `useLocalizedRouter`, server/client subpath imports, and the lazy-plugin API.
|
|
116
118
|
|
|
119
|
+
## Optimizations in v0.3
|
|
120
|
+
|
|
121
|
+
**Routing components now use `useLocale()`** — `<Link>`, `usePathname()`, and `useLocalizedRouter()` internally switched to the new `useLocale()` hook in v0.3. No behavior change for consumers; routing continues to work identically. Under the hood, this means locale-aware routing skips re-renders on namespace loads and loading-state changes (measurement-confirmed P1 performance improvement).
|
|
122
|
+
|
|
123
|
+
**Render-time mutation removed** — The internal `i18n.locale` assignment and `i18n.addTranslations()` calls that used to happen in `<I18nProvider>`'s render body have been moved into a `useState` initializer. This is a quality improvement (removes side effects from render) with no API change — `<I18nProvider>` props work identically.
|
|
124
|
+
|
|
125
|
+
## Error Boundaries
|
|
126
|
+
|
|
127
|
+
Wrap the client provider in an Error Boundary to handle initialization failures:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import React from "react";
|
|
131
|
+
import { I18nProvider } from "@comvi/next/client";
|
|
132
|
+
|
|
133
|
+
class I18nErrorBoundary extends React.Component<
|
|
134
|
+
{ children: React.ReactNode },
|
|
135
|
+
{ hasError: boolean }
|
|
136
|
+
> {
|
|
137
|
+
constructor(props: { children: React.ReactNode }) {
|
|
138
|
+
super(props);
|
|
139
|
+
this.state = { hasError: false };
|
|
140
|
+
}
|
|
141
|
+
static getDerivedStateFromError() {
|
|
142
|
+
return { hasError: true };
|
|
143
|
+
}
|
|
144
|
+
render() {
|
|
145
|
+
if (this.state.hasError) {
|
|
146
|
+
return <div>Failed to load translations. Please refresh the page.</div>;
|
|
147
|
+
}
|
|
148
|
+
return this.props.children;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function ComviProvider({
|
|
153
|
+
children,
|
|
154
|
+
locale,
|
|
155
|
+
messages,
|
|
156
|
+
}: {
|
|
157
|
+
children: React.ReactNode;
|
|
158
|
+
locale: string;
|
|
159
|
+
messages: MessagesMap;
|
|
160
|
+
}) {
|
|
161
|
+
return (
|
|
162
|
+
<I18nErrorBoundary>
|
|
163
|
+
<I18nProvider i18n={i18n} locale={locale} messages={messages} routing={routing}>
|
|
164
|
+
{children}
|
|
165
|
+
</I18nProvider>
|
|
166
|
+
</I18nErrorBoundary>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Or use [react-error-boundary](https://github.com/bvaughn/react-error-boundary) for convenience.
|
|
172
|
+
|
|
117
173
|
## Server-side translation loading
|
|
118
174
|
|
|
119
175
|
`loadTranslations()` is a server-only function that loads translations for a locale using the i18n instance registered with `setI18n(i18n)`. Call it in Server Components or Server Actions, and pass the result to `<I18nProvider>` to hydrate the client without a flash of untranslated content.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"I18nProvider.d.ts","sourceRoot":"","sources":["../../src/client/I18nProvider.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,IAAI,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;IACzF,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"I18nProvider.d.ts","sourceRoot":"","sources":["../../src/client/I18nProvider.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,IAAI,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;IACzF,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAe,EACf,OAAO,EACP,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAuCnB;yBA/Ce,YAAY"}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
"use client";
|
|
2
3
|
import { RoutingProvider } from "../routing/context.js";
|
|
3
|
-
import { useEffect, useLayoutEffect, useRef } from "react";
|
|
4
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
5
|
import { I18nProvider } from "@comvi/react";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
//#region src/client/I18nProvider.tsx
|
|
7
8
|
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Update the i18n instance locale if valid against `routing.locales` (when
|
|
11
|
+
* routing is provided). Calls `i18n.reportError` on misconfiguration so devs
|
|
12
|
+
* get a meaningful diagnostic instead of silent fallback.
|
|
13
|
+
*/
|
|
14
|
+
function syncLocaleSafely(i18n, locale, routing) {
|
|
15
|
+
if (routing && !routing.locales.includes(locale)) {
|
|
16
|
+
i18n.reportError(/* @__PURE__ */ new Error(`[next-i18n-provider] Locale "${locale}" is not in routing.locales (${routing.locales.join(", ")}). Skipping locale sync.`), {
|
|
17
|
+
source: "init",
|
|
18
|
+
locale
|
|
19
|
+
});
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (i18n.locale !== locale) i18n.locale = locale;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
9
25
|
/**
|
|
10
26
|
* I18nProvider for Next.js App Router
|
|
11
27
|
*
|
|
@@ -60,17 +76,16 @@ var isServer = typeof window === "undefined";
|
|
|
60
76
|
*/
|
|
61
77
|
function I18nProvider$1({ children, i18n, locale, messages, autoInit = true, routing, ...props }) {
|
|
62
78
|
const lastAddedMessagesRef = useRef(void 0);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (i18n.locale !== locale) i18n.locale = locale;
|
|
79
|
+
useState(() => {
|
|
80
|
+
syncLocaleSafely(i18n, locale, routing);
|
|
66
81
|
if (messages && messages !== lastAddedMessagesRef.current) {
|
|
67
82
|
i18n.addTranslations(messages);
|
|
68
83
|
lastAddedMessagesRef.current = messages;
|
|
69
84
|
}
|
|
70
|
-
|
|
71
|
-
}
|
|
85
|
+
return null;
|
|
86
|
+
});
|
|
72
87
|
useIsomorphicLayoutEffect(() => {
|
|
73
|
-
|
|
88
|
+
syncLocaleSafely(i18n, locale, routing);
|
|
74
89
|
if (messages && messages !== lastAddedMessagesRef.current) {
|
|
75
90
|
i18n.addTranslations(messages);
|
|
76
91
|
lastAddedMessagesRef.current = messages;
|
|
@@ -78,7 +93,8 @@ function I18nProvider$1({ children, i18n, locale, messages, autoInit = true, rou
|
|
|
78
93
|
}, [
|
|
79
94
|
i18n,
|
|
80
95
|
locale,
|
|
81
|
-
messages
|
|
96
|
+
messages,
|
|
97
|
+
routing
|
|
82
98
|
]);
|
|
83
99
|
const content = /* @__PURE__ */ jsx(I18nProvider, {
|
|
84
100
|
i18n,
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { useI18n, useI18nContext, T, createI18n } from '@comvi/react';
|
|
2
|
-
export type { UseI18nReturn, TProps } from '@comvi/react';
|
|
1
|
+
export { useI18n, useI18nContext, useLocale, useIsLoading, useSetLocaleTransition, useFormatters, T, createI18n, } from '@comvi/react';
|
|
2
|
+
export type { UseI18nReturn, UseSetLocaleTransitionReturn, UseFormattersReturn, TProps, } from '@comvi/react';
|
|
3
3
|
export { I18nProvider } from './client/I18nProvider';
|
|
4
4
|
export type { I18nProviderProps, MessagesMap } from './client/I18nProvider';
|
|
5
5
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,cAAc,EACd,SAAS,EACT,YAAY,EACZ,sBAAsB,EACtB,aAAa,EACb,CAAC,EACD,UAAU,GACX,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,aAAa,EACb,4BAA4B,EAC5B,mBAAmB,EACnB,MAAM,GACP,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
3
|
import { I18nProvider } from "./client/I18nProvider.js";
|
|
4
|
-
import { T, createI18n, useI18n, useI18nContext } from "@comvi/react";
|
|
5
|
-
export { I18nProvider, T, createI18n, useI18n, useI18nContext };
|
|
4
|
+
import { T, createI18n, useFormatters, useI18n, useI18nContext, useIsLoading, useLocale, useSetLocaleTransition } from "@comvi/react";
|
|
5
|
+
export { I18nProvider, T, createI18n, useFormatters, useI18n, useI18nContext, useIsLoading, useLocale, useSetLocaleTransition };
|
package/dist/routing/Link.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useRoutingConfig } from "./context.js";
|
|
4
4
|
import { localizeHref, localizeUrlObject } from "./utils.js";
|
|
5
5
|
import { forwardRef } from "react";
|
|
6
|
-
import {
|
|
6
|
+
import { useLocale } from "@comvi/react";
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
8
8
|
import NextLink from "next/link";
|
|
9
9
|
//#region src/routing/Link.tsx
|
|
@@ -25,7 +25,7 @@ import NextLink from "next/link";
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
var Link = forwardRef(function Link({ href, locale: targetLocale, ...props }, ref) {
|
|
28
|
-
const
|
|
28
|
+
const currentLocale = useLocale();
|
|
29
29
|
const locale = targetLocale ?? currentLocale;
|
|
30
30
|
const routing = useRoutingConfig();
|
|
31
31
|
return /* @__PURE__ */ jsx(NextLink, {
|
package/dist/routing/hooks.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useRoutingConfig } from "./context.js";
|
|
4
4
|
import { getCanonicalPathname, localizeHref, stripLocalePrefix } from "./utils.js";
|
|
5
5
|
import { useCallback } from "react";
|
|
6
|
-
import {
|
|
6
|
+
import { useLocale } from "@comvi/react";
|
|
7
7
|
import { usePathname, useRouter } from "next/navigation";
|
|
8
8
|
//#region src/routing/hooks.ts
|
|
9
9
|
/**
|
|
@@ -28,7 +28,7 @@ import { usePathname, useRouter } from "next/navigation";
|
|
|
28
28
|
function usePathname$1() {
|
|
29
29
|
const pathname = usePathname() ?? "/";
|
|
30
30
|
const routing = useRoutingConfig();
|
|
31
|
-
const
|
|
31
|
+
const locale = useLocale();
|
|
32
32
|
if (routing) return getCanonicalPathname(stripLocalePrefix(pathname, routing.locales), routing, locale);
|
|
33
33
|
if (pathname.startsWith(`/${locale}/`)) return pathname.slice(locale.length + 1);
|
|
34
34
|
if (pathname === `/${locale}`) return "/";
|
|
@@ -63,7 +63,7 @@ function usePathname$1() {
|
|
|
63
63
|
*/
|
|
64
64
|
function useLocalizedRouter() {
|
|
65
65
|
const router = useRouter();
|
|
66
|
-
const
|
|
66
|
+
const locale = useLocale();
|
|
67
67
|
const routing = useRoutingConfig();
|
|
68
68
|
const push = useCallback((href, targetLocale) => {
|
|
69
69
|
const localizedHref = localizeHref(href, targetLocale ?? locale, routing ?? void 0);
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comvi/next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Next.js App Router integration for Comvi — SSR, middleware, and locale routing",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Comvi <hello@comvi.io> (https://comvi.io)",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/comvi-io/comvi-js.git",
|
|
10
|
+
"url": "git+https://github.com/comvi-io/comvi-js.git",
|
|
11
11
|
"directory": "packages/next"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://comvi.io",
|
|
@@ -33,45 +33,41 @@
|
|
|
33
33
|
"files": [
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
|
-
"main": "./dist/index.cjs",
|
|
37
36
|
"module": "./dist/index.js",
|
|
38
37
|
"types": "./dist/index.d.ts",
|
|
39
38
|
"exports": {
|
|
40
39
|
".": {
|
|
41
40
|
"types": "./dist/index.d.ts",
|
|
42
|
-
"
|
|
43
|
-
"require": "./dist/index.cjs"
|
|
41
|
+
"default": "./dist/index.js"
|
|
44
42
|
},
|
|
45
43
|
"./server": {
|
|
46
44
|
"types": "./dist/server.d.ts",
|
|
47
|
-
"
|
|
48
|
-
"require": "./dist/server.cjs"
|
|
45
|
+
"default": "./dist/server.js"
|
|
49
46
|
},
|
|
50
47
|
"./client": {
|
|
51
48
|
"types": "./dist/client.d.ts",
|
|
52
|
-
"
|
|
53
|
-
"require": "./dist/client.cjs"
|
|
49
|
+
"default": "./dist/client.js"
|
|
54
50
|
},
|
|
55
51
|
"./middleware": {
|
|
56
52
|
"types": "./dist/middleware.d.ts",
|
|
57
|
-
"
|
|
58
|
-
"require": "./dist/middleware.cjs"
|
|
53
|
+
"default": "./dist/middleware.js"
|
|
59
54
|
},
|
|
60
55
|
"./routing": {
|
|
61
56
|
"types": "./dist/routing.d.ts",
|
|
62
|
-
"
|
|
63
|
-
"require": "./dist/routing.cjs"
|
|
57
|
+
"default": "./dist/routing.js"
|
|
64
58
|
},
|
|
65
59
|
"./navigation": {
|
|
66
60
|
"types": "./dist/navigation.d.ts",
|
|
67
|
-
"
|
|
68
|
-
"require": "./dist/navigation.cjs"
|
|
61
|
+
"default": "./dist/navigation.js"
|
|
69
62
|
}
|
|
70
63
|
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18"
|
|
66
|
+
},
|
|
71
67
|
"sideEffects": false,
|
|
72
68
|
"dependencies": {
|
|
73
|
-
"@comvi/core": "0.
|
|
74
|
-
"@comvi/react": "0.
|
|
69
|
+
"@comvi/core": "0.3.0",
|
|
70
|
+
"@comvi/react": "0.3.0"
|
|
75
71
|
},
|
|
76
72
|
"peerDependencies": {
|
|
77
73
|
"next": "^14.0.0 || ^15.0.0",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
//#endregion
|
|
23
|
-
exports.__toESM = __toESM;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
-
const require_context = require("../routing/context.cjs");
|
|
4
|
-
let react = require("react");
|
|
5
|
-
react = require_runtime.__toESM(react);
|
|
6
|
-
let _comvi_react = require("@comvi/react");
|
|
7
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
-
//#region src/client/I18nProvider.tsx
|
|
9
|
-
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
|
|
10
|
-
var isServer = typeof window === "undefined";
|
|
11
|
-
/**
|
|
12
|
-
* I18nProvider for Next.js App Router
|
|
13
|
-
*
|
|
14
|
-
* This provider handles hydration by syncing the server locale with the client
|
|
15
|
-
* i18n instance, preventing hydration mismatches.
|
|
16
|
-
*
|
|
17
|
-
* Translations should be pre-loaded in the i18n instance via the `translation`
|
|
18
|
-
* option in `createI18n()`.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```tsx
|
|
22
|
-
* // i18n/index.ts
|
|
23
|
-
* import { createI18n } from '@comvi/next';
|
|
24
|
-
* import { setI18n } from '@comvi/next/server';
|
|
25
|
-
* import { translations } from './translations';
|
|
26
|
-
*
|
|
27
|
-
* export const i18n = createI18n({
|
|
28
|
-
* locale: 'en',
|
|
29
|
-
* defaultNs: 'default',
|
|
30
|
-
* translation: translations, // Pre-loaded translations
|
|
31
|
-
* });
|
|
32
|
-
*
|
|
33
|
-
* setI18n(i18n);
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```tsx
|
|
38
|
-
* // app/[locale]/layout.tsx
|
|
39
|
-
* import { I18nProvider } from '@comvi/next/client';
|
|
40
|
-
* import { i18n } from '@/i18n';
|
|
41
|
-
*
|
|
42
|
-
* export default async function LocaleLayout({
|
|
43
|
-
* children,
|
|
44
|
-
* params
|
|
45
|
-
* }: {
|
|
46
|
-
* children: React.ReactNode;
|
|
47
|
-
* params: Promise<{ locale: string }>;
|
|
48
|
-
* }) {
|
|
49
|
-
* const { locale } = await params;
|
|
50
|
-
*
|
|
51
|
-
* return (
|
|
52
|
-
* <html lang={locale}>
|
|
53
|
-
* <body>
|
|
54
|
-
* <I18nProvider i18n={i18n} locale={locale}>
|
|
55
|
-
* {children}
|
|
56
|
-
* </I18nProvider>
|
|
57
|
-
* </body>
|
|
58
|
-
* </html>
|
|
59
|
-
* );
|
|
60
|
-
* }
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
function I18nProvider({ children, i18n, locale, messages, autoInit = true, routing, ...props }) {
|
|
64
|
-
const lastAddedMessagesRef = (0, react.useRef)(void 0);
|
|
65
|
-
const isFirstRenderRef = (0, react.useRef)(true);
|
|
66
|
-
if (isServer || isFirstRenderRef.current) {
|
|
67
|
-
if (i18n.locale !== locale) i18n.locale = locale;
|
|
68
|
-
if (messages && messages !== lastAddedMessagesRef.current) {
|
|
69
|
-
i18n.addTranslations(messages);
|
|
70
|
-
lastAddedMessagesRef.current = messages;
|
|
71
|
-
}
|
|
72
|
-
if (!isServer) isFirstRenderRef.current = false;
|
|
73
|
-
}
|
|
74
|
-
useIsomorphicLayoutEffect(() => {
|
|
75
|
-
if (i18n.locale !== locale) i18n.locale = locale;
|
|
76
|
-
if (messages && messages !== lastAddedMessagesRef.current) {
|
|
77
|
-
i18n.addTranslations(messages);
|
|
78
|
-
lastAddedMessagesRef.current = messages;
|
|
79
|
-
}
|
|
80
|
-
}, [
|
|
81
|
-
i18n,
|
|
82
|
-
locale,
|
|
83
|
-
messages
|
|
84
|
-
]);
|
|
85
|
-
const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_comvi_react.I18nProvider, {
|
|
86
|
-
i18n,
|
|
87
|
-
autoInit,
|
|
88
|
-
ssrInitialLocale: locale,
|
|
89
|
-
ssrInitialIsLoading: false,
|
|
90
|
-
ssrInitialIsInitializing: false,
|
|
91
|
-
...props,
|
|
92
|
-
children
|
|
93
|
-
});
|
|
94
|
-
return routing ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_context.RoutingProvider, {
|
|
95
|
-
routing,
|
|
96
|
-
children: content
|
|
97
|
-
}) : content;
|
|
98
|
-
}
|
|
99
|
-
I18nProvider.displayName = "I18nProvider";
|
|
100
|
-
//#endregion
|
|
101
|
-
exports.I18nProvider = I18nProvider;
|
package/dist/client/index.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { useI18n, useI18nContext, T, createI18n } from '@comvi/react';
|
|
2
|
-
export type { UseI18nReturn, TProps } from '@comvi/react';
|
|
3
|
-
export { I18nProvider } from './I18nProvider';
|
|
4
|
-
export type { I18nProviderProps } from './I18nProvider';
|
|
5
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/client.cjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use client";
|
|
3
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
5
|
-
const require_I18nProvider = require("./client/I18nProvider.cjs");
|
|
6
|
-
let _comvi_react = require("@comvi/react");
|
|
7
|
-
exports.I18nProvider = require_I18nProvider.I18nProvider;
|
|
8
|
-
Object.defineProperty(exports, "T", {
|
|
9
|
-
enumerable: true,
|
|
10
|
-
get: function() {
|
|
11
|
-
return _comvi_react.T;
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
Object.defineProperty(exports, "createI18n", {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function() {
|
|
17
|
-
return _comvi_react.createI18n;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
Object.defineProperty(exports, "useI18n", {
|
|
21
|
-
enumerable: true,
|
|
22
|
-
get: function() {
|
|
23
|
-
return _comvi_react.useI18n;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
Object.defineProperty(exports, "useI18nContext", {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
get: function() {
|
|
29
|
-
return _comvi_react.useI18nContext;
|
|
30
|
-
}
|
|
31
|
-
});
|
package/dist/createNextI18n.cjs
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
-
const require_defineRouting = require("./routing/defineRouting.cjs");
|
|
3
|
-
let _comvi_core = require("@comvi/core");
|
|
4
|
-
//#region src/createNextI18n.ts
|
|
5
|
-
var resolveLazyPlugin = (moduleOrPlugin) => {
|
|
6
|
-
if (typeof moduleOrPlugin === "function") return moduleOrPlugin;
|
|
7
|
-
if (moduleOrPlugin && typeof moduleOrPlugin.default === "function") return moduleOrPlugin.default;
|
|
8
|
-
throw new Error("[comvi/next] Invalid lazy plugin module. Expected a plugin function or { default: pluginFunction }.");
|
|
9
|
-
};
|
|
10
|
-
var isClientRuntime = () => {
|
|
11
|
-
if (process.env.NEXT_RUNTIME) return false;
|
|
12
|
-
return typeof window !== "undefined";
|
|
13
|
-
};
|
|
14
|
-
var shouldRunForRuntime = (runtime) => {
|
|
15
|
-
const isClient = isClientRuntime();
|
|
16
|
-
return runtime === "client" ? isClient : !isClient;
|
|
17
|
-
};
|
|
18
|
-
var shouldRunForEnvironment = (environment) => {
|
|
19
|
-
if (environment === "all") return true;
|
|
20
|
-
return environment === (process.env.NODE_ENV === "production" ? "production" : "development");
|
|
21
|
-
};
|
|
22
|
-
var createScopedPlugin = (plugin, runtime, environment) => {
|
|
23
|
-
return (i18n) => {
|
|
24
|
-
if (!shouldRunForRuntime(runtime) || !shouldRunForEnvironment(environment)) return;
|
|
25
|
-
return plugin(i18n);
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
var createScopedLazyPlugin = (loadPlugin, runtime, environment) => {
|
|
29
|
-
let pluginPromise = null;
|
|
30
|
-
return (i18n) => {
|
|
31
|
-
if (!shouldRunForRuntime(runtime) || !shouldRunForEnvironment(environment)) return;
|
|
32
|
-
if (!pluginPromise) pluginPromise = loadPlugin().then(resolveLazyPlugin);
|
|
33
|
-
return pluginPromise.then((plugin) => plugin(i18n));
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
var normalizeScopedOptions = (options) => {
|
|
37
|
-
const { environment = "all", ...pluginOptions } = options ?? {};
|
|
38
|
-
return {
|
|
39
|
-
environment,
|
|
40
|
-
pluginOptions
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Create a fully configured Next.js i18n setup with a single function call.
|
|
45
|
-
*
|
|
46
|
-
* This factory creates:
|
|
47
|
-
* - i18n instance
|
|
48
|
-
* - Routing configuration for middleware and navigation
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```typescript
|
|
52
|
-
* // i18n/config.ts
|
|
53
|
-
* import { createNextI18n } from "@comvi/next";
|
|
54
|
-
*
|
|
55
|
-
* export const { i18n, routing } = createNextI18n({
|
|
56
|
-
* // Routing
|
|
57
|
-
* locales: ["en", "de", "uk"],
|
|
58
|
-
* defaultLocale: "en",
|
|
59
|
-
*
|
|
60
|
-
* // Optional
|
|
61
|
-
* basicHtmlTags: ["strong", "em", "br", "a"],
|
|
62
|
-
* });
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```typescript
|
|
67
|
-
* // Optional plugin registration (same DX as core/react)
|
|
68
|
-
* import { FetchLoader } from "@comvi/plugin-fetch-loader";
|
|
69
|
-
*
|
|
70
|
-
* const nextI18n = createNextI18n({
|
|
71
|
-
* locales: ["en", "de"],
|
|
72
|
-
* defaultLocale: "en",
|
|
73
|
-
* })
|
|
74
|
-
* .use(
|
|
75
|
-
* FetchLoader({
|
|
76
|
-
* cdnUrl: "https://cdn.comvi.io/your-distribution-id",
|
|
77
|
-
* loadOnInit: false,
|
|
78
|
-
* }),
|
|
79
|
-
* )
|
|
80
|
-
* .useServer(MyServerPlugin())
|
|
81
|
-
* .useClientLazy(
|
|
82
|
-
* () => import("@comvi/plugin-in-context-editor").then((m) => m.InContextEditorPlugin()),
|
|
83
|
-
* { environment: "development", required: false },
|
|
84
|
-
* )
|
|
85
|
-
* .use(MyPlugin())
|
|
86
|
-
* .use(AnotherPlugin(), { required: false });
|
|
87
|
-
*
|
|
88
|
-
* export const { i18n, routing } = nextI18n;
|
|
89
|
-
* ```
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* // i18n/server.ts - Server entry point
|
|
94
|
-
* import "server-only";
|
|
95
|
-
* import { setI18n } from "@comvi/next/server";
|
|
96
|
-
* import { i18n } from "./config";
|
|
97
|
-
*
|
|
98
|
-
* setI18n(i18n);
|
|
99
|
-
*
|
|
100
|
-
* export { i18n, routing } from "./config";
|
|
101
|
-
* export { getI18n, loadTranslations } from "@comvi/next/server";
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
function createNextI18n(options) {
|
|
105
|
-
const { locales, defaultLocale, localePrefix = "as-needed", pathnames, apiKey, ns, translation, fallbackLocale = defaultLocale, defaultNs = "default", devMode: devModeOption, basicHtmlTags, onMissingKey } = options;
|
|
106
|
-
const i18n = (0, _comvi_core.createI18n)({
|
|
107
|
-
locale: defaultLocale,
|
|
108
|
-
fallbackLocale,
|
|
109
|
-
defaultNs,
|
|
110
|
-
ns,
|
|
111
|
-
translation,
|
|
112
|
-
apiKey,
|
|
113
|
-
devMode: devModeOption ?? process.env.NODE_ENV === "development",
|
|
114
|
-
onMissingKey,
|
|
115
|
-
tagInterpolation: basicHtmlTags ? { basicHtmlTags } : void 0
|
|
116
|
-
});
|
|
117
|
-
const result = {
|
|
118
|
-
i18n,
|
|
119
|
-
routing: require_defineRouting.defineRouting({
|
|
120
|
-
locales,
|
|
121
|
-
defaultLocale,
|
|
122
|
-
localePrefix,
|
|
123
|
-
pathnames
|
|
124
|
-
}),
|
|
125
|
-
use(plugin, pluginOptions) {
|
|
126
|
-
i18n.use(plugin, pluginOptions);
|
|
127
|
-
return result;
|
|
128
|
-
},
|
|
129
|
-
useClient(plugin, options) {
|
|
130
|
-
const { environment, pluginOptions } = normalizeScopedOptions(options);
|
|
131
|
-
i18n.use(createScopedPlugin(plugin, "client", environment), pluginOptions);
|
|
132
|
-
return result;
|
|
133
|
-
},
|
|
134
|
-
useServer(plugin, options) {
|
|
135
|
-
const { environment, pluginOptions } = normalizeScopedOptions(options);
|
|
136
|
-
i18n.use(createScopedPlugin(plugin, "server", environment), pluginOptions);
|
|
137
|
-
return result;
|
|
138
|
-
},
|
|
139
|
-
useClientLazy(loadPlugin, options) {
|
|
140
|
-
const { environment, pluginOptions } = normalizeScopedOptions(options);
|
|
141
|
-
i18n.use(createScopedLazyPlugin(loadPlugin, "client", environment), pluginOptions);
|
|
142
|
-
return result;
|
|
143
|
-
},
|
|
144
|
-
useServerLazy(loadPlugin, options) {
|
|
145
|
-
const { environment, pluginOptions } = normalizeScopedOptions(options);
|
|
146
|
-
i18n.use(createScopedLazyPlugin(loadPlugin, "server", environment), pluginOptions);
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
return result;
|
|
151
|
-
}
|
|
152
|
-
//#endregion
|
|
153
|
-
exports.createNextI18n = createNextI18n;
|
package/dist/index.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("./_virtual/_rolldown/runtime.cjs");
|
|
3
|
-
const require_createNextI18n = require("./createNextI18n.cjs");
|
|
4
|
-
let _comvi_core = require("@comvi/core");
|
|
5
|
-
Object.defineProperty(exports, "I18n", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return _comvi_core.I18n;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
Object.defineProperty(exports, "createI18n", {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function() {
|
|
14
|
-
return _comvi_core.createI18n;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
exports.createNextI18n = require_createNextI18n.createNextI18n;
|