@djangocfg/nextjs 2.1.110 → 2.1.111

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.
Files changed (60) hide show
  1. package/README.md +176 -7
  2. package/dist/config/index.d.mts +16 -1
  3. package/dist/config/index.mjs +83 -14
  4. package/dist/config/index.mjs.map +1 -1
  5. package/dist/i18n/client.d.mts +123 -0
  6. package/dist/i18n/client.mjs +104 -0
  7. package/dist/i18n/client.mjs.map +1 -0
  8. package/dist/i18n/components.d.mts +22 -0
  9. package/dist/i18n/components.mjs +133 -0
  10. package/dist/i18n/components.mjs.map +1 -0
  11. package/dist/i18n/index.d.mts +17 -0
  12. package/dist/i18n/index.mjs +269 -0
  13. package/dist/i18n/index.mjs.map +1 -0
  14. package/dist/i18n/navigation.d.mts +1095 -0
  15. package/dist/i18n/navigation.mjs +45 -0
  16. package/dist/i18n/navigation.mjs.map +1 -0
  17. package/dist/i18n/plugin.d.mts +41 -0
  18. package/dist/i18n/plugin.mjs +17 -0
  19. package/dist/i18n/plugin.mjs.map +1 -0
  20. package/dist/i18n/provider.d.mts +18 -0
  21. package/dist/i18n/provider.mjs +54 -0
  22. package/dist/i18n/provider.mjs.map +1 -0
  23. package/dist/i18n/proxy.d.mts +40 -0
  24. package/dist/i18n/proxy.mjs +42 -0
  25. package/dist/i18n/proxy.mjs.map +1 -0
  26. package/dist/i18n/request.d.mts +42 -0
  27. package/dist/i18n/request.mjs +63 -0
  28. package/dist/i18n/request.mjs.map +1 -0
  29. package/dist/i18n/routing.d.mts +79 -0
  30. package/dist/i18n/routing.mjs +33 -0
  31. package/dist/i18n/routing.mjs.map +1 -0
  32. package/dist/i18n/server.d.mts +90 -0
  33. package/dist/i18n/server.mjs +79 -0
  34. package/dist/i18n/server.mjs.map +1 -0
  35. package/dist/index.d.mts +3 -1
  36. package/dist/index.mjs +176 -30
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/sitemap/index.d.mts +22 -3
  39. package/dist/sitemap/index.mjs +92 -15
  40. package/dist/sitemap/index.mjs.map +1 -1
  41. package/dist/types-Cy349X20.d.mts +60 -0
  42. package/package.json +54 -4
  43. package/src/config/constants.ts +1 -0
  44. package/src/config/createNextConfig.ts +39 -17
  45. package/src/i18n/client.ts +221 -0
  46. package/src/i18n/components/LocaleSwitcher.tsx +124 -0
  47. package/src/i18n/components/index.ts +7 -0
  48. package/src/i18n/index.ts +149 -0
  49. package/src/i18n/navigation.ts +90 -0
  50. package/src/i18n/plugin.ts +66 -0
  51. package/src/i18n/provider.tsx +91 -0
  52. package/src/i18n/proxy.ts +81 -0
  53. package/src/i18n/request.ts +141 -0
  54. package/src/i18n/routing.ts +84 -0
  55. package/src/i18n/server.ts +175 -0
  56. package/src/i18n/types.ts +88 -0
  57. package/src/sitemap/generator.ts +84 -9
  58. package/src/sitemap/index.ts +1 -1
  59. package/src/sitemap/route.ts +71 -8
  60. package/src/sitemap/types.ts +9 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Client-side i18n Hooks
