intor 2.0.3 → 2.1.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/dist/index.cjs +76 -34
- package/dist/index.d.cts +83 -18
- package/dist/index.d.ts +83 -18
- package/dist/index.js +76 -34
- package/dist/next/index.cjs +194 -71
- package/dist/next/index.d.cts +67 -24
- package/dist/next/index.d.ts +67 -24
- package/dist/next/index.js +193 -71
- package/dist/next/middleware/index.cjs +4 -1
- package/dist/next/middleware/index.d.cts +3 -3
- package/dist/next/middleware/index.d.ts +3 -3
- package/dist/next/middleware/index.js +4 -1
- package/dist/next/server/index.cjs +81 -39
- package/dist/next/server/index.d.cts +51 -19
- package/dist/next/server/index.d.ts +51 -19
- package/dist/next/server/index.js +80 -37
- package/package.json +2 -2
package/dist/next/index.d.cts
CHANGED
|
@@ -5,6 +5,7 @@ import { LinkProps as LinkProps$1 } from 'next/link';
|
|
|
5
5
|
import { Url } from 'next/dist/shared/lib/router/router';
|
|
6
6
|
import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
7
7
|
import { NavigateOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
8
|
+
import { RedirectType } from 'next/navigation';
|
|
8
9
|
|
|
9
10
|
type CookieRawOptions = {
|
|
10
11
|
/** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
|
|
@@ -143,60 +144,102 @@ type TranslateHandlersProviderProps = {
|
|
|
143
144
|
|
|
144
145
|
declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHandlersProviderProps) => React.JSX.Element;
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
declare const PREFIX_PLACEHOLDER = "{locale}";
|
|
148
|
+
|
|
149
|
+
type IfGen<Then, Else = never> = IntorGeneratedTypes extends void ? Else : Then;
|
|
150
|
+
type GenConfigKeys = IfGen<keyof IntorGeneratedTypes, string>;
|
|
151
|
+
type GenConfig<C extends GenConfigKeys = "__default__"> = IntorGeneratedTypes extends void ? {
|
|
152
|
+
Locales: string;
|
|
153
|
+
Messages: LocaleNamespaceMessages;
|
|
154
|
+
} : C extends keyof IntorGeneratedTypes ? {
|
|
155
|
+
Locales: IntorGeneratedTypes[C]["Locales"];
|
|
156
|
+
Messages: {
|
|
157
|
+
[K in IntorGeneratedTypes[C]["Locales"]]: IntorGeneratedTypes[C]["Messages"][typeof PREFIX_PLACEHOLDER];
|
|
158
|
+
};
|
|
159
|
+
} : never;
|
|
160
|
+
type GenMessages<C extends GenConfigKeys = "__default__"> = GenConfig<C>["Messages"];
|
|
161
|
+
type GenLocaleFallback = Locale;
|
|
162
|
+
type GenLocale<Config extends string = "__default__"> = Config extends keyof IntorGeneratedTypes ? IntorGeneratedTypes[Config]["Locales"] : GenLocaleFallback;
|
|
163
|
+
|
|
164
|
+
type PreKey<C extends GenConfigKeys = "__default__"> = NodeKeys<UnionLocaleMessages<GenMessages<C>>>;
|
|
165
|
+
interface TranslatorBaseProps<M> {
|
|
148
166
|
messages: M;
|
|
149
167
|
locale: LocaleKey<M>;
|
|
168
|
+
}
|
|
169
|
+
interface TranslatorClientProps<M> {
|
|
150
170
|
isLoading: boolean;
|
|
151
171
|
setLocale: (locale: LocaleKey<M>) => void;
|
|
152
172
|
}
|
|
153
|
-
type
|
|
154
|
-
hasKey: (key?: InferTranslatorKey<M
|
|
155
|
-
t: (key?: InferTranslatorKey<M
|
|
156
|
-
} &
|
|
157
|
-
type
|
|
158
|
-
hasKey: (key?:
|
|
159
|
-
t: (key?:
|
|
160
|
-
} &
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
type TranslatorInstance<M> = {
|
|
174
|
+
hasKey: (key?: IfGen<InferTranslatorKey<M>, string>, targetLocale?: LocaleKey<M> | undefined) => boolean;
|
|
175
|
+
t: <Result = string>(key?: IfGen<InferTranslatorKey<M>, string>, replacements?: Replacement | RichReplacement) => Result;
|
|
176
|
+
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
177
|
+
type ScopedTranslatorInstance<M, K extends string> = {
|
|
178
|
+
hasKey: (key?: IfGen<ScopedLeafKeys<M, K> & string, string>, targetLocale?: LocaleKey<M>) => boolean;
|
|
179
|
+
t: (key?: IfGen<ScopedLeafKeys<M, K> & string, string>, replacements?: Replacement | RichReplacement) => string;
|
|
180
|
+
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* React hook to access a ready-to-use translator instance in the client.
|
|
184
|
+
*
|
|
185
|
+
* - Provides `t`, `hasKey`, `messages`, `locale`, `isLoading` and `setLocale`.
|
|
186
|
+
* - Supports optional `preKey` to create a scoped translator for nested keys.
|
|
187
|
+
* - Can accept a generic type parameter `M` to strongly type your messages.
|
|
188
|
+
*/
|
|
189
|
+
declare function useTranslator<C extends GenConfigKeys = "__default__">(): TranslatorInstance<GenMessages<C>>;
|
|
190
|
+
declare function useTranslator<C extends GenConfigKeys = "__default__", K extends PreKey<C> = PreKey<C>>(preKey: IfGen<K, string>): ScopedTranslatorInstance<GenMessages<C>, K>;
|
|
165
191
|
|
|
166
192
|
interface LinkProps extends Omit<LinkProps$1, "href">, Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
167
193
|
href?: Url;
|
|
168
|
-
locale?:
|
|
194
|
+
locale?: GenLocale;
|
|
169
195
|
}
|
|
170
196
|
/**
|
|
171
|
-
* Localized Link component
|
|
197
|
+
* Localized Link component
|
|
172
198
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
199
|
+
* - Wraps Next.js Link and handles locale switching.
|
|
200
|
+
* - Full reload occurs only if the locale changes and requires it; otherwise updates context.
|
|
175
201
|
*/
|
|
176
202
|
declare const Link: ({ href, locale, children, onClick, ...props }: LinkProps) => React.JSX.Element;
|
|
177
203
|
|
|
178
204
|
/**
|
|
179
|
-
*
|
|
205
|
+
* usePathname hook
|
|
180
206
|
*
|
|
181
|
-
*
|
|
182
|
-
* then prefixes it with the current locale
|
|
183
|
-
* based on the app's configuration and locale context.
|
|
207
|
+
* Wraps Next.js usePathname and returns the current pathname prefixed with the active locale.
|
|
184
208
|
*/
|
|
185
209
|
declare const usePathname: () => string;
|
|
186
210
|
|
|
211
|
+
/**
|
|
212
|
+
* useRouter hook.
|
|
213
|
+
*
|
|
214
|
+
* Wraps Next.js useRouter and provides push/replace methods that automatically switch locale.
|
|
215
|
+
*/
|
|
187
216
|
declare const useRouter: () => {
|
|
188
217
|
back(): void;
|
|
189
218
|
forward(): void;
|
|
190
219
|
refresh(): void;
|
|
191
220
|
prefetch(href: string, options?: next_dist_shared_lib_app_router_context_shared_runtime.PrefetchOptions): void;
|
|
192
221
|
push: (href: string, options?: NavigateOptions & {
|
|
193
|
-
locale?:
|
|
222
|
+
locale?: GenLocale;
|
|
194
223
|
}) => void;
|
|
195
224
|
replace: (href: string, options?: NavigateOptions & {
|
|
196
225
|
locale?: Locale;
|
|
197
226
|
}) => void;
|
|
198
227
|
};
|
|
199
228
|
|
|
229
|
+
/**
|
|
230
|
+
* redirect utility.
|
|
231
|
+
*
|
|
232
|
+
* - Wraps Next.js redirect and applies locale-aware navigation.
|
|
233
|
+
* - Automatically prefixes the pathname with the correct locale.
|
|
234
|
+
* - External URLs are redirected directly without modification.
|
|
235
|
+
*/
|
|
236
|
+
declare const redirect: ({ config, locale, url, type, }: {
|
|
237
|
+
config: IntorResolvedConfig;
|
|
238
|
+
locale?: GenLocale;
|
|
239
|
+
url: string;
|
|
240
|
+
type?: RedirectType | undefined;
|
|
241
|
+
}) => Promise<never>;
|
|
242
|
+
|
|
200
243
|
declare const PATHNAME_HEADER_NAME = "x-intor-pathname";
|
|
201
244
|
|
|
202
|
-
export { IntorProvider, type IntorProviderProps, Link, PATHNAME_HEADER_NAME, TranslateHandlersProvider, type TranslateHandlersProviderProps,
|
|
245
|
+
export { IntorProvider, type IntorProviderProps, Link, PATHNAME_HEADER_NAME, TranslateHandlersProvider, type TranslateHandlersProviderProps, redirect, usePathname, useRouter, useTranslator };
|
package/dist/next/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { LinkProps as LinkProps$1 } from 'next/link';
|
|
|
5
5
|
import { Url } from 'next/dist/shared/lib/router/router';
|
|
6
6
|
import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
7
7
|
import { NavigateOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
8
|
+
import { RedirectType } from 'next/navigation';
|
|
8
9
|
|
|
9
10
|
type CookieRawOptions = {
|
|
10
11
|
/** Completely disable cookie usage (no read, no write, no lookup by name) - default: false */
|
|
@@ -143,60 +144,102 @@ type TranslateHandlersProviderProps = {
|
|
|
143
144
|
|
|
144
145
|
declare const TranslateHandlersProvider: ({ children, handlers, }: TranslateHandlersProviderProps) => React.JSX.Element;
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
declare const PREFIX_PLACEHOLDER = "{locale}";
|
|
148
|
+
|
|
149
|
+
type IfGen<Then, Else = never> = IntorGeneratedTypes extends void ? Else : Then;
|
|
150
|
+
type GenConfigKeys = IfGen<keyof IntorGeneratedTypes, string>;
|
|
151
|
+
type GenConfig<C extends GenConfigKeys = "__default__"> = IntorGeneratedTypes extends void ? {
|
|
152
|
+
Locales: string;
|
|
153
|
+
Messages: LocaleNamespaceMessages;
|
|
154
|
+
} : C extends keyof IntorGeneratedTypes ? {
|
|
155
|
+
Locales: IntorGeneratedTypes[C]["Locales"];
|
|
156
|
+
Messages: {
|
|
157
|
+
[K in IntorGeneratedTypes[C]["Locales"]]: IntorGeneratedTypes[C]["Messages"][typeof PREFIX_PLACEHOLDER];
|
|
158
|
+
};
|
|
159
|
+
} : never;
|
|
160
|
+
type GenMessages<C extends GenConfigKeys = "__default__"> = GenConfig<C>["Messages"];
|
|
161
|
+
type GenLocaleFallback = Locale;
|
|
162
|
+
type GenLocale<Config extends string = "__default__"> = Config extends keyof IntorGeneratedTypes ? IntorGeneratedTypes[Config]["Locales"] : GenLocaleFallback;
|
|
163
|
+
|
|
164
|
+
type PreKey<C extends GenConfigKeys = "__default__"> = NodeKeys<UnionLocaleMessages<GenMessages<C>>>;
|
|
165
|
+
interface TranslatorBaseProps<M> {
|
|
148
166
|
messages: M;
|
|
149
167
|
locale: LocaleKey<M>;
|
|
168
|
+
}
|
|
169
|
+
interface TranslatorClientProps<M> {
|
|
150
170
|
isLoading: boolean;
|
|
151
171
|
setLocale: (locale: LocaleKey<M>) => void;
|
|
152
172
|
}
|
|
153
|
-
type
|
|
154
|
-
hasKey: (key?: InferTranslatorKey<M
|
|
155
|
-
t: (key?: InferTranslatorKey<M
|
|
156
|
-
} &
|
|
157
|
-
type
|
|
158
|
-
hasKey: (key?:
|
|
159
|
-
t: (key?:
|
|
160
|
-
} &
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
type TranslatorInstance<M> = {
|
|
174
|
+
hasKey: (key?: IfGen<InferTranslatorKey<M>, string>, targetLocale?: LocaleKey<M> | undefined) => boolean;
|
|
175
|
+
t: <Result = string>(key?: IfGen<InferTranslatorKey<M>, string>, replacements?: Replacement | RichReplacement) => Result;
|
|
176
|
+
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
177
|
+
type ScopedTranslatorInstance<M, K extends string> = {
|
|
178
|
+
hasKey: (key?: IfGen<ScopedLeafKeys<M, K> & string, string>, targetLocale?: LocaleKey<M>) => boolean;
|
|
179
|
+
t: (key?: IfGen<ScopedLeafKeys<M, K> & string, string>, replacements?: Replacement | RichReplacement) => string;
|
|
180
|
+
} & TranslatorBaseProps<M> & TranslatorClientProps<M>;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* React hook to access a ready-to-use translator instance in the client.
|
|
184
|
+
*
|
|
185
|
+
* - Provides `t`, `hasKey`, `messages`, `locale`, `isLoading` and `setLocale`.
|
|
186
|
+
* - Supports optional `preKey` to create a scoped translator for nested keys.
|
|
187
|
+
* - Can accept a generic type parameter `M` to strongly type your messages.
|
|
188
|
+
*/
|
|
189
|
+
declare function useTranslator<C extends GenConfigKeys = "__default__">(): TranslatorInstance<GenMessages<C>>;
|
|
190
|
+
declare function useTranslator<C extends GenConfigKeys = "__default__", K extends PreKey<C> = PreKey<C>>(preKey: IfGen<K, string>): ScopedTranslatorInstance<GenMessages<C>, K>;
|
|
165
191
|
|
|
166
192
|
interface LinkProps extends Omit<LinkProps$1, "href">, Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
|
|
167
193
|
href?: Url;
|
|
168
|
-
locale?:
|
|
194
|
+
locale?: GenLocale;
|
|
169
195
|
}
|
|
170
196
|
/**
|
|
171
|
-
* Localized Link component
|
|
197
|
+
* Localized Link component
|
|
172
198
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
199
|
+
* - Wraps Next.js Link and handles locale switching.
|
|
200
|
+
* - Full reload occurs only if the locale changes and requires it; otherwise updates context.
|
|
175
201
|
*/
|
|
176
202
|
declare const Link: ({ href, locale, children, onClick, ...props }: LinkProps) => React.JSX.Element;
|
|
177
203
|
|
|
178
204
|
/**
|
|
179
|
-
*
|
|
205
|
+
* usePathname hook
|
|
180
206
|
*
|
|
181
|
-
*
|
|
182
|
-
* then prefixes it with the current locale
|
|
183
|
-
* based on the app's configuration and locale context.
|
|
207
|
+
* Wraps Next.js usePathname and returns the current pathname prefixed with the active locale.
|
|
184
208
|
*/
|
|
185
209
|
declare const usePathname: () => string;
|
|
186
210
|
|
|
211
|
+
/**
|
|
212
|
+
* useRouter hook.
|
|
213
|
+
*
|
|
214
|
+
* Wraps Next.js useRouter and provides push/replace methods that automatically switch locale.
|
|
215
|
+
*/
|
|
187
216
|
declare const useRouter: () => {
|
|
188
217
|
back(): void;
|
|
189
218
|
forward(): void;
|
|
190
219
|
refresh(): void;
|
|
191
220
|
prefetch(href: string, options?: next_dist_shared_lib_app_router_context_shared_runtime.PrefetchOptions): void;
|
|
192
221
|
push: (href: string, options?: NavigateOptions & {
|
|
193
|
-
locale?:
|
|
222
|
+
locale?: GenLocale;
|
|
194
223
|
}) => void;
|
|
195
224
|
replace: (href: string, options?: NavigateOptions & {
|
|
196
225
|
locale?: Locale;
|
|
197
226
|
}) => void;
|
|
198
227
|
};
|
|
199
228
|
|
|
229
|
+
/**
|
|
230
|
+
* redirect utility.
|
|
231
|
+
*
|
|
232
|
+
* - Wraps Next.js redirect and applies locale-aware navigation.
|
|
233
|
+
* - Automatically prefixes the pathname with the correct locale.
|
|
234
|
+
* - External URLs are redirected directly without modification.
|
|
235
|
+
*/
|
|
236
|
+
declare const redirect: ({ config, locale, url, type, }: {
|
|
237
|
+
config: IntorResolvedConfig;
|
|
238
|
+
locale?: GenLocale;
|
|
239
|
+
url: string;
|
|
240
|
+
type?: RedirectType | undefined;
|
|
241
|
+
}) => Promise<never>;
|
|
242
|
+
|
|
200
243
|
declare const PATHNAME_HEADER_NAME = "x-intor-pathname";
|
|
201
244
|
|
|
202
|
-
export { IntorProvider, type IntorProviderProps, Link, PATHNAME_HEADER_NAME, TranslateHandlersProvider, type TranslateHandlersProviderProps,
|
|
245
|
+
export { IntorProvider, type IntorProviderProps, Link, PATHNAME_HEADER_NAME, TranslateHandlersProvider, type TranslateHandlersProviderProps, redirect, usePathname, useRouter, useTranslator };
|
package/dist/next/index.js
CHANGED
|
@@ -3,8 +3,9 @@ import { logry } from 'logry';
|
|
|
3
3
|
import Keyv from 'keyv';
|
|
4
4
|
import { Translator } from 'intor-translator';
|
|
5
5
|
import NextLink from 'next/link';
|
|
6
|
-
import { usePathname as usePathname$1, useRouter as useRouter$1 } from 'next/navigation';
|
|
7
6
|
import { formatUrl } from 'next/dist/shared/lib/router/utils/format-url';
|
|
7
|
+
import { usePathname as usePathname$1, useRouter as useRouter$1, redirect as redirect$1 } from 'next/navigation';
|
|
8
|
+
import { cookies, headers } from 'next/headers';
|
|
8
9
|
|
|
9
10
|
// src/adapters/next/contexts/intor-provider/intor-provider.tsx
|
|
10
11
|
var ConfigContext = React7.createContext(void 0);
|
|
@@ -104,13 +105,19 @@ var DEFAULT_FORMATTER_CONFIG = {
|
|
|
104
105
|
};
|
|
105
106
|
function getLogger({
|
|
106
107
|
id,
|
|
107
|
-
formatterConfig
|
|
108
|
+
formatterConfig,
|
|
109
|
+
preset,
|
|
108
110
|
...options
|
|
109
111
|
}) {
|
|
110
112
|
const pool = getGlobalLoggerPool();
|
|
111
113
|
let logger = pool.get(id);
|
|
112
114
|
if (!logger) {
|
|
113
|
-
logger = logry({
|
|
115
|
+
logger = logry({
|
|
116
|
+
id,
|
|
117
|
+
formatterConfig: !formatterConfig && !preset ? DEFAULT_FORMATTER_CONFIG : formatterConfig,
|
|
118
|
+
preset,
|
|
119
|
+
...options
|
|
120
|
+
});
|
|
114
121
|
pool.set(id, logger);
|
|
115
122
|
if (pool.size > 1e3) {
|
|
116
123
|
const keys = Array.from(pool.keys());
|
|
@@ -211,6 +218,55 @@ var resolveNamespaces = ({
|
|
|
211
218
|
}
|
|
212
219
|
};
|
|
213
220
|
|
|
221
|
+
// src/shared/utils/locale/normalize-locale.ts
|
|
222
|
+
var normalizeLocale = (locale = "", supportedLocales = []) => {
|
|
223
|
+
if (!locale || supportedLocales.length === 0) return;
|
|
224
|
+
const toCanonical = (input) => {
|
|
225
|
+
try {
|
|
226
|
+
return Intl.getCanonicalLocales(input)[0]?.toLowerCase();
|
|
227
|
+
} catch {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const canonicalLocale = toCanonical(locale);
|
|
232
|
+
if (!canonicalLocale) return;
|
|
233
|
+
const supportedCanonicalMap = /* @__PURE__ */ new Map();
|
|
234
|
+
for (const l of supportedLocales) {
|
|
235
|
+
const normalized = toCanonical(l);
|
|
236
|
+
if (normalized) {
|
|
237
|
+
supportedCanonicalMap.set(normalized, l);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (supportedCanonicalMap.has(canonicalLocale)) {
|
|
241
|
+
return supportedCanonicalMap.get(canonicalLocale);
|
|
242
|
+
}
|
|
243
|
+
const baseLang = canonicalLocale.split("-")[0];
|
|
244
|
+
for (const [key, original] of supportedCanonicalMap) {
|
|
245
|
+
const supportedBase = key.split("-")[0];
|
|
246
|
+
if (supportedBase === baseLang) {
|
|
247
|
+
return original;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/shared/utils/locale/resolve-preferred-locale.ts
|
|
254
|
+
var resolvePreferredLocale = (acceptLanguageHeader, supportedLocales) => {
|
|
255
|
+
if (!acceptLanguageHeader || !supportedLocales || supportedLocales.length === 0) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const supportedLocalesSet = new Set(supportedLocales);
|
|
259
|
+
const preferred = acceptLanguageHeader.split(",").map((part) => {
|
|
260
|
+
const [lang, qValue] = part.split(";");
|
|
261
|
+
const q = qValue ? parseFloat(qValue.split("=")[1]) : 1;
|
|
262
|
+
if (isNaN(q)) {
|
|
263
|
+
return { lang: lang.trim(), q: 0 };
|
|
264
|
+
}
|
|
265
|
+
return { lang: lang.trim(), q };
|
|
266
|
+
}).sort((a, b) => b.q - a.q).find(({ lang }) => supportedLocalesSet.has(lang))?.lang;
|
|
267
|
+
return preferred;
|
|
268
|
+
};
|
|
269
|
+
|
|
214
270
|
// src/shared/utils/pathname/normalize-pathname.ts
|
|
215
271
|
var normalizePathname = (rawPathname, options = {}) => {
|
|
216
272
|
const length = rawPathname.length;
|
|
@@ -308,13 +364,13 @@ var fetchMessages = async ({
|
|
|
308
364
|
const params = new URLSearchParams(searchParams);
|
|
309
365
|
params.append("locale", locale);
|
|
310
366
|
const url = `${apiUrl}?${params.toString()}`;
|
|
311
|
-
const
|
|
367
|
+
const headers2 = {
|
|
312
368
|
"Content-Type": "application/json",
|
|
313
369
|
...apiHeaders
|
|
314
370
|
};
|
|
315
371
|
const response = await fetch(url, {
|
|
316
372
|
method: "GET",
|
|
317
|
-
headers,
|
|
373
|
+
headers: headers2,
|
|
318
374
|
cache: "no-store"
|
|
319
375
|
});
|
|
320
376
|
if (!response.ok) {
|
|
@@ -394,7 +450,10 @@ var loadApiMessages = async ({
|
|
|
394
450
|
logger.warn("No apiUrl provided. Skipping fetch.");
|
|
395
451
|
return;
|
|
396
452
|
}
|
|
397
|
-
|
|
453
|
+
let pool;
|
|
454
|
+
if (cache.enabled) {
|
|
455
|
+
pool = getGlobalMessagesPool();
|
|
456
|
+
}
|
|
398
457
|
const key = normalizeCacheKey([
|
|
399
458
|
loggerOptions.id,
|
|
400
459
|
basePath,
|
|
@@ -403,7 +462,7 @@ var loadApiMessages = async ({
|
|
|
403
462
|
[...namespaces ?? []].sort().join(",")
|
|
404
463
|
]);
|
|
405
464
|
if (cache.enabled && key) {
|
|
406
|
-
const cached = await pool
|
|
465
|
+
const cached = await pool?.get(key);
|
|
407
466
|
if (cached) {
|
|
408
467
|
logger.debug("Messages cache hit.", { key });
|
|
409
468
|
return cached;
|
|
@@ -419,7 +478,7 @@ var loadApiMessages = async ({
|
|
|
419
478
|
});
|
|
420
479
|
if (messages) {
|
|
421
480
|
if (cache.enabled && key) {
|
|
422
|
-
await pool
|
|
481
|
+
await pool?.set(key, messages, cache.ttl);
|
|
423
482
|
}
|
|
424
483
|
return messages;
|
|
425
484
|
}
|
|
@@ -437,7 +496,7 @@ var loadApiMessages = async ({
|
|
|
437
496
|
searchParams: decodeURIComponent(searchParams.toString())
|
|
438
497
|
});
|
|
439
498
|
if (cache.enabled && key) {
|
|
440
|
-
await pool
|
|
499
|
+
await pool?.set(key, fallbackResult.messages, cache.ttl);
|
|
441
500
|
}
|
|
442
501
|
return fallbackResult.messages;
|
|
443
502
|
}
|
|
@@ -543,8 +602,8 @@ var useInitLocaleCookie = ({
|
|
|
543
602
|
if (typeof document === "undefined") return;
|
|
544
603
|
const { cookie, routing } = config;
|
|
545
604
|
const { firstVisit } = routing;
|
|
546
|
-
const
|
|
547
|
-
const isCookieExists =
|
|
605
|
+
const cookies2 = document.cookie.split(";").map((c) => c.trim());
|
|
606
|
+
const isCookieExists = cookies2.some((c) => c.startsWith(`${cookie.name}=`));
|
|
548
607
|
if (isCookieExists) return;
|
|
549
608
|
if (!firstVisit.redirect) return;
|
|
550
609
|
if (cookie.disabled || !cookie.autoSetCookie) return;
|
|
@@ -663,11 +722,11 @@ var IntorProvider = ({
|
|
|
663
722
|
return /* @__PURE__ */ React7.createElement(ConfigProvider, { value: { config, pathname } }, /* @__PURE__ */ React7.createElement(MessagesProvider, { value: { messages } }, /* @__PURE__ */ React7.createElement(LocaleProvider, { value: { initialLocale } }, /* @__PURE__ */ React7.createElement(TranslatorProvider, null, children))));
|
|
664
723
|
};
|
|
665
724
|
|
|
666
|
-
// src/adapters/next/hooks/use-
|
|
667
|
-
function
|
|
725
|
+
// src/adapters/next/hooks/use-translator/use-translator.ts
|
|
726
|
+
function useTranslator2(preKey) {
|
|
668
727
|
const { translator } = useTranslator();
|
|
669
728
|
const { setLocale } = useLocale();
|
|
670
|
-
const
|
|
729
|
+
const props = {
|
|
671
730
|
messages: translator.messages,
|
|
672
731
|
locale: translator.locale,
|
|
673
732
|
isLoading: translator.isLoading,
|
|
@@ -675,10 +734,10 @@ function useIntor(preKey) {
|
|
|
675
734
|
};
|
|
676
735
|
if (preKey) {
|
|
677
736
|
const { hasKey, t } = translator.scoped(preKey);
|
|
678
|
-
return { ...
|
|
737
|
+
return { ...props, hasKey, t };
|
|
679
738
|
} else {
|
|
680
739
|
const { hasKey, t } = translator;
|
|
681
|
-
return { ...
|
|
740
|
+
return { ...props, hasKey, t };
|
|
682
741
|
}
|
|
683
742
|
}
|
|
684
743
|
|
|
@@ -740,10 +799,7 @@ var localizePathname = ({
|
|
|
740
799
|
};
|
|
741
800
|
};
|
|
742
801
|
|
|
743
|
-
// src/adapters/next/
|
|
744
|
-
var shouldFullReload = (loaderOptions) => {
|
|
745
|
-
return loaderOptions?.type === "import" || loaderOptions?.type === "api" && loaderOptions.fullReload === true;
|
|
746
|
-
};
|
|
802
|
+
// src/adapters/next/navigation/use-pathname.ts
|
|
747
803
|
var usePathname = () => {
|
|
748
804
|
const { config } = useConfig();
|
|
749
805
|
const { locale } = useLocale();
|
|
@@ -755,75 +811,90 @@ var usePathname = () => {
|
|
|
755
811
|
});
|
|
756
812
|
return localePrefixedPathname;
|
|
757
813
|
};
|
|
758
|
-
|
|
759
|
-
|
|
814
|
+
|
|
815
|
+
// src/adapters/next/navigation/utils/should-full-reload.ts
|
|
816
|
+
var shouldFullReload = ({
|
|
817
|
+
config,
|
|
818
|
+
targetPathname,
|
|
760
819
|
locale,
|
|
761
|
-
|
|
762
|
-
onClick,
|
|
763
|
-
...props
|
|
820
|
+
currentLocale
|
|
764
821
|
}) => {
|
|
822
|
+
const loader = config.loader;
|
|
823
|
+
if (!loader || !loader.type) return false;
|
|
824
|
+
if (loader.type === "api" && !loader.fullReload) return false;
|
|
825
|
+
const { maybeLocale, isLocalePrefixed } = extractPathname({
|
|
826
|
+
config,
|
|
827
|
+
pathname: targetPathname
|
|
828
|
+
});
|
|
829
|
+
const isDifferentLocale = locale && locale !== currentLocale || isLocalePrefixed && maybeLocale !== currentLocale;
|
|
830
|
+
return isDifferentLocale ? true : false;
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
// src/adapters/next/navigation/utils/use-locale-switch.ts
|
|
834
|
+
var useLocaleSwitch = () => {
|
|
765
835
|
const { config } = useConfig();
|
|
766
836
|
const { locale: currentLocale, setLocale } = useLocale();
|
|
767
|
-
const targetLocale = locale || currentLocale;
|
|
768
837
|
const pathname = usePathname();
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
locale
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
838
|
+
const resolveHref = ({
|
|
839
|
+
href,
|
|
840
|
+
locale
|
|
841
|
+
}) => {
|
|
842
|
+
const isLocaleValid = locale && config.supportedLocales?.includes(locale);
|
|
843
|
+
const targetLocale = isLocaleValid ? locale : currentLocale;
|
|
844
|
+
const targetPathname = href ?? pathname;
|
|
845
|
+
const isExternal = targetPathname.startsWith("http");
|
|
846
|
+
const resolvedHref = !isExternal ? localizePathname({
|
|
847
|
+
config,
|
|
848
|
+
pathname: targetPathname,
|
|
849
|
+
locale: targetLocale
|
|
850
|
+
}).localePrefixedPathname : targetPathname;
|
|
851
|
+
return { resolvedHref, isExternal, targetLocale, targetPathname };
|
|
852
|
+
};
|
|
853
|
+
const switchLocale = ({
|
|
854
|
+
href,
|
|
855
|
+
locale
|
|
856
|
+
}) => {
|
|
857
|
+
const { resolvedHref, isExternal, targetLocale, targetPathname } = resolveHref({ href, locale });
|
|
858
|
+
if (isExternal) return;
|
|
859
|
+
if (shouldFullReload({ config, targetPathname, locale, currentLocale })) {
|
|
779
860
|
setLocaleCookieBrowser({ cookie: config.cookie, locale: targetLocale });
|
|
780
861
|
window.location.href = resolvedHref;
|
|
781
862
|
return;
|
|
782
863
|
} else {
|
|
783
864
|
setLocale(targetLocale);
|
|
784
865
|
}
|
|
866
|
+
return resolvedHref;
|
|
867
|
+
};
|
|
868
|
+
return { resolveHref, switchLocale };
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// src/adapters/next/navigation/link.tsx
|
|
872
|
+
var Link = ({
|
|
873
|
+
href,
|
|
874
|
+
locale,
|
|
875
|
+
children,
|
|
876
|
+
onClick,
|
|
877
|
+
...props
|
|
878
|
+
}) => {
|
|
879
|
+
const formatted = typeof href === "string" ? href : href ? formatUrl(href) : void 0;
|
|
880
|
+
const { resolveHref, switchLocale } = useLocaleSwitch();
|
|
881
|
+
const { resolvedHref } = resolveHref({ href: formatted, locale });
|
|
882
|
+
const handleClick = (e) => {
|
|
883
|
+
onClick?.(e);
|
|
884
|
+
switchLocale({ href: formatted, locale });
|
|
785
885
|
};
|
|
786
886
|
return /* @__PURE__ */ React7.createElement(NextLink, { href: resolvedHref, onClick: handleClick, ...props }, children);
|
|
787
887
|
};
|
|
788
888
|
var useRouter = () => {
|
|
789
|
-
const { config } = useConfig();
|
|
790
|
-
const { locale: currentLocale, setLocale } = useLocale();
|
|
791
889
|
const { push, replace, ...rest } = useRouter$1();
|
|
890
|
+
const { switchLocale } = useLocaleSwitch();
|
|
792
891
|
const pushWithLocale = (href, options) => {
|
|
793
|
-
const
|
|
794
|
-
if (options
|
|
795
|
-
const { localePrefixedPathname } = localizePathname({
|
|
796
|
-
config,
|
|
797
|
-
pathname: href,
|
|
798
|
-
locale: targetLocale
|
|
799
|
-
});
|
|
800
|
-
href = localePrefixedPathname;
|
|
801
|
-
}
|
|
802
|
-
if (shouldFullReload(config.loader)) {
|
|
803
|
-
window.location.href = href;
|
|
804
|
-
return;
|
|
805
|
-
} else {
|
|
806
|
-
setLocale(targetLocale);
|
|
807
|
-
}
|
|
808
|
-
push(href, options);
|
|
892
|
+
const resolvedHref = switchLocale({ href, locale: options?.locale });
|
|
893
|
+
if (resolvedHref) push(resolvedHref, options);
|
|
809
894
|
};
|
|
810
895
|
const replaceWithLocale = (href, options) => {
|
|
811
|
-
const
|
|
812
|
-
if (options
|
|
813
|
-
const { localePrefixedPathname } = localizePathname({
|
|
814
|
-
config,
|
|
815
|
-
pathname: href,
|
|
816
|
-
locale: targetLocale
|
|
817
|
-
});
|
|
818
|
-
href = localePrefixedPathname;
|
|
819
|
-
}
|
|
820
|
-
if (shouldFullReload(config.loader)) {
|
|
821
|
-
window.location.href = href;
|
|
822
|
-
return;
|
|
823
|
-
} else {
|
|
824
|
-
setLocale(targetLocale);
|
|
825
|
-
}
|
|
826
|
-
replace(href, options);
|
|
896
|
+
const resolvedHref = switchLocale({ href, locale: options?.locale });
|
|
897
|
+
if (resolvedHref) replace(resolvedHref, options);
|
|
827
898
|
};
|
|
828
899
|
return {
|
|
829
900
|
push: pushWithLocale,
|
|
@@ -835,4 +906,55 @@ var useRouter = () => {
|
|
|
835
906
|
// src/adapters/next/shared/constants/pathname-header-name.ts
|
|
836
907
|
var PATHNAME_HEADER_NAME = "x-intor-pathname";
|
|
837
908
|
|
|
838
|
-
|
|
909
|
+
// src/adapters/next/server/get-i18n-context.ts
|
|
910
|
+
var getI18nContext = async (config) => {
|
|
911
|
+
const baseLogger = getLogger({ id: config.id, ...config.logger });
|
|
912
|
+
const logger = baseLogger.child({ scope: "next-adapter" });
|
|
913
|
+
const cookiesStore = await cookies();
|
|
914
|
+
const headersStore = await headers();
|
|
915
|
+
const { defaultLocale, supportedLocales = [], cookie, routing } = config;
|
|
916
|
+
let locale;
|
|
917
|
+
if (!cookie.disabled) {
|
|
918
|
+
const localeFromCookie = cookiesStore.get(cookie.name)?.value;
|
|
919
|
+
locale = normalizeLocale(localeFromCookie, supportedLocales);
|
|
920
|
+
if (locale) {
|
|
921
|
+
logger.trace("Locale retrieved from cookie.", { locale });
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (!locale && routing.firstVisit.localeSource === "browser") {
|
|
925
|
+
const aLHeader = headersStore.get("accept-language") || void 0;
|
|
926
|
+
const preferredLocale = resolvePreferredLocale(aLHeader, supportedLocales);
|
|
927
|
+
locale = normalizeLocale(preferredLocale, supportedLocales);
|
|
928
|
+
logger.trace("Locale retrieved from header.", { locale });
|
|
929
|
+
}
|
|
930
|
+
const pathname = headersStore.get(PATHNAME_HEADER_NAME);
|
|
931
|
+
if (pathname) {
|
|
932
|
+
logger.trace("Pathname retrieved from header.", { pathname });
|
|
933
|
+
}
|
|
934
|
+
return {
|
|
935
|
+
locale: locale || defaultLocale,
|
|
936
|
+
pathname: pathname || ""
|
|
937
|
+
};
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
// src/adapters/next/navigation/redirect.ts
|
|
941
|
+
var redirect = async ({
|
|
942
|
+
config,
|
|
943
|
+
locale,
|
|
944
|
+
url,
|
|
945
|
+
type
|
|
946
|
+
}) => {
|
|
947
|
+
if (url.startsWith("http")) {
|
|
948
|
+
redirect$1(url);
|
|
949
|
+
}
|
|
950
|
+
const isLocaleValid = locale && config.supportedLocales?.includes(locale);
|
|
951
|
+
const { locale: detectedLocale } = await getI18nContext(config);
|
|
952
|
+
const { localePrefixedPathname } = localizePathname({
|
|
953
|
+
config,
|
|
954
|
+
pathname: url,
|
|
955
|
+
locale: isLocaleValid ? locale : detectedLocale
|
|
956
|
+
});
|
|
957
|
+
redirect$1(localePrefixedPathname, type);
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
export { IntorProvider, Link, PATHNAME_HEADER_NAME, TranslateHandlersProvider, redirect, usePathname, useRouter, useTranslator2 as useTranslator };
|
|
@@ -266,7 +266,10 @@ var createResponse = ({
|
|
|
266
266
|
override
|
|
267
267
|
});
|
|
268
268
|
}
|
|
269
|
-
const finalResponse = setPathnameHeader({
|
|
269
|
+
const finalResponse = setPathnameHeader({
|
|
270
|
+
request,
|
|
271
|
+
response
|
|
272
|
+
});
|
|
270
273
|
return finalResponse;
|
|
271
274
|
};
|
|
272
275
|
var determineInitialLocale = async (config) => {
|