@comvi/next 0.2.0 → 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 CHANGED
@@ -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;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAe,EACf,OAAO,EACP,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAuDnB;yBA/De,YAAY"}
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
- var isServer = typeof window === "undefined";
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
- const isFirstRenderRef = useRef(true);
64
- if (isServer || isFirstRenderRef.current) {
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
- if (!isServer) isFirstRenderRef.current = false;
71
- }
85
+ return null;
86
+ });
72
87
  useIsomorphicLayoutEffect(() => {
73
- if (i18n.locale !== locale) i18n.locale = locale;
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
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.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,uBAAuB,CAAC;AACrD,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
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 };
@@ -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 { useI18n } from "@comvi/react";
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 { locale: currentLocale } = useI18n();
28
+ const currentLocale = useLocale();
29
29
  const locale = targetLocale ?? currentLocale;
30
30
  const routing = useRoutingConfig();
31
31
  return /* @__PURE__ */ jsx(NextLink, {
@@ -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 { useI18n } from "@comvi/react";
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 { locale } = useI18n();
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 { locale } = useI18n();
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.2.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
- "import": "./dist/index.js",
43
- "require": "./dist/index.cjs"
41
+ "default": "./dist/index.js"
44
42
  },
45
43
  "./server": {
46
44
  "types": "./dist/server.d.ts",
47
- "import": "./dist/server.js",
48
- "require": "./dist/server.cjs"
45
+ "default": "./dist/server.js"
49
46
  },
50
47
  "./client": {
51
48
  "types": "./dist/client.d.ts",
52
- "import": "./dist/client.js",
53
- "require": "./dist/client.cjs"
49
+ "default": "./dist/client.js"
54
50
  },
55
51
  "./middleware": {
56
52
  "types": "./dist/middleware.d.ts",
57
- "import": "./dist/middleware.js",
58
- "require": "./dist/middleware.cjs"
53
+ "default": "./dist/middleware.js"
59
54
  },
60
55
  "./routing": {
61
56
  "types": "./dist/routing.d.ts",
62
- "import": "./dist/routing.js",
63
- "require": "./dist/routing.cjs"
57
+ "default": "./dist/routing.js"
64
58
  },
65
59
  "./navigation": {
66
60
  "types": "./dist/navigation.d.ts",
67
- "import": "./dist/navigation.js",
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.2.0",
74
- "@comvi/react": "0.2.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;
@@ -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
- });
@@ -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;