3
+ *
4
+ * For use in Client Components ('use client')
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * 'use client';
9
+ *
10
+ * import { useTranslations, useLocale } from '@djangocfg/nextjs/i18n/client';
11
+ *
12
+ * export function MyComponent() {
13
+ * const t = useTranslations('HomePage');
14
+ * const locale = useLocale();
15
+ *
16
+ * return <h1>{t('title')}</h1>;
17
+ * }
18
+ * ```
19
+ */
20
+
21
+ 'use client';
22
+
23
+ import {
24
+ useTranslations as useNextIntlTranslations,
25
+ useLocale as useNextIntlLocale,
26
+ useMessages,
27
+ useNow,
28
+ useTimeZone,
29
+ useFormatter,
30
+ } from 'next-intl';
31
+ import { useRouter, usePathname } from './navigation';
32
+ import { routing } from './routing';
33
+ import type { LocaleCode } from './types';
34
+
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+ // Core Client Hooks
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+
39
+ /**
40
+ * Get translations in Client Components
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * const t = useTranslations('HomePage');
45
+ * return <h1>{t('title')}</h1>;
46
+ *
47
+ * // With interpolation
48
+ * return <p>{t('greeting', { name: 'John' })}</p>;
49
+ * ```
50
+ */
51
+ export function useTranslations<Namespace extends string = never>(
52
+ namespace?: Namespace
53
+ ) {
54
+ return useNextIntlTranslations(namespace);
55
+ }
56
+
57
+ /**
58
+ * Get current locale in Client Components
59
+ */
60
+ export function useLocale(): LocaleCode {
61
+ return useNextIntlLocale() as LocaleCode;
62
+ }
63
+
64
+ /**
65
+ * Get all messages
66
+ * Useful for passing to child providers
67
+ */
68
+ export { useMessages };
69
+
70
+ /**
71
+ * Get current time
72
+ */
73
+ export { useNow };
74
+
75
+ /**
76
+ * Get timezone
77
+ */
78
+ export { useTimeZone };
79
+
80
+ /**
81
+ * Get formatter for dates, numbers, etc.
82
+ */
83
+ export { useFormatter };
84
+
85
+ // ─────────────────────────────────────────────────────────────────────────────
86
+ // Convenience Hooks
87
+ // ─────────────────────────────────────────────────────────────────────────────
88
+
89
+ /**
90
+ * Shorthand for useTranslations
91
+ * Alias for compatibility with @djangocfg/i18n
92
+ */
93
+ export const useT = useTranslations;
94
+
95
+ /**
96
+ * Get namespaced translations
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * const pt = useNamespacedTranslations('payments');
101
+ * return <span>{pt('balance.available')}</span>;
102
+ * ```
103
+ */
104
+ export function useNamespacedTranslations(namespace: string) {
105
+ return useNextIntlTranslations(namespace);
106
+ }
107
+
108
+ // ─────────────────────────────────────────────────────────────────────────────
109
+ // Formatting Hooks
110
+ // ─────────────────────────────────────────────────────────────────────────────
111
+
112
+ /**
113
+ * Format a date according to locale
114
+ *
115
+ * @example
116
+ * ```tsx
117
+ * const formatDate = useDateFormatter();
118
+ * return <span>{formatDate(new Date())}</span>;
119
+ * ```
120
+ */
121
+ export function useDateFormatter() {
122
+ const formatter = useFormatter();
123
+ return (date: Date | number, options?: Parameters<typeof formatter.dateTime>[1]) =>
124
+ formatter.dateTime(date, options);
125
+ }
126
+
127
+ /**
128
+ * Format a number according to locale
129
+ *
130
+ * @example
131
+ * ```tsx
132
+ * const formatNumber = useNumberFormatter();
133
+ * return <span>{formatNumber(1234.56)}</span>;
134
+ * ```
135
+ */
136
+ export function useNumberFormatter() {
137
+ const formatter = useFormatter();
138
+ return (number: number, options?: Parameters<typeof formatter.number>[1]) =>
139
+ formatter.number(number, options);
140
+ }
141
+
142
+ /**
143
+ * Format relative time
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * const formatRelative = useRelativeTimeFormatter();
148
+ * return <span>{formatRelative(new Date())}</span>;
149
+ * ```
150
+ */
151
+ export function useRelativeTimeFormatter() {
152
+ const formatter = useFormatter();
153
+ return (date: Date | number, options?: Parameters<typeof formatter.relativeTime>[1]) =>
154
+ formatter.relativeTime(date, options);
155
+ }
156
+
157
+ // ─────────────────────────────────────────────────────────────────────────────
158
+ // Locale Switching Hooks
159
+ // ─────────────────────────────────────────────────────────────────────────────
160
+
161
+ /**
162
+ * Get list of available locales from routing config
163
+ *
164
+ * @example
165
+ * ```tsx
166
+ * const locales = useLocales();
167
+ * // ['en', 'ru', 'ko']
168
+ * ```
169
+ */
170
+ export function useLocales(): LocaleCode[] {
171
+ return routing.locales as LocaleCode[];
172
+ }
173
+
174
+ /**
175
+ * Get default locale from routing config
176
+ */
177
+ export function useDefaultLocale(): LocaleCode {
178
+ return routing.defaultLocale as LocaleCode;
179
+ }
180
+
181
+ /**
182
+ * Hook to change current locale
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * const changeLocale = useChangeLocale();
187
+ *
188
+ * <button onClick={() => changeLocale('ru')}>
189
+ * Switch to Russian
190
+ * </button>
191
+ * ```
192
+ */
193
+ export function useChangeLocale() {
194
+ const router = useRouter();
195
+ const pathname = usePathname();
196
+
197
+ return (locale: LocaleCode) => {
198
+ router.replace(pathname, { locale });
199
+ };
200
+ }
201
+
202
+ /**
203
+ * Combined hook for locale switching
204
+ * Returns current locale, available locales, and change function
205
+ *
206
+ * @example
207
+ * ```tsx
208
+ * const { locale, locales, changeLocale } = useLocaleSwitcher();
209
+ *
210
+ * <select value={locale} onChange={(e) => changeLocale(e.target.value)}>
211
+ * {locales.map(l => <option key={l} value={l}>{l}</option>)}
212
+ * </select>
213
+ * ```
214
+ */
215
+ export function useLocaleSwitcher() {
216
+ const locale = useLocale();
217
+ const locales = useLocales();
218
+ const changeLocale = useChangeLocale();
219
+
220
+ return { locale, locales, changeLocale };
221
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * LocaleSwitcher Component
3
+ *
4
+ * Ready-to-use locale switcher dropdown using @djangocfg/ui-core components
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { LocaleSwitcher } from '@djangocfg/nextjs/i18n/components';
9
+ *
10
+ * // Basic usage (uses all locales from routing config)
11
+ * <LocaleSwitcher />
12
+ *
13
+ * // With custom locales
14
+ * <LocaleSwitcher locales={['en', 'ru']} />
15
+ *
16
+ * // With custom labels
17
+ * <LocaleSwitcher
18
+ * labels={{
19
+ * en: 'English',
20
+ * ru: 'Русский',
21
+ * ko: '한국어',
22
+ * }}
23
+ * />
24
+ * ```
25
+ */
26
+
27
+ 'use client';
28
+
29
+ import { Globe } from 'lucide-react';
30
+
31
+ import {
32
+ Button,
33
+ DropdownMenu,
34
+ DropdownMenuContent,
35
+ DropdownMenuItem,
36
+ DropdownMenuTrigger,
37
+ } from '@djangocfg/ui-core/components';
38
+
39
+ import { useLocaleSwitcher } from '../client';
40
+ import type { LocaleCode } from '../types';
41
+
42
+ // Default locale labels
43
+ const DEFAULT_LABELS: Record<string, string> = {
44
+ en: 'English',
45
+ ru: 'Русский',
46
+ ko: '한국어',
47
+ zh: '中文',
48
+ ja: '日本語',
49
+ es: 'Español',
50
+ fr: 'Français',
51
+ de: 'Deutsch',
52
+ pt: 'Português',
53
+ it: 'Italiano',
54
+ ar: 'العربية',
55
+ hi: 'हिन्दी',
56
+ tr: 'Türkçe',
57
+ pl: 'Polski',
58
+ nl: 'Nederlands',
59
+ uk: 'Українська',
60
+ };
61
+
62
+ export interface LocaleSwitcherProps {
63
+ /** Available locales (defaults to all from routing config) */
64
+ locales?: LocaleCode[];
65
+ /** Custom labels for locales */
66
+ labels?: Record<string, string>;
67
+ /** Show locale code instead of/with label */
68
+ showCode?: boolean;
69
+ /** Button variant */
70
+ variant?: 'ghost' | 'outline' | 'default';
71
+ /** Button size */
72
+ size?: 'sm' | 'default' | 'lg' | 'icon';
73
+ /** Show icon */
74
+ showIcon?: boolean;
75
+ /** Custom className */
76
+ className?: string;
77
+ }
78
+
79
+ export function LocaleSwitcher({
80
+ locales: customLocales,
81
+ labels = {},
82
+ showCode = false,
83
+ variant = 'ghost',
84
+ size = 'sm',
85
+ showIcon = true,
86
+ className,
87
+ }: LocaleSwitcherProps) {
88
+ const { locale, locales: routingLocales, changeLocale } = useLocaleSwitcher();
89
+
90
+ const availableLocales = customLocales || routingLocales;
91
+ const allLabels = { ...DEFAULT_LABELS, ...labels };
92
+
93
+ const getLabel = (code: LocaleCode) => {
94
+ const label = allLabels[code] || code.toUpperCase();
95
+ if (showCode) {
96
+ return `${code.toUpperCase()} - ${label}`;
97
+ }
98
+ return label;
99
+ };
100
+
101
+ const currentLabel = showCode ? locale.toUpperCase() : getLabel(locale);
102
+
103
+ return (
104
+ <DropdownMenu>
105
+ <DropdownMenuTrigger asChild>
106
+ <Button variant={variant} size={size} className={className}>
107
+ {showIcon && <Globe className="h-4 w-4 mr-1" />}
108
+ <span>{currentLabel}</span>
109
+ </Button>
110
+ </DropdownMenuTrigger>
111
+ <DropdownMenuContent align="end">
112
+ {availableLocales.map((code) => (
113
+ <DropdownMenuItem
114
+ key={code}
115
+ onClick={() => changeLocale(code)}
116
+ className={code === locale ? 'bg-accent' : ''}
117
+ >
118
+ {getLabel(code)}
119
+ </DropdownMenuItem>
120
+ ))}
121
+ </DropdownMenuContent>
122
+ </DropdownMenu>
123
+ );
124
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * i18n Components
3
+ *
4
+ * Ready-to-use UI components for internationalization
5
+ */
6
+
7
+ export { LocaleSwitcher, type LocaleSwitcherProps } from './LocaleSwitcher';
@@ -0,0 +1,149 @@
1
+ /**
2
+ * i18n Module for Next.js App Router
3
+ *
4
+ * Complete internationalization solution integrating next-intl with @djangocfg/i18n
5
+ *
6
+ * @example Setup
7
+ * ```ts
8
+ * // 1. Create i18n/routing.ts
9
+ * import { createRouting } from '@djangocfg/nextjs/i18n';
10
+ *
11
+ * export const routing = createRouting({
12
+ * locales: ['en', 'ru', 'ko'],
13
+ * defaultLocale: 'en',
14
+ * });
15
+ *
16
+ * // 2. Create i18n/request.ts
17
+ * import { createRequestConfig } from '@djangocfg/nextjs/i18n';
18
+ * import { leadsI18n } from '@djangocfg/ext-leads';
19
+ *
20
+ * export default createRequestConfig({
21
+ * extensions: [leadsI18n],
22
+ * });
23
+ *
24
+ * // 3. Create i18n/navigation.ts
25
+ * import { createNavigation } from '@djangocfg/nextjs/i18n';
26
+ * import { routing } from './routing';
27
+ *
28
+ * export const { Link, redirect, usePathname, useRouter } = createNavigation(routing);
29
+ *
30
+ * // 4. Create proxy.ts
31
+ * import { createProxy } from '@djangocfg/nextjs/i18n';
32
+ * import { routing } from './i18n/routing';
33
+ *
34
+ * export default createProxy(routing);
35
+ * export const config = { matcher: ['/((?!api|_next|.*\\..*).*)'] };
36
+ *
37
+ * // 5. Update next.config.ts
38
+ * import { createBaseNextConfig } from '@djangocfg/nextjs/config';
39
+ *
40
+ * export default createBaseNextConfig({
41
+ * i18n: {
42
+ * locales: ['en', 'ru', 'ko'],
43
+ * defaultLocale: 'en',
44
+ * },
45
+ * });
46
+ *
47
+ * // 6. Create app/[locale]/layout.tsx
48
+ * import { I18nProvider } from '@djangocfg/nextjs/i18n';
49
+ * import { getMessages, getLocaleFromParams } from '@djangocfg/nextjs/i18n/server';
50
+ *
51
+ * export default async function LocaleLayout({ children, params }) {
52
+ * const locale = await getLocaleFromParams(params);
53
+ * const messages = await getMessages();
54
+ *
55
+ * return (
56
+ * <html lang={locale}>
57
+ * <body>
58
+ * <I18nProvider locale={locale} messages={messages}>
59
+ * {children}
60
+ * </I18nProvider>
61
+ * </body>
62
+ * </html>
63
+ * );
64
+ * }
65
+ * ```
66
+ */
67
+
68
+ // ─────────────────────────────────────────────────────────────────────────────
69
+ // Types
70
+ // ─────────────────────────────────────────────────────────────────────────────
71
+
72
+ export type {
73
+ I18nConfig,
74
+ I18nPluginOptions,
75
+ I18nProviderProps,
76
+ Messages,
77
+ MessagesLoader,
78
+ ExtensionMessages,
79
+ LocaleParams,
80
+ LocaleLayoutProps,
81
+ LocalePageProps,
82
+ LocaleCode,
83
+ I18nTranslations,
84
+ } from './types';
85
+
86
+ // ─────────────────────────────────────────────────────────────────────────────
87
+ // Routing
88
+ // ─────────────────────────────────────────────────────────────────────────────
89
+
90
+ export {
91
+ createRouting,
92
+ routing,
93
+ isValidLocale,
94
+ getLocaleFromParams,
95
+ generateLocaleParams,
96
+ } from './routing';
97
+
98
+ // ─────────────────────────────────────────────────────────────────────────────
99
+ // Navigation
100
+ // ─────────────────────────────────────────────────────────────────────────────
101
+
102
+ export {
103
+ createNavigation,
104
+ createNavigationFromConfig,
105
+ Link,
106
+ redirect,
107
+ usePathname,
108
+ useRouter,
109
+ getPathname,
110
+ } from './navigation';
111
+
112
+ export type { LinkProps } from './navigation';
113
+
114
+ // ─────────────────────────────────────────────────────────────────────────────
115
+ // Provider
116
+ // ─────────────────────────────────────────────────────────────────────────────
117
+
118
+ export { I18nProvider, NextIntlProvider } from './provider';
119
+
120
+ // ─────────────────────────────────────────────────────────────────────────────
121
+ // Request Config (for i18n/request.ts)
122
+ // ─────────────────────────────────────────────────────────────────────────────
123
+
124
+ export {
125
+ createRequestConfig,
126
+ type RequestConfigOptions,
127
+ } from './request';
128
+
129
+ // ─────────────────────────────────────────────────────────────────────────────
130
+ // Proxy (Next.js 16+)
131
+ // ─────────────────────────────────────────────────────────────────────────────
132
+
133
+ export {
134
+ createProxy,
135
+ createProxyFromConfig,
136
+ proxy,
137
+ config as proxyConfig,
138
+ } from './proxy';
139
+
140
+ // ─────────────────────────────────────────────────────────────────────────────
141
+ // Plugin (for next.config.ts) - import from '@djangocfg/nextjs/i18n/plugin'
142
+ // Not exported here to avoid SWC plugin issues with Turbopack
143
+ // ─────────────────────────────────────────────────────────────────────────────
144
+
145
+ // ─────────────────────────────────────────────────────────────────────────────
146
+ // Components
147
+ // ─────────────────────────────────────────────────────────────────────────────
148
+
149
+ export { LocaleSwitcher, type LocaleSwitcherProps } from './components';
@@ -0,0 +1,90 @@
1
+ /**
2
+ * i18n Navigation Utilities
3
+ *
4
+ * Provides locale-aware navigation components and functions
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * // In your app's i18n/navigation.ts
9
+ * import { createNavigation } from '@djangocfg/nextjs/i18n';
10
+ * import { routing } from './routing';
11
+ *
12
+ * export const { Link, redirect, usePathname, useRouter } = createNavigation(routing);
13
+ * ```
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * // Using in components
18
+ * import { Link, usePathname } from '@/i18n/navigation';
19
+ *
20
+ * function Nav() {
21
+ * const pathname = usePathname();
22
+ * return <Link href="/about">About</Link>;
23
+ * }
24
+ * ```
25
+ */
26
+
27
+ import { createNavigation as createNextIntlNavigation } from 'next-intl/navigation';
28
+ import { routing, createRouting } from './routing';
29
+ import type { I18nConfig } from './types';
30
+
31
+ // ─────────────────────────────────────────────────────────────────────────────
32
+ // Navigation Factory
33
+ // ─────────────────────────────────────────────────────────────────────────────
34
+
35
+ /**
36
+ * Create navigation utilities with custom routing
37
+ *
38
+ * Returns locale-aware versions of:
39
+ * - Link: Locale-prefixed links
40
+ * - redirect: Server-side redirect with locale
41
+ * - usePathname: Current pathname without locale prefix
42
+ * - useRouter: Router with locale-aware navigation
43
+ * - getPathname: Get pathname for a route
44
+ */
45
+ export function createNavigation(routingConfig?: ReturnType<typeof createRouting>) {
46
+ const config = routingConfig ?? routing;
47
+ return createNextIntlNavigation(config);
48
+ }
49
+
50
+ /**
51
+ * Create navigation from config options
52
+ */
53
+ export function createNavigationFromConfig(config: Partial<I18nConfig>) {
54
+ const routingConfig = createRouting(config);
55
+ return createNextIntlNavigation(routingConfig);
56
+ }
57
+
58
+ // ─────────────────────────────────────────────────────────────────────────────
59
+ // Default Navigation (using default routing)
60
+ // ─────────────────────────────────────────────────────────────────────────────
61
+
62
+ /**
63
+ * Default navigation utilities
64
+ * Use these directly or create custom ones with createNavigation()
65
+ */
66
+ export const {
67
+ Link,
68
+ redirect,
69
+ usePathname,
70
+ useRouter,
71
+ getPathname,
72
+ } = createNavigation();
73
+
74
+ // ─────────────────────────────────────────────────────────────────────────────
75
+ // Types
76
+ // ─────────────────────────────────────────────────────────────────────────────
77
+
78
+ /**
79
+ * Props for locale-aware Link component
80
+ */
81
+ export interface LinkProps {
82
+ /** Target href */
83
+ href: string;
84
+ /** Target locale (optional, defaults to current) */
85
+ locale?: string;
86
+ /** Children */
87
+ children?: React.ReactNode;
88
+ /** Additional props passed to Next.js Link */
89
+ [key: string]: unknown;
90
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * i18n Plugin for Next.js Configuration
3
+ *
4
+ * Wraps next-intl plugin for use with createBaseNextConfig
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * // next.config.ts
9
+ * import { createBaseNextConfig } from '@djangocfg/nextjs/config';
10
+ *
11
+ * export default createBaseNextConfig({
12
+ * i18n: {
13
+ * locales: ['en', 'ru', 'ko'],
14
+ * defaultLocale: 'en',
15
+ * },
16
+ * });
17
+ * ```
18
+ */
19
+
20
+ import createNextIntlPlugin from 'next-intl/plugin';
21
+ import type { NextConfig } from 'next';
22
+ import type { I18nPluginOptions } from './types';
23
+
24
+ export type { I18nPluginOptions } from './types';
25
+
26
+ // ─────────────────────────────────────────────────────────────────────────────
27
+ // Plugin Factory
28
+ // ─────────────────────────────────────────────────────────────────────────────
29
+
30
+ /**
31
+ * Create next-intl plugin wrapper
32
+ *
33
+ * @param options - i18n configuration options
34
+ * @returns Next.js config wrapper function
35
+ */
36
+ export function createI18nPlugin(options?: I18nPluginOptions) {
37
+ // Determine request config path
38
+ const requestConfigPath = options?.requestConfig
39
+ ?? './i18n/request.ts';
40
+
41
+ // Create next-intl plugin
42
+ const withNextIntl = createNextIntlPlugin(requestConfigPath);
43
+
44
+ return withNextIntl;
45
+ }
46
+
47
+ /**
48
+ * Apply i18n plugin to Next.js config
49
+ *
50
+ * @param config - Base Next.js config
51
+ * @param options - i18n options
52
+ * @returns Modified Next.js config
53
+ */
54
+ export function withI18n(
55
+ config: NextConfig,
56
+ options?: I18nPluginOptions
57
+ ): NextConfig {
58
+ const plugin = createI18nPlugin(options);
59
+ return plugin(config);
60
+ }
61
+
62
+ // ─────────────────────────────────────────────────────────────────────────────
63
+ // Export for direct use
64
+ // ─────────────────────────────────────────────────────────────────────────────
65
+
66
+ export { createNextIntlPlugin };