@intlayer/next-intl 9.4.4 → 9.5.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 +0 -2
- package/dist/cjs/plugin/index.cjs +36 -11
- package/dist/cjs/plugin/index.cjs.map +1 -1
- package/dist/cjs/react-server/helpers.cjs +20 -0
- package/dist/cjs/react-server/helpers.cjs.map +1 -0
- package/dist/cjs/react-server/index.cjs +61 -0
- package/dist/cjs/react-server/resolveLocale.cjs +19 -0
- package/dist/cjs/react-server/resolveLocale.cjs.map +1 -0
- package/dist/cjs/react-server/useDictionary.cjs +23 -0
- package/dist/cjs/react-server/useDictionary.cjs.map +1 -0
- package/dist/cjs/react-server/useDictionaryDynamic.cjs +19 -0
- package/dist/cjs/react-server/useDictionaryDynamic.cjs.map +1 -0
- package/dist/cjs/react-server/useLocale.cjs +13 -0
- package/dist/cjs/react-server/useLocale.cjs.map +1 -0
- package/dist/cjs/react-server/useTranslations.cjs +42 -0
- package/dist/cjs/react-server/useTranslations.cjs.map +1 -0
- package/dist/cjs/server/react/helpers.cjs +23 -0
- package/dist/cjs/server/react/helpers.cjs.map +1 -0
- package/dist/cjs/server/react/index.cjs +61 -0
- package/dist/cjs/server/react/resolveLocale.cjs +27 -0
- package/dist/cjs/server/react/resolveLocale.cjs.map +1 -0
- package/dist/cjs/server/react/useDictionary.cjs +23 -0
- package/dist/cjs/server/react/useDictionary.cjs.map +1 -0
- package/dist/cjs/server/react/useDictionaryDynamic.cjs +19 -0
- package/dist/cjs/server/react/useDictionaryDynamic.cjs.map +1 -0
- package/dist/cjs/server/react/useLocale.cjs +13 -0
- package/dist/cjs/server/react/useLocale.cjs.map +1 -0
- package/dist/cjs/server/react/useTranslations.cjs +42 -0
- package/dist/cjs/server/react/useTranslations.cjs.map +1 -0
- package/dist/esm/plugin/index.mjs +37 -12
- package/dist/esm/plugin/index.mjs.map +1 -1
- package/dist/esm/react-server/helpers.mjs +17 -0
- package/dist/esm/react-server/helpers.mjs.map +1 -0
- package/dist/esm/react-server/index.mjs +10 -0
- package/dist/esm/react-server/resolveLocale.mjs +18 -0
- package/dist/esm/react-server/resolveLocale.mjs.map +1 -0
- package/dist/esm/react-server/useDictionary.mjs +22 -0
- package/dist/esm/react-server/useDictionary.mjs.map +1 -0
- package/dist/esm/react-server/useDictionaryDynamic.mjs +18 -0
- package/dist/esm/react-server/useDictionaryDynamic.mjs.map +1 -0
- package/dist/esm/react-server/useLocale.mjs +12 -0
- package/dist/esm/react-server/useLocale.mjs.map +1 -0
- package/dist/esm/react-server/useTranslations.mjs +41 -0
- package/dist/esm/react-server/useTranslations.mjs.map +1 -0
- package/dist/esm/server/react/helpers.mjs +20 -0
- package/dist/esm/server/react/helpers.mjs.map +1 -0
- package/dist/esm/server/react/index.mjs +10 -0
- package/dist/esm/server/react/resolveLocale.mjs +26 -0
- package/dist/esm/server/react/resolveLocale.mjs.map +1 -0
- package/dist/esm/server/react/useDictionary.mjs +22 -0
- package/dist/esm/server/react/useDictionary.mjs.map +1 -0
- package/dist/esm/server/react/useDictionaryDynamic.mjs +18 -0
- package/dist/esm/server/react/useDictionaryDynamic.mjs.map +1 -0
- package/dist/esm/server/react/useLocale.mjs +12 -0
- package/dist/esm/server/react/useLocale.mjs.map +1 -0
- package/dist/esm/server/react/useTranslations.mjs +41 -0
- package/dist/esm/server/react/useTranslations.mjs.map +1 -0
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/react-server/helpers.d.ts +12 -0
- package/dist/types/react-server/helpers.d.ts.map +1 -0
- package/dist/types/react-server/index.d.ts +9 -0
- package/dist/types/react-server/resolveLocale.d.ts +14 -0
- package/dist/types/react-server/resolveLocale.d.ts.map +1 -0
- package/dist/types/react-server/useDictionary.d.ts +24 -0
- package/dist/types/react-server/useDictionary.d.ts.map +1 -0
- package/dist/types/react-server/useDictionaryDynamic.d.ts +15 -0
- package/dist/types/react-server/useDictionaryDynamic.d.ts.map +1 -0
- package/dist/types/react-server/useLocale.d.ts +9 -0
- package/dist/types/react-server/useLocale.d.ts.map +1 -0
- package/dist/types/react-server/useTranslations.d.ts +23 -0
- package/dist/types/react-server/useTranslations.d.ts.map +1 -0
- package/dist/types/server/react/helpers.d.ts +15 -0
- package/dist/types/server/react/helpers.d.ts.map +1 -0
- package/dist/types/server/react/index.d.ts +9 -0
- package/dist/types/server/react/resolveLocale.d.ts +18 -0
- package/dist/types/server/react/resolveLocale.d.ts.map +1 -0
- package/dist/types/server/react/useDictionary.d.ts +24 -0
- package/dist/types/server/react/useDictionary.d.ts.map +1 -0
- package/dist/types/server/react/useDictionaryDynamic.d.ts +15 -0
- package/dist/types/server/react/useDictionaryDynamic.d.ts.map +1 -0
- package/dist/types/server/react/useLocale.d.ts +9 -0
- package/dist/types/server/react/useLocale.d.ts.map +1 -0
- package/dist/types/server/react/useTranslations.d.ts +23 -0
- package/dist/types/server/react/useTranslations.d.ts.map +1 -0
- package/package.json +11 -10
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_server_react_resolveLocale = require('./resolveLocale.cjs');
|
|
3
|
+
let _intlayer_use_intl = require("@intlayer/use-intl");
|
|
4
|
+
let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
|
|
5
|
+
|
|
6
|
+
//#region src/server/react/useTranslations.ts
|
|
7
|
+
/** Splits `'about.counter'` into the dictionary key and its key prefix. */
|
|
8
|
+
const splitNamespace = (namespace) => {
|
|
9
|
+
const dotPosition = namespace.indexOf(".");
|
|
10
|
+
if (dotPosition === -1) return [namespace, void 0];
|
|
11
|
+
return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Server counterpart of `useTranslations`.
|
|
15
|
+
*
|
|
16
|
+
* next-intl's `useTranslations` is isomorphic — the same component code runs in
|
|
17
|
+
* a Server or a Client Component — so the adapter has to be too. Without this
|
|
18
|
+
* every component calling it is forced across the client boundary, which drags
|
|
19
|
+
* its dictionary into a client chunk that Next shares across every locale.
|
|
20
|
+
*
|
|
21
|
+
* The optimize pass normally rewrites these calls to `useDictionary` with the
|
|
22
|
+
* dictionary inlined; this runtime path covers the calls it could not resolve
|
|
23
|
+
* statically (a dynamic namespace, or an unoptimized build).
|
|
24
|
+
*/
|
|
25
|
+
const useTranslations = ((namespace) => {
|
|
26
|
+
const locale = require_server_react_resolveLocale.resolveServerLocale();
|
|
27
|
+
if (!namespace) {
|
|
28
|
+
const rootTranslator = (key, values) => {
|
|
29
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(key);
|
|
30
|
+
const content = (0, _intlayer_core_interpreter.getIntlayer)(dictionaryKey, locale);
|
|
31
|
+
return (0, _intlayer_use_intl.createDictionaryTranslator)(locale, content, void 0)(keyPrefix ?? "", values);
|
|
32
|
+
};
|
|
33
|
+
return rootTranslator;
|
|
34
|
+
}
|
|
35
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(namespace);
|
|
36
|
+
const content = (0, _intlayer_core_interpreter.getIntlayer)(dictionaryKey, locale);
|
|
37
|
+
return (0, _intlayer_use_intl.createDictionaryTranslator)(locale, content, keyPrefix);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
exports.useTranslations = useTranslations;
|
|
42
|
+
//# sourceMappingURL=useTranslations.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslations.cjs","names":["resolveServerLocale","getIntlayer","createDictionaryTranslator"],"sources":["../../../../src/server/react/useTranslations.ts"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport type { DictionaryKeys } from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type LooseTranslateFunction,\n type TranslateFunction,\n type TranslateFunctionForNamespace,\n} from '@intlayer/use-intl';\nimport { resolveServerLocale } from './resolveLocale';\n\ntype UseTranslations = {\n <N extends DictionaryKeys>(namespace: N): TranslateFunction<N>;\n <N extends `${string}.${string}`>(\n namespace: N\n ): TranslateFunctionForNamespace<N>;\n (): LooseTranslateFunction;\n};\n\n/** Splits `'about.counter'` into the dictionary key and its key prefix. */\nconst splitNamespace = (namespace: string): [string, string | undefined] => {\n const dotPosition = namespace.indexOf('.');\n if (dotPosition === -1) return [namespace, undefined];\n return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];\n};\n\n/**\n * Server counterpart of `useTranslations`.\n *\n * next-intl's `useTranslations` is isomorphic — the same component code runs in\n * a Server or a Client Component — so the adapter has to be too. Without this\n * every component calling it is forced across the client boundary, which drags\n * its dictionary into a client chunk that Next shares across every locale.\n *\n * The optimize pass normally rewrites these calls to `useDictionary` with the\n * dictionary inlined; this runtime path covers the calls it could not resolve\n * statically (a dynamic namespace, or an unoptimized build).\n */\nexport const useTranslations = ((namespace?: string) => {\n const locale = resolveServerLocale();\n\n if (!namespace) {\n // Root scope: the first segment of each message id names the dictionary,\n // so the lookup can only happen per call.\n const rootTranslator = (key: string, values?: Record<string, unknown>) => {\n const [dictionaryKey, keyPrefix] = splitNamespace(key);\n const content = getIntlayer(dictionaryKey as never, locale as never);\n const translate = createDictionaryTranslator(locale, content, undefined);\n return translate(keyPrefix ?? '', values as never);\n };\n return rootTranslator as unknown as LooseTranslateFunction;\n }\n\n const [dictionaryKey, keyPrefix] = splitNamespace(namespace);\n const content = getIntlayer(dictionaryKey as never, locale as never);\n\n return createDictionaryTranslator(locale, content, keyPrefix);\n}) as UseTranslations;\n"],"mappings":";;;;;;;AAmBA,MAAM,kBAAkB,cAAoD;CAC1E,MAAM,cAAc,UAAU,QAAQ,GAAG;CACzC,IAAI,gBAAgB,IAAI,OAAO,CAAC,WAAW,MAAS;CACpD,OAAO,CAAC,UAAU,MAAM,GAAG,WAAW,GAAG,UAAU,MAAM,cAAc,CAAC,CAAC;AAC3E;;;;;;;;;;;;;AAcA,MAAa,oBAAoB,cAAuB;CACtD,MAAM,SAASA,uDAAoB;CAEnC,IAAI,CAAC,WAAW;EAGd,MAAM,kBAAkB,KAAa,WAAqC;GACxE,MAAM,CAAC,eAAe,aAAa,eAAe,GAAG;GACrD,MAAM,cAAUC,wCAAY,eAAwB,MAAe;GAEnE,WADkBC,+CAA2B,QAAQ,SAAS,MAC/C,CAAC,CAAC,aAAa,IAAI,MAAe;EACnD;EACA,OAAO;CACT;CAEA,MAAM,CAAC,eAAe,aAAa,eAAe,SAAS;CAC3D,MAAM,cAAUD,wCAAY,eAAwB,MAAe;CAEnE,WAAOC,+CAA2B,QAAQ,SAAS,SAAS;AAC9D"}
|
|
@@ -3,7 +3,7 @@ import * as ANSIColors from "@intlayer/config/colors";
|
|
|
3
3
|
import { colorize, getAppLogger } from "@intlayer/config/logger";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
6
|
-
import { NEXT_INTL_CALLERS
|
|
6
|
+
import { NEXT_INTL_CALLERS } from "@intlayer/config/callers";
|
|
7
7
|
import { getConfiguration } from "@intlayer/config/node";
|
|
8
8
|
import { runOnce } from "@intlayer/engine/utils";
|
|
9
9
|
|
|
@@ -77,6 +77,24 @@ const resolveEsmPath = (specifier) => {
|
|
|
77
77
|
return resolve(packageDir, relativeFile);
|
|
78
78
|
};
|
|
79
79
|
/**
|
|
80
|
+
* Absolute path of a specifier's `react-server` export condition, when the
|
|
81
|
+
* package declares one.
|
|
82
|
+
*
|
|
83
|
+
* Aliasing to a file bypasses the package's `exports` map, so the condition
|
|
84
|
+
* would never be consulted — the alias itself has to carry it. Without this,
|
|
85
|
+
* every Server Component resolves the client build of `useTranslations`, gets
|
|
86
|
+
* pulled across the client boundary, and drags its dictionary into a chunk
|
|
87
|
+
* Next shares across every locale.
|
|
88
|
+
*/
|
|
89
|
+
const resolveReactServerPath = (specifier) => {
|
|
90
|
+
const { packageName, exportKey } = splitSpecifier(specifier);
|
|
91
|
+
const packageJson = compatRequire(`${packageName}/package.json`);
|
|
92
|
+
const packageDir = dirname(compatRequire.resolve(`${packageName}/package.json`));
|
|
93
|
+
const exportEntry = packageJson.exports?.[exportKey];
|
|
94
|
+
const relativeFile = typeof exportEntry === "string" ? void 0 : exportEntry?.["react-server"];
|
|
95
|
+
return relativeFile ? resolve(packageDir, relativeFile) : void 0;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
80
98
|
* Format an absolute path as a project-root-relative specifier (prefixed with
|
|
81
99
|
* `./` and using forward slashes). Turbopack only honours `resolveAlias` values
|
|
82
100
|
* that are project-root-relative paths — bare specifiers are ignored and
|
|
@@ -88,12 +106,6 @@ const resolveEsmPath = (specifier) => {
|
|
|
88
106
|
*/
|
|
89
107
|
const toTurbopackAlias = (absolutePath) => `./${relative(process.cwd(), absolutePath).split(sep).join("/")}`;
|
|
90
108
|
/**
|
|
91
|
-
* SWC extra-caller configs derived from the shared caller registry
|
|
92
|
-
* (`@intlayer/config/callers`) — the single source of truth also consumed by
|
|
93
|
-
* the babel analyzer/optimizer and the LSP.
|
|
94
|
-
*/
|
|
95
|
-
const NEXT_INTL_SWC_CALLERS = toSwcExtraCallers(NEXT_INTL_CALLERS);
|
|
96
|
-
/**
|
|
97
109
|
* A Next.js plugin for next-intl compat that wraps next-intlayer's plugin
|
|
98
110
|
* and configures resolve aliases so `next-intl` imports are served by
|
|
99
111
|
* `@intlayer/next-intl`.
|
|
@@ -108,10 +120,23 @@ const createNextIntlPlugin = (_i18nPath) => {
|
|
|
108
120
|
const customWebpack = nextConfig.webpack;
|
|
109
121
|
const resolvedTargets = ALIAS_ENTRIES.map(({ request, replacement }) => ({
|
|
110
122
|
request,
|
|
111
|
-
|
|
123
|
+
replacement,
|
|
124
|
+
hasReactServerBuild: Boolean(resolveReactServerPath(replacement))
|
|
112
125
|
}));
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Aliasing to a resolved *file* pins one build of the target and bypasses
|
|
128
|
+
* its `exports` map — so the `react-server` condition is never consulted
|
|
129
|
+
* and a Server Component silently gets the client build of
|
|
130
|
+
* `useTranslations`. That drags every component calling it across the
|
|
131
|
+
* client boundary, and with it the multi-locale dictionary, into a chunk
|
|
132
|
+
* Next serves to every locale.
|
|
133
|
+
*
|
|
134
|
+
* Aliasing to the package specifier instead lets the bundler resolve
|
|
135
|
+
* normally, so each layer picks its own condition.
|
|
136
|
+
*/
|
|
137
|
+
const aliasTarget = ({ replacement, hasReactServerBuild }) => hasReactServerBuild ? replacement : toTurbopackAlias(resolveEsmPath(replacement));
|
|
138
|
+
const webpackAlias = Object.fromEntries(resolvedTargets.map(({ request, replacement, hasReactServerBuild }) => [request, hasReactServerBuild ? replacement : resolveEsmPath(replacement)]));
|
|
139
|
+
const turboAlias = Object.fromEntries(resolvedTargets.map((target) => [target.request, aliasTarget(target)]));
|
|
115
140
|
const aliasConfig = { webpack: (config, options) => {
|
|
116
141
|
config.resolve.alias = {
|
|
117
142
|
...config.resolve.alias,
|
|
@@ -135,7 +160,7 @@ const createNextIntlPlugin = (_i18nPath) => {
|
|
|
135
160
|
try {
|
|
136
161
|
hasUserDefinedStorage = !!(intlayerConfig?.routing && "storage" in intlayerConfig.routing && intlayerConfig.routing.storage !== void 0);
|
|
137
162
|
} catch {}
|
|
138
|
-
return withIntlayer(mergedConfig, hasUserDefinedStorage ? {
|
|
163
|
+
return withIntlayer(mergedConfig, hasUserDefinedStorage ? { compatCallers: NEXT_INTL_CALLERS } : {
|
|
139
164
|
override: { routing: { storage: [{
|
|
140
165
|
type: "cookie",
|
|
141
166
|
name: "NEXT_LOCALE"
|
|
@@ -143,7 +168,7 @@ const createNextIntlPlugin = (_i18nPath) => {
|
|
|
143
168
|
type: "header",
|
|
144
169
|
name: "x-intlayer-locale"
|
|
145
170
|
}] } },
|
|
146
|
-
|
|
171
|
+
compatCallers: NEXT_INTL_CALLERS
|
|
147
172
|
});
|
|
148
173
|
};
|
|
149
174
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { NEXT_INTL_CALLERS, toSwcExtraCallers } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { NextConfig } from 'next';\nimport { withIntlayer } from 'next-intlayer/server';\n\n/**\n * `require` that works in both the CJS and ESM builds of this plugin.\n * `import.meta.url` is rewritten to the module path in the CJS output by the\n * bundler, so `createRequire` resolves correctly in either format.\n */\nconst compatRequire = createRequire(import.meta.url);\n\n/**\n * Maps each original `next-intl` import specifier to the `@intlayer/next-intl`\n * specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-intl/server', replacement: '@intlayer/next-intl/server' },\n { request: 'next-intl/routing', replacement: '@intlayer/next-intl/routing' },\n {\n request: 'next-intl/navigation',\n replacement: '@intlayer/next-intl/navigation',\n },\n {\n request: 'next-intl/middleware',\n replacement: '@intlayer/next-intl/middleware',\n },\n { request: 'next-intl', replacement: '@intlayer/next-intl' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/next-intl/server` or `next-intl`.\n * @returns `{ packageName, exportKey }` where `exportKey` is the `exports` map\n * key (`.` for the package root).\n */\nconst splitSpecifier = (\n specifier: string\n): { packageName: string; exportKey: string } => {\n const segments = specifier.split('/');\n const packageName = specifier.startsWith('@')\n ? segments.slice(0, 2).join('/')\n : (segments[0] ?? specifier);\n const subpath = specifier.slice(packageName?.length);\n return { packageName, exportKey: subpath === '' ? '.' : `.${subpath}` };\n};\n\n/**\n * Resolve the absolute path of a package export, preferring the ESM (`import`)\n * condition so Turbopack and modern bundlers load the `.mjs` build (which keeps\n * the `\"use client\"` directives) rather than the CommonJS fallback.\n *\n * Both Turbopack and webpack ignore alias values that are bare package\n * specifiers, so the aliases must point at real files.\n *\n * @param specifier - Package specifier, e.g. `@intlayer/next-intl/server`.\n * @returns Absolute path to the resolved module file.\n */\nconst resolveEsmPath = (specifier: string): string => {\n const { packageName, exportKey } = splitSpecifier(specifier);\n const packageJson = compatRequire(`${packageName}/package.json`) as {\n exports?: Record<\n string,\n string | { import?: string; require?: string; default?: string }\n >;\n };\n const packageDir = dirname(\n compatRequire.resolve(`${packageName}/package.json`)\n );\n\n const exportEntry = packageJson.exports?.[exportKey];\n const relativeFile =\n typeof exportEntry === 'string'\n ? exportEntry\n : (exportEntry?.import ?? exportEntry?.require ?? exportEntry?.default);\n\n // Fall back to Node resolution if the exports map is unexpected.\n if (!relativeFile) return compatRequire.resolve(specifier);\n\n return resolve(packageDir, relativeFile);\n};\n\n/**\n * Format an absolute path as a project-root-relative specifier (prefixed with\n * `./` and using forward slashes). Turbopack only honours `resolveAlias` values\n * that are project-root-relative paths — bare specifiers are ignored and\n * absolute paths are misread as root-relative. Mirrors `withIntlayer`'s\n * Turbopack alias formatter.\n *\n * @param absolutePath - Absolute path to the target module file.\n * @returns Relative specifier such as `./node_modules/@intlayer/next-intl/...`.\n */\nconst toTurbopackAlias = (absolutePath: string): string =>\n `./${relative(process.cwd(), absolutePath).split(sep).join('/')}`;\n\n/**\n * SWC extra-caller configs derived from the shared caller registry\n * (`@intlayer/config/callers`) — the single source of truth also consumed by\n * the babel analyzer/optimizer and the LSP.\n */\nconst NEXT_INTL_SWC_CALLERS = toSwcExtraCallers(NEXT_INTL_CALLERS);\n\n/**\n * A Next.js plugin for next-intl compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-intl` imports are served by\n * `@intlayer/next-intl`.\n */\nexport const createNextIntlPlugin = (_i18nPath?: string) => {\n return async (nextConfig: NextConfig = {}): Promise<NextConfig> => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig?.system?.baseDir ?? process.cwd(),\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const customWebpack = nextConfig.webpack;\n\n const resolvedTargets = ALIAS_ENTRIES.map(({ request, replacement }) => ({\n request,\n absolutePath: resolveEsmPath(replacement),\n }));\n\n // Webpack resolves aliases from absolute paths.\n const webpackAlias = Object.fromEntries(\n resolvedTargets.map(({ request, absolutePath }) => [\n request,\n absolutePath,\n ])\n );\n\n // Turbopack only honours project-root-relative `./` paths.\n const turboAlias = Object.fromEntries(\n resolvedTargets.map(({ request, absolutePath }) => [\n request,\n toTurbopackAlias(absolutePath),\n ])\n );\n\n const aliasConfig = {\n webpack: (config: any, options: any) => {\n config.resolve.alias = {\n ...config.resolve.alias,\n ...webpackAlias,\n };\n\n if (typeof customWebpack === 'function') {\n return customWebpack(config, options);\n }\n return config;\n },\n };\n\n const mergedConfig: NextConfig = {\n ...nextConfig,\n ...aliasConfig,\n turbopack: {\n ...(nextConfig.turbopack ?? {}),\n resolveAlias: {\n ...(nextConfig.turbopack?.resolveAlias ?? {}),\n ...turboAlias,\n },\n },\n };\n\n // Only inject the NEXT_LOCALE cookie default when the user has not\n // configured their own routing.storage in intlayer.config.ts.\n // This lets users override via intlayer.config.ts while keeping\n // next-intl compatibility (NEXT_LOCALE) as the default.\n let hasUserDefinedStorage = false;\n try {\n hasUserDefinedStorage = !!(\n intlayerConfig?.routing &&\n 'storage' in intlayerConfig.routing &&\n intlayerConfig.routing.storage !== undefined\n );\n } catch {\n // If the config file cannot be read, fall back to the NEXT_LOCALE default.\n }\n\n const configOptions = hasUserDefinedStorage\n ? { swcExtraCallers: NEXT_INTL_SWC_CALLERS }\n : {\n override: {\n routing: {\n storage: [\n { type: 'cookie' as const, name: 'NEXT_LOCALE' },\n { type: 'header' as const, name: 'x-intlayer-locale' },\n ],\n },\n },\n swcExtraCallers: NEXT_INTL_SWC_CALLERS,\n };\n\n return withIntlayer(mergedConfig, configOptions);\n };\n};\n\nexport default createNextIntlPlugin;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { NEXT_INTL_CALLERS } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { NextConfig } from 'next';\nimport { withIntlayer } from 'next-intlayer/server';\n\n/**\n * `require` that works in both the CJS and ESM builds of this plugin.\n * `import.meta.url` is rewritten to the module path in the CJS output by the\n * bundler, so `createRequire` resolves correctly in either format.\n */\nconst compatRequire = createRequire(import.meta.url);\n\n/**\n * Maps each original `next-intl` import specifier to the `@intlayer/next-intl`\n * specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-intl/server', replacement: '@intlayer/next-intl/server' },\n { request: 'next-intl/routing', replacement: '@intlayer/next-intl/routing' },\n {\n request: 'next-intl/navigation',\n replacement: '@intlayer/next-intl/navigation',\n },\n {\n request: 'next-intl/middleware',\n replacement: '@intlayer/next-intl/middleware',\n },\n { request: 'next-intl', replacement: '@intlayer/next-intl' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/next-intl/server` or `next-intl`.\n * @returns `{ packageName, exportKey }` where `exportKey` is the `exports` map\n * key (`.` for the package root).\n */\nconst splitSpecifier = (\n specifier: string\n): { packageName: string; exportKey: string } => {\n const segments = specifier.split('/');\n const packageName = specifier.startsWith('@')\n ? segments.slice(0, 2).join('/')\n : (segments[0] ?? specifier);\n const subpath = specifier.slice(packageName?.length);\n return { packageName, exportKey: subpath === '' ? '.' : `.${subpath}` };\n};\n\n/**\n * Resolve the absolute path of a package export, preferring the ESM (`import`)\n * condition so Turbopack and modern bundlers load the `.mjs` build (which keeps\n * the `\"use client\"` directives) rather than the CommonJS fallback.\n *\n * Both Turbopack and webpack ignore alias values that are bare package\n * specifiers, so the aliases must point at real files.\n *\n * @param specifier - Package specifier, e.g. `@intlayer/next-intl/server`.\n * @returns Absolute path to the resolved module file.\n */\nconst resolveEsmPath = (specifier: string): string => {\n const { packageName, exportKey } = splitSpecifier(specifier);\n const packageJson = compatRequire(`${packageName}/package.json`) as {\n exports?: Record<\n string,\n | string\n | {\n 'react-server'?: string;\n import?: string;\n require?: string;\n default?: string;\n }\n >;\n };\n const packageDir = dirname(\n compatRequire.resolve(`${packageName}/package.json`)\n );\n\n const exportEntry = packageJson.exports?.[exportKey];\n const relativeFile =\n typeof exportEntry === 'string'\n ? exportEntry\n : (exportEntry?.import ?? exportEntry?.require ?? exportEntry?.default);\n\n // Fall back to Node resolution if the exports map is unexpected.\n if (!relativeFile) return compatRequire.resolve(specifier);\n\n return resolve(packageDir, relativeFile);\n};\n\n/**\n * Absolute path of a specifier's `react-server` export condition, when the\n * package declares one.\n *\n * Aliasing to a file bypasses the package's `exports` map, so the condition\n * would never be consulted — the alias itself has to carry it. Without this,\n * every Server Component resolves the client build of `useTranslations`, gets\n * pulled across the client boundary, and drags its dictionary into a chunk\n * Next shares across every locale.\n */\nconst resolveReactServerPath = (specifier: string): string | undefined => {\n const { packageName, exportKey } = splitSpecifier(specifier);\n const packageJson = compatRequire(`${packageName}/package.json`) as {\n exports?: Record<string, string | { 'react-server'?: string }>;\n };\n const packageDir = dirname(\n compatRequire.resolve(`${packageName}/package.json`)\n );\n\n const exportEntry = packageJson.exports?.[exportKey];\n const relativeFile =\n typeof exportEntry === 'string' ? undefined : exportEntry?.['react-server'];\n\n return relativeFile ? resolve(packageDir, relativeFile) : undefined;\n};\n\n/**\n * Format an absolute path as a project-root-relative specifier (prefixed with\n * `./` and using forward slashes). Turbopack only honours `resolveAlias` values\n * that are project-root-relative paths — bare specifiers are ignored and\n * absolute paths are misread as root-relative. Mirrors `withIntlayer`'s\n * Turbopack alias formatter.\n *\n * @param absolutePath - Absolute path to the target module file.\n * @returns Relative specifier such as `./node_modules/@intlayer/next-intl/...`.\n */\nconst toTurbopackAlias = (absolutePath: string): string =>\n `./${relative(process.cwd(), absolutePath).split(sep).join('/')}`;\n\n/**\n * A Next.js plugin for next-intl compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-intl` imports are served by\n * `@intlayer/next-intl`.\n */\nexport const createNextIntlPlugin = (_i18nPath?: string) => {\n return async (nextConfig: NextConfig = {}): Promise<NextConfig> => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig?.system?.baseDir ?? process.cwd(),\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const customWebpack = nextConfig.webpack;\n\n const resolvedTargets = ALIAS_ENTRIES.map(({ request, replacement }) => ({\n request,\n replacement,\n hasReactServerBuild: Boolean(resolveReactServerPath(replacement)),\n }));\n\n /**\n * Aliasing to a resolved *file* pins one build of the target and bypasses\n * its `exports` map — so the `react-server` condition is never consulted\n * and a Server Component silently gets the client build of\n * `useTranslations`. That drags every component calling it across the\n * client boundary, and with it the multi-locale dictionary, into a chunk\n * Next serves to every locale.\n *\n * Aliasing to the package specifier instead lets the bundler resolve\n * normally, so each layer picks its own condition.\n */\n const aliasTarget = ({\n replacement,\n hasReactServerBuild,\n }: {\n replacement: string;\n hasReactServerBuild: boolean;\n }) =>\n hasReactServerBuild\n ? replacement\n : toTurbopackAlias(resolveEsmPath(replacement));\n\n const webpackAlias = Object.fromEntries(\n resolvedTargets.map(({ request, replacement, hasReactServerBuild }) => [\n request,\n hasReactServerBuild ? replacement : resolveEsmPath(replacement),\n ])\n );\n\n const turboAlias = Object.fromEntries(\n resolvedTargets.map((target) => [target.request, aliasTarget(target)])\n );\n\n const aliasConfig = {\n webpack: (config: any, options: any) => {\n config.resolve.alias = {\n ...config.resolve.alias,\n ...webpackAlias,\n };\n\n if (typeof customWebpack === 'function') {\n return customWebpack(config, options);\n }\n return config;\n },\n };\n\n const mergedConfig: NextConfig = {\n ...nextConfig,\n ...aliasConfig,\n turbopack: {\n ...(nextConfig.turbopack ?? {}),\n resolveAlias: {\n ...(nextConfig.turbopack?.resolveAlias ?? {}),\n ...turboAlias,\n },\n },\n };\n\n // Only inject the NEXT_LOCALE cookie default when the user has not\n // configured their own routing.storage in intlayer.config.ts.\n // This lets users override via intlayer.config.ts while keeping\n // next-intl compatibility (NEXT_LOCALE) as the default.\n let hasUserDefinedStorage = false;\n try {\n hasUserDefinedStorage = !!(\n intlayerConfig?.routing &&\n 'storage' in intlayerConfig.routing &&\n intlayerConfig.routing.storage !== undefined\n );\n } catch {\n // If the config file cannot be read, fall back to the NEXT_LOCALE default.\n }\n\n const configOptions = hasUserDefinedStorage\n ? { compatCallers: NEXT_INTL_CALLERS }\n : {\n override: {\n routing: {\n storage: [\n { type: 'cookie' as const, name: 'NEXT_LOCALE' },\n { type: 'header' as const, name: 'x-intlayer-locale' },\n ],\n },\n },\n compatCallers: NEXT_INTL_CALLERS,\n };\n\n return withIntlayer(mergedConfig, configOptions);\n };\n};\n\nexport default createNextIntlPlugin;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useLocale } from "./useLocale.mjs";
|
|
2
|
+
import { createFormatter } from "@intlayer/use-intl";
|
|
3
|
+
|
|
4
|
+
//#region src/react-server/helpers.ts
|
|
5
|
+
/**
|
|
6
|
+
* Server counterparts of use-intl's ambient hooks. They mirror the client
|
|
7
|
+
* versions' signatures so the same component code type-checks on both sides.
|
|
8
|
+
*/
|
|
9
|
+
const useFormatter = (() => createFormatter({ locale: useLocale() }));
|
|
10
|
+
/** Current time on the server render. */
|
|
11
|
+
const useNow = (() => /* @__PURE__ */ new Date());
|
|
12
|
+
/** Time zone used by the formatters; UTC unless the app overrides it. */
|
|
13
|
+
const useTimeZone = (() => void 0);
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { useFormatter, useNow, useTimeZone };
|
|
17
|
+
//# sourceMappingURL=helpers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../../src/react-server/helpers.ts"],"sourcesContent":["import { createFormatter } from '@intlayer/use-intl';\nimport { useLocale } from './useLocale';\n\n/**\n * Server counterparts of use-intl's ambient hooks. They mirror the client\n * versions' signatures so the same component code type-checks on both sides.\n */\nexport const useFormatter: typeof import('@intlayer/use-intl').useFormatter =\n (() => createFormatter({ locale: useLocale() as string })) as never;\n\n/** Current time on the server render. */\nexport const useNow: typeof import('@intlayer/use-intl').useNow = (() =>\n new Date()) as never;\n\n/** Time zone used by the formatters; UTC unless the app overrides it. */\nexport const useTimeZone: typeof import('@intlayer/use-intl').useTimeZone =\n (() => undefined) as never;\n"],"mappings":";;;;;;;;AAOA,MAAa,sBACJ,gBAAgB,EAAE,QAAQ,UAAU,EAAY,CAAC;;AAG1D,MAAa,gCACX,IAAI,KAAK;;AAGX,MAAa,qBACJ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineRouting } from "../routing.mjs";
|
|
2
|
+
import { NextIntlClientProvider } from "../client/NextIntlClientProvider.mjs";
|
|
3
|
+
import { useTranslations } from "./useTranslations.mjs";
|
|
4
|
+
import { useLocale } from "./useLocale.mjs";
|
|
5
|
+
import { useFormatter, useNow, useTimeZone } from "./helpers.mjs";
|
|
6
|
+
import { useDictionaryDynamic } from "./useDictionaryDynamic.mjs";
|
|
7
|
+
import { useDictionary } from "./useDictionary.mjs";
|
|
8
|
+
import { IntlError, IntlErrorCode, createFormatter, createTranslator, hasLocale, initializeConfig, useMessages } from "@intlayer/use-intl";
|
|
9
|
+
|
|
10
|
+
export { IntlError, IntlErrorCode, NextIntlClientProvider, createFormatter, createTranslator, defineRouting, hasLocale, initializeConfig, useDictionary, useDictionaryDynamic, useFormatter, useLocale, useMessages, useNow, useTimeZone, useTranslations };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getCachedRequestLocale } from "../server/requestLocaleCache.mjs";
|
|
2
|
+
import { useLocale } from "next-intlayer/server";
|
|
3
|
+
|
|
4
|
+
//#region src/react-server/resolveLocale.ts
|
|
5
|
+
/**
|
|
6
|
+
* Locale for a synchronous server hook, resolved the same way `getLocale()`
|
|
7
|
+
* resolves it — so server-rendered content and the client provider never
|
|
8
|
+
* disagree about which locale the request is in.
|
|
9
|
+
*
|
|
10
|
+
* 1. The locale forwarded through `setRequestLocale(locale)` (the `[locale]`
|
|
11
|
+
* route segment), which is next-intl's source of truth for URL routing.
|
|
12
|
+
* 2. Otherwise Intlayer's ambient locale (server context, then the request).
|
|
13
|
+
*/
|
|
14
|
+
const resolveServerLocale = () => getCachedRequestLocale() ?? useLocale().locale;
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { resolveServerLocale };
|
|
18
|
+
//# sourceMappingURL=resolveLocale.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveLocale.mjs","names":["useLocaleIntlayer"],"sources":["../../../src/react-server/resolveLocale.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { useLocale as useLocaleIntlayer } from 'next-intlayer/server';\nimport { getCachedRequestLocale } from '../server/requestLocaleCache';\n\n/**\n * Locale for a synchronous server hook, resolved the same way `getLocale()`\n * resolves it — so server-rendered content and the client provider never\n * disagree about which locale the request is in.\n *\n * 1. The locale forwarded through `setRequestLocale(locale)` (the `[locale]`\n * route segment), which is next-intl's source of truth for URL routing.\n * 2. Otherwise Intlayer's ambient locale (server context, then the request).\n */\nexport const resolveServerLocale = (): LocalesValues =>\n (getCachedRequestLocale() ??\n useLocaleIntlayer().locale) as LocalesValues;\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,4BACV,uBAAuB,KACtBA,UAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { useDictionary as useDictionary$1 } from "next-intlayer/server";
|
|
4
|
+
|
|
5
|
+
//#region src/react-server/useDictionary.ts
|
|
6
|
+
/**
|
|
7
|
+
* Server counterpart of `@intlayer/use-intl`'s `useDictionary`.
|
|
8
|
+
*
|
|
9
|
+
* The optimize pass rewrites every `useTranslations(...)` call to this helper
|
|
10
|
+
* with the dictionary pre-imported. Resolving it here — rather than in a client
|
|
11
|
+
* component — keeps the dictionary out of the client bundle entirely: the
|
|
12
|
+
* server renders the text and only the rendered output crosses the boundary.
|
|
13
|
+
*/
|
|
14
|
+
const useDictionary = ((dictionary, namespacePrefix) => {
|
|
15
|
+
const locale = resolveServerLocale();
|
|
16
|
+
const content = useDictionary$1(dictionary, locale);
|
|
17
|
+
return createDictionaryTranslator(locale, content, namespacePrefix);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { useDictionary };
|
|
22
|
+
//# sourceMappingURL=useDictionary.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionary.mjs","names":["useDictionaryBase"],"sources":["../../../src/react-server/useDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type ScopedTranslateFunction,\n type TranslateFunction,\n} from '@intlayer/use-intl';\nimport { useDictionary as useDictionaryBase } from 'next-intlayer/server';\nimport { resolveServerLocale } from './resolveLocale';\n\n/**\n * Overload set mirroring the client `useDictionary` exactly, so the optimize\n * pass can emit the same call shape whichever side of the boundary the\n * component ends up on.\n */\ntype UseDictionary = {\n <T extends Dictionary>(\n dictionary: T\n ): TranslateFunction<T['key'] & DictionaryKeys>;\n <T extends Dictionary, Prefix extends string>(\n dictionary: T,\n namespacePrefix: Prefix\n ): ScopedTranslateFunction<T['key'] & DictionaryKeys, Prefix>;\n};\n\n/**\n * Server counterpart of `@intlayer/use-intl`'s `useDictionary`.\n *\n * The optimize pass rewrites every `useTranslations(...)` call to this helper\n * with the dictionary pre-imported. Resolving it here — rather than in a client\n * component — keeps the dictionary out of the client bundle entirely: the\n * server renders the text and only the rendered output crosses the boundary.\n */\nexport const useDictionary = (<T extends Dictionary>(\n dictionary: T,\n namespacePrefix?: string\n) => {\n const locale = resolveServerLocale();\n const content = useDictionaryBase(dictionary, locale as never);\n\n return createDictionaryTranslator(\n locale,\n content,\n namespacePrefix\n );\n}) as UseDictionary;\n"],"mappings":";;;;;;;;;;;;;AAoCA,MAAa,kBACX,YACA,oBACG;CACH,MAAM,SAAS,oBAAoB;CACnC,MAAM,UAAUA,gBAAkB,YAAY,MAAe;CAE7D,OAAO,2BACL,QACA,SACA,eACF;AACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { useDictionaryDynamic as useDictionaryDynamic$1 } from "next-intlayer/server";
|
|
4
|
+
|
|
5
|
+
//#region src/react-server/useDictionaryDynamic.ts
|
|
6
|
+
/**
|
|
7
|
+
* Server counterpart of `useDictionaryDynamic`, emitted by the optimize pass
|
|
8
|
+
* for dictionaries on the per-locale loader.
|
|
9
|
+
*/
|
|
10
|
+
const useDictionaryDynamic = ((dictionaryPromise, key, namespacePrefix) => {
|
|
11
|
+
const locale = resolveServerLocale();
|
|
12
|
+
const content = useDictionaryDynamic$1(dictionaryPromise, key, locale);
|
|
13
|
+
return createDictionaryTranslator(locale, content, namespacePrefix);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { useDictionaryDynamic };
|
|
18
|
+
//# sourceMappingURL=useDictionaryDynamic.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionaryDynamic.mjs","names":["useDictionaryDynamicBase"],"sources":["../../../src/react-server/useDictionaryDynamic.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type ScopedTranslateFunction,\n type TranslateFunction,\n} from '@intlayer/use-intl';\nimport { useDictionaryDynamic as useDictionaryDynamicBase } from 'next-intlayer/server';\nimport { resolveServerLocale } from './resolveLocale';\n\ntype UseDictionaryDynamic = {\n <T extends Dictionary, K extends DictionaryKeys>(\n dictionaryPromise: Record<string, () => Promise<T>>,\n key: K\n ): TranslateFunction<K>;\n <T extends Dictionary, K extends DictionaryKeys, Prefix extends string>(\n dictionaryPromise: Record<string, () => Promise<T>>,\n key: K,\n namespacePrefix: Prefix\n ): ScopedTranslateFunction<K, Prefix>;\n};\n\n/**\n * Server counterpart of `useDictionaryDynamic`, emitted by the optimize pass\n * for dictionaries on the per-locale loader.\n */\nexport const useDictionaryDynamic = ((\n dictionaryPromise: Record<string, () => Promise<Dictionary>>,\n key: string,\n namespacePrefix?: string\n) => {\n const locale = resolveServerLocale();\n const content = useDictionaryDynamicBase(\n dictionaryPromise as never,\n key as never,\n locale as never\n );\n\n return createDictionaryTranslator(\n locale,\n content,\n namespacePrefix\n );\n}) as UseDictionaryDynamic;\n"],"mappings":";;;;;;;;;AA6BA,MAAa,yBACX,mBACA,KACA,oBACG;CACH,MAAM,SAAS,oBAAoB;CACnC,MAAM,UAAUA,uBACd,mBACA,KACA,MACF;CAEA,OAAO,2BACL,QACA,SACA,eACF;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/react-server/useLocale.ts
|
|
4
|
+
/**
|
|
5
|
+
* Server counterpart of `useLocale`, resolved from the `[locale]` route segment
|
|
6
|
+
* forwarded through `setRequestLocale` when the app provides one.
|
|
7
|
+
*/
|
|
8
|
+
const useLocale = () => resolveServerLocale();
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useLocale };
|
|
12
|
+
//# sourceMappingURL=useLocale.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLocale.mjs","names":[],"sources":["../../../src/react-server/useLocale.ts"],"sourcesContent":["import type { useLocale as _useLocale } from 'next-intl';\nimport { resolveServerLocale } from './resolveLocale';\n\n/**\n * Server counterpart of `useLocale`, resolved from the `[locale]` route segment\n * forwarded through `setRequestLocale` when the app provides one.\n */\nexport const useLocale: typeof _useLocale = () =>\n resolveServerLocale() as ReturnType<typeof _useLocale>;\n"],"mappings":";;;;;;;AAOA,MAAa,kBACX,oBAAoB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { useIntlayer } from "next-intlayer/server";
|
|
4
|
+
|
|
5
|
+
//#region src/react-server/useTranslations.ts
|
|
6
|
+
/** Splits `'about.counter'` into the dictionary key and its key prefix. */
|
|
7
|
+
const splitNamespace = (namespace) => {
|
|
8
|
+
const dotPosition = namespace.indexOf(".");
|
|
9
|
+
if (dotPosition === -1) return [namespace, void 0];
|
|
10
|
+
return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Server counterpart of `useTranslations`.
|
|
14
|
+
*
|
|
15
|
+
* next-intl's `useTranslations` is isomorphic — the same component code runs in
|
|
16
|
+
* a Server or a Client Component — so the adapter has to be too. Without this
|
|
17
|
+
* every component calling it is forced across the client boundary, which drags
|
|
18
|
+
* its dictionary into a client chunk that Next shares across every locale.
|
|
19
|
+
*
|
|
20
|
+
* The optimize pass normally rewrites these calls to `useDictionary` with the
|
|
21
|
+
* dictionary inlined; this runtime path covers the calls it could not resolve
|
|
22
|
+
* statically (a dynamic namespace, or an unoptimized build).
|
|
23
|
+
*/
|
|
24
|
+
const useTranslations = ((namespace) => {
|
|
25
|
+
const locale = resolveServerLocale();
|
|
26
|
+
if (!namespace) {
|
|
27
|
+
const rootTranslator = (key, values) => {
|
|
28
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(key);
|
|
29
|
+
const content = useIntlayer(dictionaryKey, locale);
|
|
30
|
+
return createDictionaryTranslator(locale, content, void 0)(keyPrefix ?? "", values);
|
|
31
|
+
};
|
|
32
|
+
return rootTranslator;
|
|
33
|
+
}
|
|
34
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(namespace);
|
|
35
|
+
const content = useIntlayer(dictionaryKey, locale);
|
|
36
|
+
return createDictionaryTranslator(locale, content, keyPrefix);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { useTranslations };
|
|
41
|
+
//# sourceMappingURL=useTranslations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslations.mjs","names":[],"sources":["../../../src/react-server/useTranslations.ts"],"sourcesContent":["import type { DictionaryKeys } from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type LooseTranslateFunction,\n type TranslateFunction,\n type TranslateFunctionForNamespace,\n} from '@intlayer/use-intl';\nimport { useIntlayer } from 'next-intlayer/server';\nimport { resolveServerLocale } from './resolveLocale';\n\ntype UseTranslations = {\n <N extends DictionaryKeys>(namespace: N): TranslateFunction<N>;\n <N extends `${string}.${string}`>(\n namespace: N\n ): TranslateFunctionForNamespace<N>;\n (): LooseTranslateFunction;\n};\n\n/** Splits `'about.counter'` into the dictionary key and its key prefix. */\nconst splitNamespace = (namespace: string): [string, string | undefined] => {\n const dotPosition = namespace.indexOf('.');\n if (dotPosition === -1) return [namespace, undefined];\n return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];\n};\n\n/**\n * Server counterpart of `useTranslations`.\n *\n * next-intl's `useTranslations` is isomorphic — the same component code runs in\n * a Server or a Client Component — so the adapter has to be too. Without this\n * every component calling it is forced across the client boundary, which drags\n * its dictionary into a client chunk that Next shares across every locale.\n *\n * The optimize pass normally rewrites these calls to `useDictionary` with the\n * dictionary inlined; this runtime path covers the calls it could not resolve\n * statically (a dynamic namespace, or an unoptimized build).\n */\nexport const useTranslations = ((namespace?: string) => {\n const locale = resolveServerLocale();\n\n if (!namespace) {\n // Root scope: the first segment of each message id names the dictionary,\n // so the lookup can only happen per call.\n const rootTranslator = (key: string, values?: Record<string, unknown>) => {\n const [dictionaryKey, keyPrefix] = splitNamespace(key);\n const content = useIntlayer(dictionaryKey as never, locale as never);\n const translate = createDictionaryTranslator(locale, content, undefined);\n return translate(keyPrefix ?? '', values as never);\n };\n return rootTranslator as unknown as LooseTranslateFunction;\n }\n\n const [dictionaryKey, keyPrefix] = splitNamespace(namespace);\n const content = useIntlayer(dictionaryKey as never, locale as never);\n\n return createDictionaryTranslator(locale, content, keyPrefix);\n}) as UseTranslations;\n"],"mappings":";;;;;;AAmBA,MAAM,kBAAkB,cAAoD;CAC1E,MAAM,cAAc,UAAU,QAAQ,GAAG;CACzC,IAAI,gBAAgB,IAAI,OAAO,CAAC,WAAW,MAAS;CACpD,OAAO,CAAC,UAAU,MAAM,GAAG,WAAW,GAAG,UAAU,MAAM,cAAc,CAAC,CAAC;AAC3E;;;;;;;;;;;;;AAcA,MAAa,oBAAoB,cAAuB;CACtD,MAAM,SAAS,oBAAoB;CAEnC,IAAI,CAAC,WAAW;EAGd,MAAM,kBAAkB,KAAa,WAAqC;GACxE,MAAM,CAAC,eAAe,aAAa,eAAe,GAAG;GACrD,MAAM,UAAU,YAAY,eAAwB,MAAe;GAEnE,OADkB,2BAA2B,QAAQ,SAAS,MAC/C,CAAC,CAAC,aAAa,IAAI,MAAe;EACnD;EACA,OAAO;CACT;CAEA,MAAM,CAAC,eAAe,aAAa,eAAe,SAAS;CAC3D,MAAM,UAAU,YAAY,eAAwB,MAAe;CAEnE,OAAO,2BAA2B,QAAQ,SAAS,SAAS;AAC9D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useLocale } from "./useLocale.mjs";
|
|
2
|
+
import { createFormatter } from "@intlayer/use-intl";
|
|
3
|
+
|
|
4
|
+
//#region src/server/react/helpers.ts
|
|
5
|
+
/**
|
|
6
|
+
* Server counterparts of use-intl's ambient hooks. They mirror the client
|
|
7
|
+
* versions' signatures so the same component code type-checks on both sides.
|
|
8
|
+
*/
|
|
9
|
+
const useFormatter = (() => createFormatter({ locale: useLocale() }));
|
|
10
|
+
/** Current time on the server render. */
|
|
11
|
+
const useNow = (() => /* @__PURE__ */ new Date());
|
|
12
|
+
/**
|
|
13
|
+
* Time zone the formatters resolve against — the same value the async
|
|
14
|
+
* `getTimeZone()` reports, so both server surfaces agree.
|
|
15
|
+
*/
|
|
16
|
+
const useTimeZone = (() => Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { useFormatter, useNow, useTimeZone };
|
|
20
|
+
//# sourceMappingURL=helpers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../../../src/server/react/helpers.ts"],"sourcesContent":["import { createFormatter } from '@intlayer/use-intl';\nimport { useLocale } from './useLocale';\n\n/**\n * Server counterparts of use-intl's ambient hooks. They mirror the client\n * versions' signatures so the same component code type-checks on both sides.\n */\nexport const useFormatter: typeof import('@intlayer/use-intl').useFormatter =\n (() => createFormatter({ locale: useLocale() as string })) as never;\n\n/** Current time on the server render. */\nexport const useNow: typeof import('@intlayer/use-intl').useNow = (() =>\n new Date()) as never;\n\n/**\n * Time zone the formatters resolve against — the same value the async\n * `getTimeZone()` reports, so both server surfaces agree.\n */\nexport const useTimeZone: typeof import('@intlayer/use-intl').useTimeZone =\n (() => Intl.DateTimeFormat().resolvedOptions().timeZone) as never;\n"],"mappings":";;;;;;;;AAOA,MAAa,sBACJ,gBAAgB,EAAE,QAAQ,UAAU,EAAY,CAAC;;AAG1D,MAAa,gCACX,IAAI,KAAK;;;;;AAMX,MAAa,qBACJ,KAAK,eAAe,CAAC,CAAC,gBAAgB,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineRouting } from "../../routing.mjs";
|
|
2
|
+
import { NextIntlClientProvider } from "../../client/NextIntlClientProvider.mjs";
|
|
3
|
+
import { useTranslations } from "./useTranslations.mjs";
|
|
4
|
+
import { useLocale } from "./useLocale.mjs";
|
|
5
|
+
import { useFormatter, useNow, useTimeZone } from "./helpers.mjs";
|
|
6
|
+
import { useDictionaryDynamic } from "./useDictionaryDynamic.mjs";
|
|
7
|
+
import { useDictionary } from "./useDictionary.mjs";
|
|
8
|
+
import { IntlError, IntlErrorCode, createFormatter, createTranslator, hasLocale, initializeConfig, useMessages } from "@intlayer/use-intl";
|
|
9
|
+
|
|
10
|
+
export { IntlError, IntlErrorCode, NextIntlClientProvider, createFormatter, createTranslator, defineRouting, hasLocale, initializeConfig, useDictionary, useDictionaryDynamic, useFormatter, useLocale, useMessages, useNow, useTimeZone, useTranslations };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getCachedRequestLocale } from "../requestLocaleCache.mjs";
|
|
2
|
+
import { useLocale } from "next-intlayer/server";
|
|
3
|
+
|
|
4
|
+
//#region src/server/react/resolveLocale.ts
|
|
5
|
+
/**
|
|
6
|
+
* Locale for the synchronous server hooks, resolved the way `getLocale()`
|
|
7
|
+
* resolves it — so server-rendered output and the client provider never
|
|
8
|
+
* disagree about which locale the request is in.
|
|
9
|
+
*
|
|
10
|
+
* 1. The locale forwarded through `setRequestLocale(locale)` (the `[locale]`
|
|
11
|
+
* route segment), which is next-intl's source of truth for URL routing.
|
|
12
|
+
* 2. Otherwise Intlayer's ambient locale (server context, then the request).
|
|
13
|
+
*
|
|
14
|
+
* The second rung must stay lazy. It ends in `headers()` / `cookies()`, which
|
|
15
|
+
* opts the route into dynamic rendering: evaluating it eagerly took this
|
|
16
|
+
* package's own benchmark app from 14 prerendered pages to 0.
|
|
17
|
+
*/
|
|
18
|
+
const resolveServerLocale = () => {
|
|
19
|
+
const requestLocale = getCachedRequestLocale();
|
|
20
|
+
if (requestLocale) return requestLocale;
|
|
21
|
+
return useLocale().locale;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { resolveServerLocale };
|
|
26
|
+
//# sourceMappingURL=resolveLocale.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveLocale.mjs","names":["readAmbientLocale"],"sources":["../../../../src/server/react/resolveLocale.ts"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\n// Not a React hook despite the name: `next-intlayer/server` prefixes its\n// server readers with `use` for symmetry with the client API, but they hold no\n// positional state — its own `resolveFallbackLocale` documents that this is\n// exactly what lets them run conditionally. Bound to a plain name here so the\n// call below reads as what it is.\nimport { useLocale as readAmbientLocale } from 'next-intlayer/server';\nimport { getCachedRequestLocale } from '../requestLocaleCache';\n\n/**\n * Locale for the synchronous server hooks, resolved the way `getLocale()`\n * resolves it — so server-rendered output and the client provider never\n * disagree about which locale the request is in.\n *\n * 1. The locale forwarded through `setRequestLocale(locale)` (the `[locale]`\n * route segment), which is next-intl's source of truth for URL routing.\n * 2. Otherwise Intlayer's ambient locale (server context, then the request).\n *\n * The second rung must stay lazy. It ends in `headers()` / `cookies()`, which\n * opts the route into dynamic rendering: evaluating it eagerly took this\n * package's own benchmark app from 14 prerendered pages to 0.\n */\nexport const resolveServerLocale = (): LocalesValues => {\n const requestLocale = getCachedRequestLocale();\n if (requestLocale) return requestLocale as LocalesValues;\n\n return readAmbientLocale().locale as LocalesValues;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAsBA,MAAa,4BAA2C;CACtD,MAAM,gBAAgB,uBAAuB;CAC7C,IAAI,eAAe,OAAO;CAE1B,OAAOA,UAAkB,CAAC,CAAC;AAC7B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { useDictionary as useDictionary$1 } from "next-intlayer/server";
|
|
4
|
+
|
|
5
|
+
//#region src/server/react/useDictionary.ts
|
|
6
|
+
/**
|
|
7
|
+
* Server counterpart of `@intlayer/use-intl`'s `useDictionary`.
|
|
8
|
+
*
|
|
9
|
+
* The optimize pass rewrites every `useTranslations(...)` call to this helper
|
|
10
|
+
* with the dictionary pre-imported. Resolving it here — rather than in a client
|
|
11
|
+
* component — keeps the dictionary out of the client bundle entirely: the
|
|
12
|
+
* server renders the text and only the rendered output crosses the boundary.
|
|
13
|
+
*/
|
|
14
|
+
const useDictionary = ((dictionary, namespacePrefix) => {
|
|
15
|
+
const locale = resolveServerLocale();
|
|
16
|
+
const content = useDictionary$1(dictionary, locale);
|
|
17
|
+
return createDictionaryTranslator(locale, content, namespacePrefix);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { useDictionary };
|
|
22
|
+
//# sourceMappingURL=useDictionary.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionary.mjs","names":["useDictionaryBase"],"sources":["../../../../src/server/react/useDictionary.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { DictionaryKeys } from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type ScopedTranslateFunction,\n type TranslateFunction,\n} from '@intlayer/use-intl';\nimport { useDictionary as useDictionaryBase } from 'next-intlayer/server';\nimport { resolveServerLocale } from './resolveLocale';\n\n/**\n * Overload set mirroring the client `useDictionary` exactly, so the optimize\n * pass can emit the same call shape whichever side of the boundary the\n * component ends up on.\n */\ntype UseDictionary = {\n <T extends Dictionary>(\n dictionary: T\n ): TranslateFunction<T['key'] & DictionaryKeys>;\n <T extends Dictionary, Prefix extends string>(\n dictionary: T,\n namespacePrefix: Prefix\n ): ScopedTranslateFunction<T['key'] & DictionaryKeys, Prefix>;\n};\n\n/**\n * Server counterpart of `@intlayer/use-intl`'s `useDictionary`.\n *\n * The optimize pass rewrites every `useTranslations(...)` call to this helper\n * with the dictionary pre-imported. Resolving it here — rather than in a client\n * component — keeps the dictionary out of the client bundle entirely: the\n * server renders the text and only the rendered output crosses the boundary.\n */\nexport const useDictionary = (<T extends Dictionary>(\n dictionary: T,\n namespacePrefix?: string\n) => {\n const locale = resolveServerLocale();\n const content = useDictionaryBase(dictionary, locale as never);\n\n return createDictionaryTranslator(locale, content, namespacePrefix);\n}) as UseDictionary;\n"],"mappings":";;;;;;;;;;;;;AAiCA,MAAa,kBACX,YACA,oBACG;CACH,MAAM,SAAS,oBAAoB;CACnC,MAAM,UAAUA,gBAAkB,YAAY,MAAe;CAE7D,OAAO,2BAA2B,QAAQ,SAAS,eAAe;AACpE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { useDictionaryDynamic as useDictionaryDynamic$1 } from "next-intlayer/server";
|
|
4
|
+
|
|
5
|
+
//#region src/server/react/useDictionaryDynamic.ts
|
|
6
|
+
/**
|
|
7
|
+
* Server counterpart of `useDictionaryDynamic`, emitted by the optimize pass
|
|
8
|
+
* for dictionaries on the per-locale loader.
|
|
9
|
+
*/
|
|
10
|
+
const useDictionaryDynamic = ((dictionaryPromise, key, namespacePrefix) => {
|
|
11
|
+
const locale = resolveServerLocale();
|
|
12
|
+
const content = useDictionaryDynamic$1(dictionaryPromise, key, locale);
|
|
13
|
+
return createDictionaryTranslator(locale, content, namespacePrefix);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { useDictionaryDynamic };
|
|
18
|
+
//# sourceMappingURL=useDictionaryDynamic.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionaryDynamic.mjs","names":["useDictionaryDynamicBase"],"sources":["../../../../src/server/react/useDictionaryDynamic.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport type { DictionaryKeys } from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type ScopedTranslateFunction,\n type TranslateFunction,\n} from '@intlayer/use-intl';\nimport { useDictionaryDynamic as useDictionaryDynamicBase } from 'next-intlayer/server';\nimport { resolveServerLocale } from './resolveLocale';\n\ntype UseDictionaryDynamic = {\n <T extends Dictionary, K extends DictionaryKeys>(\n dictionaryPromise: Record<string, () => Promise<T>>,\n key: K\n ): TranslateFunction<K>;\n <T extends Dictionary, K extends DictionaryKeys, Prefix extends string>(\n dictionaryPromise: Record<string, () => Promise<T>>,\n key: K,\n namespacePrefix: Prefix\n ): ScopedTranslateFunction<K, Prefix>;\n};\n\n/**\n * Server counterpart of `useDictionaryDynamic`, emitted by the optimize pass\n * for dictionaries on the per-locale loader.\n */\nexport const useDictionaryDynamic = ((\n dictionaryPromise: Record<string, () => Promise<Dictionary>>,\n key: string,\n namespacePrefix?: string\n) => {\n const locale = resolveServerLocale();\n const content = useDictionaryDynamicBase(\n dictionaryPromise as never,\n key as never,\n locale as never\n );\n\n return createDictionaryTranslator(locale, content, namespacePrefix);\n}) as UseDictionaryDynamic;\n"],"mappings":";;;;;;;;;AA0BA,MAAa,yBACX,mBACA,KACA,oBACG;CACH,MAAM,SAAS,oBAAoB;CACnC,MAAM,UAAUA,uBACd,mBACA,KACA,MACF;CAEA,OAAO,2BAA2B,QAAQ,SAAS,eAAe;AACpE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/server/react/useLocale.ts
|
|
4
|
+
/**
|
|
5
|
+
* Server counterpart of `useLocale`, resolved from the `[locale]` route segment
|
|
6
|
+
* forwarded through `setRequestLocale` when the app provides one.
|
|
7
|
+
*/
|
|
8
|
+
const useLocale = () => resolveServerLocale();
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useLocale };
|
|
12
|
+
//# sourceMappingURL=useLocale.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLocale.mjs","names":[],"sources":["../../../../src/server/react/useLocale.ts"],"sourcesContent":["import type { useLocale as _useLocale } from 'next-intl';\nimport { resolveServerLocale } from './resolveLocale';\n\n/**\n * Server counterpart of `useLocale`, resolved from the `[locale]` route segment\n * forwarded through `setRequestLocale` when the app provides one.\n */\nexport const useLocale: typeof _useLocale = () =>\n resolveServerLocale() as ReturnType<typeof _useLocale>;\n"],"mappings":";;;;;;;AAOA,MAAa,kBACX,oBAAoB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { resolveServerLocale } from "./resolveLocale.mjs";
|
|
2
|
+
import { createDictionaryTranslator } from "@intlayer/use-intl";
|
|
3
|
+
import { getIntlayer } from "@intlayer/core/interpreter";
|
|
4
|
+
|
|
5
|
+
//#region src/server/react/useTranslations.ts
|
|
6
|
+
/** Splits `'about.counter'` into the dictionary key and its key prefix. */
|
|
7
|
+
const splitNamespace = (namespace) => {
|
|
8
|
+
const dotPosition = namespace.indexOf(".");
|
|
9
|
+
if (dotPosition === -1) return [namespace, void 0];
|
|
10
|
+
return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Server counterpart of `useTranslations`.
|
|
14
|
+
*
|
|
15
|
+
* next-intl's `useTranslations` is isomorphic — the same component code runs in
|
|
16
|
+
* a Server or a Client Component — so the adapter has to be too. Without this
|
|
17
|
+
* every component calling it is forced across the client boundary, which drags
|
|
18
|
+
* its dictionary into a client chunk that Next shares across every locale.
|
|
19
|
+
*
|
|
20
|
+
* The optimize pass normally rewrites these calls to `useDictionary` with the
|
|
21
|
+
* dictionary inlined; this runtime path covers the calls it could not resolve
|
|
22
|
+
* statically (a dynamic namespace, or an unoptimized build).
|
|
23
|
+
*/
|
|
24
|
+
const useTranslations = ((namespace) => {
|
|
25
|
+
const locale = resolveServerLocale();
|
|
26
|
+
if (!namespace) {
|
|
27
|
+
const rootTranslator = (key, values) => {
|
|
28
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(key);
|
|
29
|
+
const content = getIntlayer(dictionaryKey, locale);
|
|
30
|
+
return createDictionaryTranslator(locale, content, void 0)(keyPrefix ?? "", values);
|
|
31
|
+
};
|
|
32
|
+
return rootTranslator;
|
|
33
|
+
}
|
|
34
|
+
const [dictionaryKey, keyPrefix] = splitNamespace(namespace);
|
|
35
|
+
const content = getIntlayer(dictionaryKey, locale);
|
|
36
|
+
return createDictionaryTranslator(locale, content, keyPrefix);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { useTranslations };
|
|
41
|
+
//# sourceMappingURL=useTranslations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslations.mjs","names":[],"sources":["../../../../src/server/react/useTranslations.ts"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport type { DictionaryKeys } from '@intlayer/types/module_augmentation';\nimport {\n createDictionaryTranslator,\n type LooseTranslateFunction,\n type TranslateFunction,\n type TranslateFunctionForNamespace,\n} from '@intlayer/use-intl';\nimport { resolveServerLocale } from './resolveLocale';\n\ntype UseTranslations = {\n <N extends DictionaryKeys>(namespace: N): TranslateFunction<N>;\n <N extends `${string}.${string}`>(\n namespace: N\n ): TranslateFunctionForNamespace<N>;\n (): LooseTranslateFunction;\n};\n\n/** Splits `'about.counter'` into the dictionary key and its key prefix. */\nconst splitNamespace = (namespace: string): [string, string | undefined] => {\n const dotPosition = namespace.indexOf('.');\n if (dotPosition === -1) return [namespace, undefined];\n return [namespace.slice(0, dotPosition), namespace.slice(dotPosition + 1)];\n};\n\n/**\n * Server counterpart of `useTranslations`.\n *\n * next-intl's `useTranslations` is isomorphic — the same component code runs in\n * a Server or a Client Component — so the adapter has to be too. Without this\n * every component calling it is forced across the client boundary, which drags\n * its dictionary into a client chunk that Next shares across every locale.\n *\n * The optimize pass normally rewrites these calls to `useDictionary` with the\n * dictionary inlined; this runtime path covers the calls it could not resolve\n * statically (a dynamic namespace, or an unoptimized build).\n */\nexport const useTranslations = ((namespace?: string) => {\n const locale = resolveServerLocale();\n\n if (!namespace) {\n // Root scope: the first segment of each message id names the dictionary,\n // so the lookup can only happen per call.\n const rootTranslator = (key: string, values?: Record<string, unknown>) => {\n const [dictionaryKey, keyPrefix] = splitNamespace(key);\n const content = getIntlayer(dictionaryKey as never, locale as never);\n const translate = createDictionaryTranslator(locale, content, undefined);\n return translate(keyPrefix ?? '', values as never);\n };\n return rootTranslator as unknown as LooseTranslateFunction;\n }\n\n const [dictionaryKey, keyPrefix] = splitNamespace(namespace);\n const content = getIntlayer(dictionaryKey as never, locale as never);\n\n return createDictionaryTranslator(locale, content, keyPrefix);\n}) as UseTranslations;\n"],"mappings":";;;;;;AAmBA,MAAM,kBAAkB,cAAoD;CAC1E,MAAM,cAAc,UAAU,QAAQ,GAAG;CACzC,IAAI,gBAAgB,IAAI,OAAO,CAAC,WAAW,MAAS;CACpD,OAAO,CAAC,UAAU,MAAM,GAAG,WAAW,GAAG,UAAU,MAAM,cAAc,CAAC,CAAC;AAC3E;;;;;;;;;;;;;AAcA,MAAa,oBAAoB,cAAuB;CACtD,MAAM,SAAS,oBAAoB;CAEnC,IAAI,CAAC,WAAW;EAGd,MAAM,kBAAkB,KAAa,WAAqC;GACxE,MAAM,CAAC,eAAe,aAAa,eAAe,GAAG;GACrD,MAAM,UAAU,YAAY,eAAwB,MAAe;GAEnE,OADkB,2BAA2B,QAAQ,SAAS,MAC/C,CAAC,CAAC,aAAa,IAAI,MAAe;EACnD;EACA,OAAO;CACT;CAEA,MAAM,CAAC,eAAe,aAAa,eAAe,SAAS;CAC3D,MAAM,UAAU,YAAY,eAAwB,MAAe;CAEnE,OAAO,2BAA2B,QAAQ,SAAS,SAAS;AAC9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugin/index.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugin/index.ts"],"mappings":";;;;;;;qBA0Ia,uBAAoB,wBAAsB,aAC3B,eAAkB,QAAQ"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/react-server/helpers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Server counterparts of use-intl's ambient hooks. They mirror the client
|
|
4
|
+
* versions' signatures so the same component code type-checks on both sides.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useFormatter: typeof import('@intlayer/use-intl').useFormatter;
|
|
7
|
+
/** Current time on the server render. */
|
|
8
|
+
export declare const useNow: typeof import('@intlayer/use-intl').useNow;
|
|
9
|
+
/** Time zone used by the formatters; UTC unless the app overrides it. */
|
|
10
|
+
export declare const useTimeZone: typeof import('@intlayer/use-intl').useTimeZone;
|
|
11
|
+
//#endregion
|
|
12
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","names":[],"sources":["../../../src/react-server/helpers.ts"],"mappings":";;;;;qBAOa,kDAAkD;;qBAIlD,4CAA4C;;qBAI5C,iDAAiD"}
|