@better-i18n/next 0.5.2 → 0.5.3

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.
@@ -0,0 +1,99 @@
1
+ import { type ReactNode } from "react";
2
+ import type { LanguageOption, Messages } from "@better-i18n/core";
3
+ import type { I18nConfig } from "./types.js";
4
+ export interface BetterI18nProviderProps {
5
+ /** Initial locale from server (getLocale()) */
6
+ locale: string;
7
+ /** Initial messages from server (getMessages()) */
8
+ messages: Messages;
9
+ /** i18n config — only project and defaultLocale are required */
10
+ config: I18nConfig;
11
+ children: ReactNode;
12
+ }
13
+ /**
14
+ * Provider that wraps `NextIntlClientProvider` and enables instant locale
15
+ * switching without a server round-trip.
16
+ *
17
+ * When `useSetLocale()` is called inside this provider, it:
18
+ * 1. Sets a cookie (for server-side persistence on next navigation)
19
+ * 2. Fetches new messages from CDN on the client
20
+ * 3. Re-renders the tree with new locale + messages instantly
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * // app/layout.tsx
25
+ * import { BetterI18nProvider } from '@better-i18n/next/client'
26
+ *
27
+ * export default async function RootLayout({ children }) {
28
+ * const locale = await getLocale()
29
+ * const messages = await getMessages()
30
+ *
31
+ * return (
32
+ * <BetterI18nProvider
33
+ * locale={locale}
34
+ * messages={messages}
35
+ * config={{ project: 'acme/dashboard', defaultLocale: 'en' }}
36
+ * >
37
+ * {children}
38
+ * </BetterI18nProvider>
39
+ * )
40
+ * }
41
+ * ```
42
+ */
43
+ export declare function BetterI18nProvider({ locale: initialLocale, messages: initialMessages, config, children, }: BetterI18nProviderProps): import("react/jsx-runtime").JSX.Element;
44
+ export type UseManifestLanguagesResult = {
45
+ languages: LanguageOption[];
46
+ isLoading: boolean;
47
+ error: Error | null;
48
+ };
49
+ /**
50
+ * React hook to fetch manifest languages on the client
51
+ *
52
+ * Uses `createI18nCore` from `@better-i18n/core` internally with
53
+ * request deduplication to prevent duplicate fetches.
54
+ *
55
+ * @example
56
+ * ```tsx
57
+ * const { languages, isLoading, error } = useManifestLanguages({
58
+ * project: 'acme/dashboard',
59
+ * defaultLocale: 'en',
60
+ * })
61
+ *
62
+ * if (isLoading) return <Spinner />
63
+ * if (error) return <Error message={error.message} />
64
+ *
65
+ * return (
66
+ * <select>
67
+ * {languages.map(lang => (
68
+ * <option key={lang.code} value={lang.code}>
69
+ * {lang.nativeName || lang.name || lang.code}
70
+ * </option>
71
+ * ))}
72
+ * </select>
73
+ * )
74
+ * ```
75
+ */
76
+ export declare const useManifestLanguages: (config: I18nConfig) => UseManifestLanguagesResult;
77
+ /**
78
+ * React hook that returns a function to switch the active locale.
79
+ *
80
+ * - **With `BetterI18nProvider`**: Fetches new messages client-side from CDN
81
+ * and updates the UI instantly — no page refresh needed.
82
+ * - **Without provider (standalone)**: Pass a config object. Sets a cookie and
83
+ * calls `router.refresh()` for a soft server re-render.
84
+ *
85
+ * @example With provider (recommended — instant switching)
86
+ * ```tsx
87
+ * // Wrap your layout with BetterI18nProvider, then:
88
+ * const setLocale = useSetLocale()
89
+ * <button onClick={() => setLocale('tr')}>Türkçe</button>
90
+ * ```
91
+ *
92
+ * @example Standalone (soft refresh)
93
+ * ```tsx
94
+ * const setLocale = useSetLocale({ project: 'acme/dashboard', defaultLocale: 'en' })
95
+ * <button onClick={() => setLocale('tr')}>Türkçe</button>
96
+ * ```
97
+ */
98
+ export declare function useSetLocale(config?: I18nConfig): (locale: string) => void;
99
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAU7C,MAAM,WAAW,uBAAuB;IACtC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,QAAQ,EAAE,QAAQ,CAAC;IACnB,gEAAgE;IAChE,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,eAAe,EACzB,MAAM,EACN,QAAQ,GACT,EAAE,uBAAuB,2CAqDzB;AAID,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAcF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,UAAU,KAAG,0BAuFzD,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAkB1E"}
package/dist/client.js ADDED
@@ -0,0 +1,230 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
4
+ import { useRouter } from "next/navigation";
5
+ import { NextIntlClientProvider } from "next-intl";
6
+ import { createI18nCore, parseProject } from "@better-i18n/core";
7
+ import { normalizeConfig } from "./config.js";
8
+ const BetterI18nContext = createContext(null);
9
+ /**
10
+ * Provider that wraps `NextIntlClientProvider` and enables instant locale
11
+ * switching without a server round-trip.
12
+ *
13
+ * When `useSetLocale()` is called inside this provider, it:
14
+ * 1. Sets a cookie (for server-side persistence on next navigation)
15
+ * 2. Fetches new messages from CDN on the client
16
+ * 3. Re-renders the tree with new locale + messages instantly
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * // app/layout.tsx
21
+ * import { BetterI18nProvider } from '@better-i18n/next/client'
22
+ *
23
+ * export default async function RootLayout({ children }) {
24
+ * const locale = await getLocale()
25
+ * const messages = await getMessages()
26
+ *
27
+ * return (
28
+ * <BetterI18nProvider
29
+ * locale={locale}
30
+ * messages={messages}
31
+ * config={{ project: 'acme/dashboard', defaultLocale: 'en' }}
32
+ * >
33
+ * {children}
34
+ * </BetterI18nProvider>
35
+ * )
36
+ * }
37
+ * ```
38
+ */
39
+ export function BetterI18nProvider({ locale: initialLocale, messages: initialMessages, config, children, }) {
40
+ const normalized = useMemo(() => normalizeConfig(config), [
41
+ config.project,
42
+ config.defaultLocale,
43
+ config.cookieName,
44
+ config.cdnBaseUrl,
45
+ ]);
46
+ const [locale, setLocaleState] = useState(initialLocale);
47
+ const [messages, setMessages] = useState(initialMessages);
48
+ // Sync with server-provided values when they change (e.g. navigation to a new page)
49
+ useEffect(() => {
50
+ setLocaleState(initialLocale);
51
+ setMessages(initialMessages);
52
+ }, [initialLocale, initialMessages]);
53
+ const setLocale = useCallback(async (newLocale) => {
54
+ if (newLocale === locale)
55
+ return;
56
+ // 1. Set cookie for server-side persistence
57
+ document.cookie = `${normalized.cookieName}=${newLocale}; path=/; max-age=31536000; samesite=lax`;
58
+ // 2. Fetch new messages from CDN
59
+ const { workspaceId, projectSlug } = parseProject(normalized.project);
60
+ const cdnBase = normalized.cdnBaseUrl || "https://cdn.better-i18n.com";
61
+ const url = `${cdnBase}/${workspaceId}/${projectSlug}/${newLocale}/translations.json`;
62
+ try {
63
+ const res = await fetch(url);
64
+ if (!res.ok)
65
+ throw new Error(`HTTP ${res.status}`);
66
+ const newMessages = await res.json();
67
+ // 3. Instant client-side update — no server round-trip
68
+ setLocaleState(newLocale);
69
+ setMessages(newMessages);
70
+ }
71
+ catch (err) {
72
+ console.error("[better-i18n] Client-side locale switch failed, falling back to refresh:", err);
73
+ // Fallback: let the server handle it
74
+ window.location.reload();
75
+ }
76
+ }, [locale, normalized]);
77
+ return (_jsx(BetterI18nContext.Provider, { value: { setLocale }, children: _jsx(NextIntlClientProvider, { locale: locale, messages: messages, children: children }) }));
78
+ }
79
+ // Client-side request deduplication cache
80
+ const clientCache = new Map();
81
+ const getCacheKey = (project, cdnBaseUrl) => `${cdnBaseUrl || "https://cdn.better-i18n.com"}|${project}`;
82
+ /**
83
+ * React hook to fetch manifest languages on the client
84
+ *
85
+ * Uses `createI18nCore` from `@better-i18n/core` internally with
86
+ * request deduplication to prevent duplicate fetches.
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * const { languages, isLoading, error } = useManifestLanguages({
91
+ * project: 'acme/dashboard',
92
+ * defaultLocale: 'en',
93
+ * })
94
+ *
95
+ * if (isLoading) return <Spinner />
96
+ * if (error) return <Error message={error.message} />
97
+ *
98
+ * return (
99
+ * <select>
100
+ * {languages.map(lang => (
101
+ * <option key={lang.code} value={lang.code}>
102
+ * {lang.nativeName || lang.name || lang.code}
103
+ * </option>
104
+ * ))}
105
+ * </select>
106
+ * )
107
+ * ```
108
+ */
109
+ export const useManifestLanguages = (config) => {
110
+ const normalized = useMemo(() => normalizeConfig(config), [
111
+ config.project,
112
+ config.defaultLocale,
113
+ config.cdnBaseUrl,
114
+ config.debug,
115
+ config.logLevel,
116
+ ]);
117
+ const i18nCore = useMemo(() => createI18nCore({
118
+ project: normalized.project,
119
+ defaultLocale: normalized.defaultLocale,
120
+ cdnBaseUrl: normalized.cdnBaseUrl,
121
+ debug: normalized.debug,
122
+ logLevel: normalized.logLevel,
123
+ }), [normalized]);
124
+ const cacheKey = getCacheKey(normalized.project, normalized.cdnBaseUrl);
125
+ const cached = clientCache.get(cacheKey);
126
+ const [languages, setLanguages] = useState(cached?.data ?? []);
127
+ const [isLoading, setIsLoading] = useState(!cached?.data);
128
+ const [error, setError] = useState(cached?.error ?? null);
129
+ useEffect(() => {
130
+ let isMounted = true;
131
+ const run = async () => {
132
+ const entry = clientCache.get(cacheKey) ?? {};
133
+ // Return cached data if available
134
+ if (entry.data) {
135
+ if (isMounted) {
136
+ setLanguages(entry.data);
137
+ setIsLoading(false);
138
+ }
139
+ return;
140
+ }
141
+ // Deduplicate in-flight requests
142
+ if (!entry.promise) {
143
+ entry.promise = i18nCore
144
+ .getLanguages()
145
+ .then((langs) => {
146
+ clientCache.set(cacheKey, { data: langs });
147
+ return langs;
148
+ })
149
+ .catch((err) => {
150
+ const error = err instanceof Error ? err : new Error(String(err));
151
+ clientCache.set(cacheKey, { error });
152
+ throw error;
153
+ });
154
+ clientCache.set(cacheKey, entry);
155
+ }
156
+ try {
157
+ const langs = await entry.promise;
158
+ if (isMounted) {
159
+ setLanguages(langs);
160
+ setError(null);
161
+ }
162
+ }
163
+ catch (err) {
164
+ if (isMounted) {
165
+ setError(err instanceof Error ? err : new Error(String(err)));
166
+ }
167
+ }
168
+ finally {
169
+ if (isMounted) {
170
+ setIsLoading(false);
171
+ }
172
+ }
173
+ };
174
+ run();
175
+ return () => {
176
+ isMounted = false;
177
+ };
178
+ }, [cacheKey, i18nCore]);
179
+ return { languages, isLoading, error };
180
+ };
181
+ // ─── useSetLocale ────────────────────────────────────────────────────
182
+ /**
183
+ * React hook that returns a function to switch the active locale.
184
+ *
185
+ * - **With `BetterI18nProvider`**: Fetches new messages client-side from CDN
186
+ * and updates the UI instantly — no page refresh needed.
187
+ * - **Without provider (standalone)**: Pass a config object. Sets a cookie and
188
+ * calls `router.refresh()` for a soft server re-render.
189
+ *
190
+ * @example With provider (recommended — instant switching)
191
+ * ```tsx
192
+ * // Wrap your layout with BetterI18nProvider, then:
193
+ * const setLocale = useSetLocale()
194
+ * <button onClick={() => setLocale('tr')}>Türkçe</button>
195
+ * ```
196
+ *
197
+ * @example Standalone (soft refresh)
198
+ * ```tsx
199
+ * const setLocale = useSetLocale({ project: 'acme/dashboard', defaultLocale: 'en' })
200
+ * <button onClick={() => setLocale('tr')}>Türkçe</button>
201
+ * ```
202
+ */
203
+ export function useSetLocale(config) {
204
+ const ctx = useContext(BetterI18nContext);
205
+ // If BetterI18nProvider is in the tree, use instant client-side switching
206
+ if (ctx) {
207
+ return ctx.setLocale;
208
+ }
209
+ // Standalone fallback: cookie + router.refresh()
210
+ if (!config) {
211
+ throw new Error("[better-i18n] useSetLocale() requires either a <BetterI18nProvider> ancestor " +
212
+ "or a config argument. Use useSetLocale({ project, defaultLocale }) for standalone mode.");
213
+ }
214
+ // eslint-disable-next-line react-hooks/rules-of-hooks
215
+ return useStandaloneSetLocale(config);
216
+ }
217
+ /** Internal standalone hook — cookie + router.refresh() */
218
+ function useStandaloneSetLocale(config) {
219
+ const normalized = useMemo(() => normalizeConfig(config), [
220
+ config.project,
221
+ config.defaultLocale,
222
+ config.cookieName,
223
+ ]);
224
+ const router = useRouter();
225
+ return useCallback((locale) => {
226
+ document.cookie = `${normalized.cookieName}=${locale}; path=/; max-age=31536000; samesite=lax`;
227
+ router.refresh();
228
+ }, [normalized.cookieName, router]);
229
+ }
230
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { parseProject } from "@better-i18n/core";
2
+ import type { I18nConfig, NormalizedConfig } from "./types.js";
3
+ export { parseProject };
4
+ /**
5
+ * Normalize Next.js i18n config with defaults
6
+ */
7
+ export declare const normalizeConfig: (config: I18nConfig) => NormalizedConfig;
8
+ /**
9
+ * Get the project base URL on CDN
10
+ */
11
+ export declare const getProjectBaseUrl: (config: NormalizedConfig) => string;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,UAAU,KAAG,gBAoBpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,gBAAgB,KAAG,MAC9B,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,31 @@
1
+ import { parseProject, getProjectBaseUrl as coreGetProjectBaseUrl, normalizeConfig as coreNormalizeConfig, } from "@better-i18n/core";
2
+ // Re-export parseProject from core
3
+ export { parseProject };
4
+ /**
5
+ * Normalize Next.js i18n config with defaults
6
+ */
7
+ export const normalizeConfig = (config) => {
8
+ // Use core normalization for base config
9
+ const coreConfig = coreNormalizeConfig({
10
+ project: config.project,
11
+ defaultLocale: config.defaultLocale,
12
+ cdnBaseUrl: config.cdnBaseUrl,
13
+ manifestCacheTtlMs: config.manifestCacheTtlMs,
14
+ debug: config.debug,
15
+ logLevel: config.logLevel,
16
+ fetch: config.fetch,
17
+ });
18
+ // Add Next.js-specific defaults
19
+ return {
20
+ ...coreConfig,
21
+ localePrefix: config.localePrefix ?? "as-needed",
22
+ cookieName: config.cookieName ?? "locale",
23
+ manifestRevalidateSeconds: config.manifestRevalidateSeconds ?? 3600,
24
+ messagesRevalidateSeconds: config.messagesRevalidateSeconds ?? 30,
25
+ };
26
+ };
27
+ /**
28
+ * Get the project base URL on CDN
29
+ */
30
+ export const getProjectBaseUrl = (config) => coreGetProjectBaseUrl(config);
31
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,iBAAiB,IAAI,qBAAqB,EAC1C,eAAe,IAAI,mBAAmB,GACvC,MAAM,mBAAmB,CAAC;AAG3B,mCAAmC;AACnC,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAkB,EAAoB,EAAE;IACtE,yCAAyC;IACzC,MAAM,UAAU,GAAG,mBAAmB,CAAC;QACrC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;IAEH,gCAAgC;IAChC,OAAO;QACL,GAAG,UAAU;QACb,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,WAAW;QAChD,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,QAAQ;QACzC,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,IAAI,IAAI;QACnE,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,IAAI,EAAE;KAClE,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAwB,EAAU,EAAE,CACpE,qBAAqB,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { I18nConfig } from "./types.js";
2
+ import { createBetterI18nMiddleware, composeMiddleware, type MiddlewareCallback } from "./middleware.js";
3
+ /**
4
+ * Create a complete i18n setup for Next.js
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * // i18n/config.ts
9
+ * import { createI18n } from '@better-i18n/next'
10
+ *
11
+ * export const i18n = createI18n({
12
+ * project: 'acme/dashboard',
13
+ * defaultLocale: 'en',
14
+ * localePrefix: 'always',
15
+ * })
16
+ *
17
+ * // i18n/request.ts
18
+ * export default i18n.requestConfig
19
+ *
20
+ * // middleware.ts (simple)
21
+ * export default i18n.middleware
22
+ *
23
+ * // middleware.ts (with auth - Clerk-style)
24
+ * export default i18n.betterMiddleware(async (request, { locale }) => {
25
+ * if (needsLogin) {
26
+ * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
27
+ * }
28
+ * });
29
+ * ```
30
+ */
31
+ export declare const createI18n: (config: I18nConfig) => {
32
+ config: import("./types.js").NormalizedConfig;
33
+ requestConfig: (params: import("next-intl/server").GetRequestConfigParams) => import("next-intl/server").RequestConfig | Promise<import("next-intl/server").RequestConfig>;
34
+ /** @deprecated Use betterMiddleware() for Clerk-style callback support */
35
+ middleware: (request: import("next/server.js").NextRequest) => Promise<import("next/server.js").NextResponse<unknown>>;
36
+ proxy: (request: import("next/server.js").NextRequest) => Promise<import("next/server.js").NextResponse<unknown>>;
37
+ getManifest: (options?: {
38
+ forceRefresh?: boolean;
39
+ }) => Promise<import("@better-i18n/core").ManifestResponse>;
40
+ getLocales: () => Promise<string[]>;
41
+ getMessages: (locale: string) => Promise<import("@better-i18n/core").Messages>;
42
+ /**
43
+ * Create middleware with optional Clerk-style callback for auth integration
44
+ *
45
+ * @example Simple usage
46
+ * ```ts
47
+ * export default i18n.betterMiddleware();
48
+ * ```
49
+ *
50
+ * @example With auth callback
51
+ * ```ts
52
+ * export default i18n.betterMiddleware(async (request, { locale, response }) => {
53
+ * if (needsLogin) {
54
+ * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
55
+ * }
56
+ * // Return nothing = i18n response is used (headers preserved!)
57
+ * });
58
+ * ```
59
+ */
60
+ betterMiddleware: (callback?: MiddlewareCallback) => (request: import("next/server.js").NextRequest) => Promise<import("next/server.js").NextResponse>;
61
+ };
62
+ export { createBetterI18nMiddleware, composeMiddleware };
63
+ export type { MiddlewareContext, MiddlewareCallback } from "./middleware.js";
64
+ export { createNextI18nCore } from "./server.js";
65
+ export { BetterI18nProvider, useManifestLanguages, useSetLocale } from "./client.js";
66
+ export type { BetterI18nProviderProps } from "./client.js";
67
+ export type { I18nConfig, LanguageOption, Locale, LocalePrefix, LogLevel, ManifestLanguage, ManifestResponse, Messages, } from "./types.js";
68
+ export type { I18nMiddlewareConfig } from "@better-i18n/core";
69
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C,OAAO,EAGL,0BAA0B,EAC1B,iBAAiB,EACjB,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,UAAU;;;IAOzC,0EAA0E;;;;oBA0D1E,CAAC;;;;IAnDD;;;;;;;;;;;;;;;;;OAiBG;kCAC2B,kBAAkB;CAgBnD,CAAC;AAGF,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrF,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG3D,YAAY,EACV,UAAU,EACV,cAAc,EACd,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,82 @@
1
+ import { normalizeConfig } from "./config.js";
2
+ import { createNextI18nCore, createNextIntlRequestConfig, } from "./server.js";
3
+ import { createI18nMiddleware, createI18nProxy, createBetterI18nMiddleware, composeMiddleware, } from "./middleware.js";
4
+ /**
5
+ * Create a complete i18n setup for Next.js
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * // i18n/config.ts
10
+ * import { createI18n } from '@better-i18n/next'
11
+ *
12
+ * export const i18n = createI18n({
13
+ * project: 'acme/dashboard',
14
+ * defaultLocale: 'en',
15
+ * localePrefix: 'always',
16
+ * })
17
+ *
18
+ * // i18n/request.ts
19
+ * export default i18n.requestConfig
20
+ *
21
+ * // middleware.ts (simple)
22
+ * export default i18n.middleware
23
+ *
24
+ * // middleware.ts (with auth - Clerk-style)
25
+ * export default i18n.betterMiddleware(async (request, { locale }) => {
26
+ * if (needsLogin) {
27
+ * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
28
+ * }
29
+ * });
30
+ * ```
31
+ */
32
+ export const createI18n = (config) => {
33
+ const normalized = normalizeConfig(config);
34
+ const i18n = createNextI18nCore(normalized);
35
+ return {
36
+ config: normalized,
37
+ requestConfig: createNextIntlRequestConfig(normalized),
38
+ /** @deprecated Use betterMiddleware() for Clerk-style callback support */
39
+ middleware: createI18nMiddleware(normalized),
40
+ proxy: createI18nProxy(normalized),
41
+ getManifest: i18n.getManifest,
42
+ getLocales: i18n.getLocales,
43
+ getMessages: i18n.getMessages,
44
+ /**
45
+ * Create middleware with optional Clerk-style callback for auth integration
46
+ *
47
+ * @example Simple usage
48
+ * ```ts
49
+ * export default i18n.betterMiddleware();
50
+ * ```
51
+ *
52
+ * @example With auth callback
53
+ * ```ts
54
+ * export default i18n.betterMiddleware(async (request, { locale, response }) => {
55
+ * if (needsLogin) {
56
+ * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
57
+ * }
58
+ * // Return nothing = i18n response is used (headers preserved!)
59
+ * });
60
+ * ```
61
+ */
62
+ betterMiddleware: (callback) => {
63
+ return createBetterI18nMiddleware({
64
+ project: normalized.project,
65
+ defaultLocale: normalized.defaultLocale,
66
+ localePrefix: normalized.localePrefix,
67
+ detection: {
68
+ cookie: true,
69
+ browserLanguage: true,
70
+ cookieName: normalized.cookieName,
71
+ },
72
+ }, callback);
73
+ },
74
+ };
75
+ };
76
+ // Modern standalone middleware exports
77
+ export { createBetterI18nMiddleware, composeMiddleware };
78
+ // Core instance factory
79
+ export { createNextI18nCore } from "./server.js";
80
+ // Client hooks & provider
81
+ export { BetterI18nProvider, useManifestLanguages, useSetLocale } from "./client.js";
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,0BAA0B,EAC1B,iBAAiB,GAElB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAkB,EAAE,EAAE;IAC/C,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE5C,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,aAAa,EAAE,2BAA2B,CAAC,UAAU,CAAC;QACtD,0EAA0E;QAC1E,UAAU,EAAE,oBAAoB,CAAC,UAAU,CAAC;QAC5C,KAAK,EAAE,eAAe,CAAC,UAAU,CAAC;QAClC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;QAE7B;;;;;;;;;;;;;;;;;WAiBG;QACH,gBAAgB,EAAE,CAAC,QAA6B,EAAE,EAAE;YAClD,OAAO,0BAA0B,CAC/B;gBACE,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,aAAa,EAAE,UAAU,CAAC,aAAa;gBACvC,YAAY,EAAE,UAAU,CAAC,YAAY;gBACrC,SAAS,EAAE;oBACT,MAAM,EAAE,IAAI;oBACZ,eAAe,EAAE,IAAI;oBACrB,UAAU,EAAE,UAAU,CAAC,UAAU;iBAClC;aACF,EACD,QAAQ,CACT,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,uCAAuC;AACvC,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,CAAC;AAGzD,wBAAwB;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,0BAA0B;AAC1B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { NextRequest, NextResponse } from "next/server";
2
+ import type { I18nMiddlewareConfig } from "@better-i18n/core";
3
+ import type { I18nConfig } from "./types.js";
4
+ /**
5
+ * Context passed to the middleware callback (Clerk-style pattern)
6
+ */
7
+ export interface MiddlewareContext {
8
+ /** Detected locale from the request */
9
+ locale: string;
10
+ /** The i18n response with headers already set - can be modified */
11
+ response: NextResponse;
12
+ }
13
+ /**
14
+ * Callback function for Clerk-style middleware composition
15
+ *
16
+ * @param request - The incoming Next.js request
17
+ * @param context - Contains locale and response from i18n middleware
18
+ * @returns NextResponse to short-circuit (e.g., redirect), or void to continue with i18n response
19
+ */
20
+ export type MiddlewareCallback = (request: NextRequest, context: MiddlewareContext) => Promise<NextResponse | void> | NextResponse | void;
21
+ /**
22
+ * Legacy Next-intl based middleware
23
+ */
24
+ export declare const createI18nMiddleware: (config: I18nConfig) => (request: NextRequest) => Promise<NextResponse<unknown>>;
25
+ export declare const createI18nProxy: (config: I18nConfig) => (request: NextRequest) => Promise<NextResponse<unknown>>;
26
+ /**
27
+ * Modern composable middleware for Better i18n (Clerk-style pattern)
28
+ *
29
+ * Delegates to next-intl's middleware internally to ensure full compatibility
30
+ * with `getRequestConfig({ requestLocale })` while keeping our compose-friendly
31
+ * API and custom locale detection options.
32
+ *
33
+ * @example Simple usage (no callback)
34
+ * ```ts
35
+ * export default createBetterI18nMiddleware({
36
+ * project: "acme/dashboard",
37
+ * defaultLocale: "en",
38
+ * localePrefix: "always",
39
+ * });
40
+ * ```
41
+ *
42
+ * @example With callback (Clerk-style - recommended for auth)
43
+ * ```ts
44
+ * export default createBetterI18nMiddleware({
45
+ * project: "acme/dashboard",
46
+ * defaultLocale: "en",
47
+ * localePrefix: "always",
48
+ * }, async (request, { locale, response }) => {
49
+ * // Auth logic here - locale and response are available
50
+ * if (needsLogin) {
51
+ * return NextResponse.redirect(new URL(`/${locale}/login`, request.url));
52
+ * }
53
+ * // Return nothing = i18n response is used (headers preserved!)
54
+ * });
55
+ * ```
56
+ */
57
+ export declare function createBetterI18nMiddleware(config: I18nMiddlewareConfig, callback?: MiddlewareCallback): (request: NextRequest) => Promise<NextResponse>;
58
+ /**
59
+ * Helper to compose multiple Next.js middleware
60
+ *
61
+ * @deprecated Use `createBetterI18nMiddleware` with a callback instead (Clerk-style pattern).
62
+ * The callback approach is more reliable and gives you access to the detected locale.
63
+ *
64
+ * @example Migration
65
+ * ```ts
66
+ * // Before (deprecated):
67
+ * export default composeMiddleware(i18nMiddleware, authMiddleware);
68
+ *
69
+ * // After (recommended):
70
+ * export default createBetterI18nMiddleware(config, async (req, { locale, response }) => {
71
+ * // Auth logic here
72
+ * });
73
+ * ```
74
+ *
75
+ * @see https://github.com/better-i18n/better-i18n#middleware-composition
76
+ */
77
+ export declare function composeMiddleware(...middlewares: Array<(req: NextRequest) => Promise<NextResponse>>): (request: NextRequest) => Promise<NextResponse>;
78
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAI9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,UAAU,MAIpB,SAAS,WAAW,mCAYtD,CAAC;AAEF,eAAO,MAAM,eAAe,WAlBiB,UAAU,MAIpB,SAAS,WAAW,mCAcJ,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,CAAC,EAAE,kBAAkB,IAkBf,SAAS,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC,CA+E3D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,WAAW,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC,IAUpD,SAAS,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC,CA0B3D"}