@intlayer/next-i18next 9.4.3 → 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 +1 -26
- package/dist/cjs/plugin/index.cjs.map +1 -1
- package/dist/esm/plugin/index.mjs +2 -27
- package/dist/esm/plugin/index.mjs.map +1 -1
- package/dist/types/appWithTranslation.d.ts +1 -2
- package/dist/types/appWithTranslation.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/plugin/index.d.ts +3 -3
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/serverSideTranslations.d.ts +1 -2
- package/dist/types/serverSideTranslations.d.ts.map +1 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -69,8 +69,6 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
|
|
|
69
69
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
|
|
70
70
|
| <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
|
|
71
71
|
|
|
72
|
-
---
|
|
73
|
-
|
|
74
72
|
## 📦 Installation
|
|
75
73
|
|
|
76
74
|
Start your journey with Intlayer today and experience a smoother, more powerful approach to internationalization.
|
|
@@ -83,29 +83,6 @@ const resolveEsmPath = (specifier) => {
|
|
|
83
83
|
*/
|
|
84
84
|
const toTurbopackAlias = (absolutePath) => `./${(0, node_path.relative)(process.cwd(), absolutePath).split(node_path.sep).join("/")}`;
|
|
85
85
|
/**
|
|
86
|
-
* SWC extra-caller configs derived from the shared caller registry
|
|
87
|
-
* (`@intlayer/config/callers`) — the single source of truth also consumed by
|
|
88
|
-
* the babel analyzer/optimizer and the LSP.
|
|
89
|
-
*/
|
|
90
|
-
const NEXT_I18NEXT_SWC_CALLERS = (0, _intlayer_config_callers.toSwcExtraCallers)(_intlayer_config_callers.REACT_I18NEXT_CALLERS);
|
|
91
|
-
/**
|
|
92
|
-
* Disables the SWC `replaceDictionaryEntry` optimization on the resolved Next.js
|
|
93
|
-
* config so the runtime dictionary registry stays populated. Mutates the
|
|
94
|
-
* `@intlayer/swc` plugin options in place (both webpack and Turbopack read the
|
|
95
|
-
* same `experimental.swcPlugins` entry).
|
|
96
|
-
*
|
|
97
|
-
* @param config - The Next.js config returned by `withIntlayer`.
|
|
98
|
-
*/
|
|
99
|
-
const keepDictionaryRegistry = (config) => {
|
|
100
|
-
const swcPlugins = config.experimental?.swcPlugins;
|
|
101
|
-
if (!Array.isArray(swcPlugins)) return;
|
|
102
|
-
for (const plugin of swcPlugins) {
|
|
103
|
-
if (!Array.isArray(plugin)) continue;
|
|
104
|
-
const [pluginPath, pluginOptions] = plugin;
|
|
105
|
-
if (typeof pluginPath === "string" && pluginPath.includes("@intlayer/swc") && pluginOptions !== null && typeof pluginOptions === "object") pluginOptions.replaceDictionaryEntry = false;
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
86
|
* A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin
|
|
110
87
|
* and configures resolve aliases so `next-i18next` imports are served by
|
|
111
88
|
* `@intlayer/next-i18next`.
|
|
@@ -143,9 +120,7 @@ const createNextI18nPlugin = (_i18nPath) => {
|
|
|
143
120
|
}
|
|
144
121
|
}
|
|
145
122
|
};
|
|
146
|
-
|
|
147
|
-
keepDictionaryRegistry(finalConfig);
|
|
148
|
-
return finalConfig;
|
|
123
|
+
return await (0, next_intlayer_server.withIntlayer)(mergedConfig, { compatCallers: _intlayer_config_callers.REACT_I18NEXT_CALLERS });
|
|
149
124
|
};
|
|
150
125
|
};
|
|
151
126
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["createRequire","dirname","resolve","relative","sep","toSwcExtraCallers","REACT_I18NEXT_CALLERS","getConfiguration","getAppLogger","join","colorize","ANSIColors","withIntlayer"],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport {\n REACT_I18NEXT_CALLERS,\n toSwcExtraCallers,\n} 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 import specifier (next-i18next, react-i18next, i18next) to\n * the `@intlayer/*` specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-i18next', replacement: '@intlayer/next-i18next' },\n { request: 'react-i18next', replacement: '@intlayer/react-i18next' },\n { request: 'i18next', replacement: '@intlayer/i18next' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/react-i18next` or `i18next`.\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/react-i18next`.\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/react-i18next/...`.\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_I18NEXT_SWC_CALLERS = toSwcExtraCallers(REACT_I18NEXT_CALLERS);\n\n/**\n * Disables the SWC `replaceDictionaryEntry` optimization on the resolved Next.js\n * config so the runtime dictionary registry stays populated. Mutates the\n * `@intlayer/swc` plugin options in place (both webpack and Turbopack read the\n * same `experimental.swcPlugins` entry).\n *\n * @param config - The Next.js config returned by `withIntlayer`.\n */\nconst keepDictionaryRegistry = (config: NextConfig): void => {\n const swcPlugins = (\n config.experimental as { swcPlugins?: unknown[] } | undefined\n )?.swcPlugins;\n if (!Array.isArray(swcPlugins)) return;\n\n for (const plugin of swcPlugins) {\n if (!Array.isArray(plugin)) continue;\n const [pluginPath, pluginOptions] = plugin as [unknown, unknown];\n if (\n typeof pluginPath === 'string' &&\n pluginPath.includes('@intlayer/swc') &&\n pluginOptions !== null &&\n typeof pluginOptions === 'object'\n ) {\n (pluginOptions as Record<string, unknown>).replaceDictionaryEntry = false;\n }\n }\n};\n\n/**\n * A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-i18next` imports are served by\n * `@intlayer/next-i18next`.\n */\nexport const createNextI18nPlugin = (_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,\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 const finalConfig = await withIntlayer(mergedConfig, {\n swcExtraCallers: NEXT_I18NEXT_SWC_CALLERS,\n });\n\n // i18next exposes runtime namespace APIs (`i18n.getFixedT(locale, ns)`,\n // `t('ns:key')`) that resolve dictionaries at runtime through `getIntlayer`.\n // Unlike `useTranslation('ns')`, these are not statically analyzable, so the\n // SWC cannot rewrite them to direct dictionary imports. The build optimization\n // normally empties the runtime dictionary registry (`replaceDictionaryEntry`),\n // which would make those APIs fall back to raw keys on the server. Keeping the\n // registry populated restores them; statically analyzable call sites are still\n // rewritten to direct imports, so client bundles stay tree-shaken.\n keepDictionaryRegistry(finalConfig);\n\n return finalConfig;\n };\n};\n\nexport default createNextI18nPlugin;\n\n/**\n * A pre-instantiated Next.js plugin for next-i18next compat.\n * Wraps a NextConfig directly without requiring the factory call pattern.\n *\n * Usage:\n * ```ts\n * import { withI18next } from '@intlayer/next-i18next/plugin';\n * export default withI18next(nextConfig);\n * ```\n */\nexport const withI18next = createNextI18nPlugin();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["createRequire","dirname","resolve","relative","sep","getConfiguration","getAppLogger","join","colorize","ANSIColors","withIntlayer","REACT_I18NEXT_CALLERS"],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join, relative, resolve, sep } from 'node:path';\nimport { REACT_I18NEXT_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 import specifier (next-i18next, react-i18next, i18next) to\n * the `@intlayer/*` specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-i18next', replacement: '@intlayer/next-i18next' },\n { request: 'react-i18next', replacement: '@intlayer/react-i18next' },\n { request: 'i18next', replacement: '@intlayer/i18next' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/react-i18next` or `i18next`.\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/react-i18next`.\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/react-i18next/...`.\n */\nconst toTurbopackAlias = (absolutePath: string): string =>\n `./${relative(process.cwd(), absolutePath).split(sep).join('/')}`;\n\n/**\n * A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-i18next` imports are served by\n * `@intlayer/next-i18next`.\n */\nexport const createNextI18nPlugin = (_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,\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 return await withIntlayer(mergedConfig, {\n compatCallers: REACT_I18NEXT_CALLERS,\n });\n };\n};\n\nexport default createNextI18nPlugin;\n\n/**\n * A pre-instantiated Next.js plugin for next-i18next compat.\n * Wraps a NextConfig directly without requiring the factory call pattern.\n *\n * Usage:\n * ```ts\n * import { withI18next } from '@intlayer/next-i18next/plugin';\n * export default withI18next(nextConfig);\n * ```\n */\nexport const withI18next = createNextI18nPlugin();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAeA,MAAM,oBAAgBA,wEAA6B;;;;;AAMnD,MAAM,gBAA4D;CAChE;EAAE,SAAS;EAAgB,aAAa;CAAyB;CACjE;EAAE,SAAS;EAAiB,aAAa;CAA0B;CACnE;EAAE,SAAS;EAAW,aAAa;CAAoB;AACzD;;;;;;;;AASA,MAAM,kBACJ,cAC+C;CAC/C,MAAM,WAAW,UAAU,MAAM,GAAG;CACpC,MAAM,cAAc,UAAU,WAAW,GAAG,IACxC,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAC5B,SAAS,MAAM;CACpB,MAAM,UAAU,UAAU,MAAM,YAAY,MAAM;CAClD,OAAO;EAAE;EAAa,WAAW,YAAY,KAAK,MAAM,IAAI;CAAU;AACxE;;;;;;;;;;;;AAaA,MAAM,kBAAkB,cAA8B;CACpD,MAAM,EAAE,aAAa,cAAc,eAAe,SAAS;CAC3D,MAAM,cAAc,cAAc,GAAG,YAAY,cAAc;CAM/D,MAAM,iBAAaC,mBACjB,cAAc,QAAQ,GAAG,YAAY,cAAc,CACrD;CAEA,MAAM,cAAc,YAAY,UAAU;CAC1C,MAAM,eACJ,OAAO,gBAAgB,WACnB,cACC,aAAa,UAAU,aAAa,WAAW,aAAa;CAGnE,IAAI,CAAC,cAAc,OAAO,cAAc,QAAQ,SAAS;CAEzD,WAAOC,mBAAQ,YAAY,YAAY;AACzC;;;;;;;;;;;AAYA,MAAM,oBAAoB,iBACxB,SAAKC,oBAAS,QAAQ,IAAI,GAAG,YAAY,CAAC,CAAC,MAAMC,aAAG,CAAC,CAAC,KAAK,GAAG;;;;;;AAOhE,MAAa,wBAAwB,cAAuB;CAC1D,OAAO,OAAO,aAAyB,CAAC,MAA2B;EACjE,MAAM,qBAAiBC,wCAAiB;EACxC,MAAM,gBAAYC,sCAAa,cAAc;EAE7C,wCACEC,gBACE,eAAe,OAAO,SACtB,aACA,SACA,iCACF,SACM;GACJ,UAAU,KACRC,kCACE,+CACAC,wBAAW,IACb,OACAD,kCACE,iDACAC,wBAAW,UACb,CACF,CAAC;EACH,GACA,EACE,gBAAgB,KAClB,CACF;EAEA,MAAM,gBAAgB,WAAW;EAEjC,MAAM,kBAAkB,cAAc,KAAK,EAAE,SAAS,mBAAmB;GACvE;GACA,cAAc,eAAe,WAAW;EAC1C,EAAE;EAGF,MAAM,eAAe,OAAO,YAC1B,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,YACF,CAAC,CACH;EAGA,MAAM,aAAa,OAAO,YACxB,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,iBAAiB,YAAY,CAC/B,CAAC,CACH;EAEA,MAAM,cAAc,EAClB,UAAU,QAAa,YAAiB;GACtC,OAAO,QAAQ,QAAQ;IACrB,GAAG,OAAO,QAAQ;IAClB,GAAG;GACL;GAEA,IAAI,OAAO,kBAAkB,YAC3B,OAAO,cAAc,QAAQ,OAAO;GAEtC,OAAO;EACT,EACF;EAEA,MAAM,eAA2B;GAC/B,GAAG;GACH,GAAG;GACH,WAAW;IACT,GAAI,WAAW,aAAa,CAAC;IAC7B,cAAc;KACZ,GAAI,WAAW,WAAW,gBAAgB,CAAC;KAC3C,GAAG;IACL;GACF;EACF;EAEA,OAAO,UAAMC,mCAAa,cAAc,EACtC,eAAeC,+CACjB,CAAC;CACH;AACF;;;;;;;;;;;AAcA,MAAa,cAAc,qBAAqB"}
|
|
@@ -2,7 +2,7 @@ import * as ANSIColors from "@intlayer/config/colors";
|
|
|
2
2
|
import { colorize, getAppLogger } from "@intlayer/config/logger";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
5
|
-
import { REACT_I18NEXT_CALLERS
|
|
5
|
+
import { REACT_I18NEXT_CALLERS } from "@intlayer/config/callers";
|
|
6
6
|
import { getConfiguration } from "@intlayer/config/node";
|
|
7
7
|
import { runOnce } from "@intlayer/engine/utils";
|
|
8
8
|
import { withIntlayer } from "next-intlayer/server";
|
|
@@ -80,29 +80,6 @@ const resolveEsmPath = (specifier) => {
|
|
|
80
80
|
*/
|
|
81
81
|
const toTurbopackAlias = (absolutePath) => `./${relative(process.cwd(), absolutePath).split(sep).join("/")}`;
|
|
82
82
|
/**
|
|
83
|
-
* SWC extra-caller configs derived from the shared caller registry
|
|
84
|
-
* (`@intlayer/config/callers`) — the single source of truth also consumed by
|
|
85
|
-
* the babel analyzer/optimizer and the LSP.
|
|
86
|
-
*/
|
|
87
|
-
const NEXT_I18NEXT_SWC_CALLERS = toSwcExtraCallers(REACT_I18NEXT_CALLERS);
|
|
88
|
-
/**
|
|
89
|
-
* Disables the SWC `replaceDictionaryEntry` optimization on the resolved Next.js
|
|
90
|
-
* config so the runtime dictionary registry stays populated. Mutates the
|
|
91
|
-
* `@intlayer/swc` plugin options in place (both webpack and Turbopack read the
|
|
92
|
-
* same `experimental.swcPlugins` entry).
|
|
93
|
-
*
|
|
94
|
-
* @param config - The Next.js config returned by `withIntlayer`.
|
|
95
|
-
*/
|
|
96
|
-
const keepDictionaryRegistry = (config) => {
|
|
97
|
-
const swcPlugins = config.experimental?.swcPlugins;
|
|
98
|
-
if (!Array.isArray(swcPlugins)) return;
|
|
99
|
-
for (const plugin of swcPlugins) {
|
|
100
|
-
if (!Array.isArray(plugin)) continue;
|
|
101
|
-
const [pluginPath, pluginOptions] = plugin;
|
|
102
|
-
if (typeof pluginPath === "string" && pluginPath.includes("@intlayer/swc") && pluginOptions !== null && typeof pluginOptions === "object") pluginOptions.replaceDictionaryEntry = false;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
83
|
* A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin
|
|
107
84
|
* and configures resolve aliases so `next-i18next` imports are served by
|
|
108
85
|
* `@intlayer/next-i18next`.
|
|
@@ -140,9 +117,7 @@ const createNextI18nPlugin = (_i18nPath) => {
|
|
|
140
117
|
}
|
|
141
118
|
}
|
|
142
119
|
};
|
|
143
|
-
|
|
144
|
-
keepDictionaryRegistry(finalConfig);
|
|
145
|
-
return finalConfig;
|
|
120
|
+
return await withIntlayer(mergedConfig, { compatCallers: REACT_I18NEXT_CALLERS });
|
|
146
121
|
};
|
|
147
122
|
};
|
|
148
123
|
/**
|
|
@@ -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 {\n REACT_I18NEXT_CALLERS,\n toSwcExtraCallers,\n} 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 import specifier (next-i18next, react-i18next, i18next) to\n * the `@intlayer/*` specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-i18next', replacement: '@intlayer/next-i18next' },\n { request: 'react-i18next', replacement: '@intlayer/react-i18next' },\n { request: 'i18next', replacement: '@intlayer/i18next' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/react-i18next` or `i18next`.\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/react-i18next`.\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/react-i18next/...`.\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_I18NEXT_SWC_CALLERS = toSwcExtraCallers(REACT_I18NEXT_CALLERS);\n\n/**\n * Disables the SWC `replaceDictionaryEntry` optimization on the resolved Next.js\n * config so the runtime dictionary registry stays populated. Mutates the\n * `@intlayer/swc` plugin options in place (both webpack and Turbopack read the\n * same `experimental.swcPlugins` entry).\n *\n * @param config - The Next.js config returned by `withIntlayer`.\n */\nconst keepDictionaryRegistry = (config: NextConfig): void => {\n const swcPlugins = (\n config.experimental as { swcPlugins?: unknown[] } | undefined\n )?.swcPlugins;\n if (!Array.isArray(swcPlugins)) return;\n\n for (const plugin of swcPlugins) {\n if (!Array.isArray(plugin)) continue;\n const [pluginPath, pluginOptions] = plugin as [unknown, unknown];\n if (\n typeof pluginPath === 'string' &&\n pluginPath.includes('@intlayer/swc') &&\n pluginOptions !== null &&\n typeof pluginOptions === 'object'\n ) {\n (pluginOptions as Record<string, unknown>).replaceDictionaryEntry = false;\n }\n }\n};\n\n/**\n * A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-i18next` imports are served by\n * `@intlayer/next-i18next`.\n */\nexport const createNextI18nPlugin = (_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,\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 const finalConfig = await withIntlayer(mergedConfig, {\n swcExtraCallers: NEXT_I18NEXT_SWC_CALLERS,\n });\n\n // i18next exposes runtime namespace APIs (`i18n.getFixedT(locale, ns)`,\n // `t('ns:key')`) that resolve dictionaries at runtime through `getIntlayer`.\n // Unlike `useTranslation('ns')`, these are not statically analyzable, so the\n // SWC cannot rewrite them to direct dictionary imports. The build optimization\n // normally empties the runtime dictionary registry (`replaceDictionaryEntry`),\n // which would make those APIs fall back to raw keys on the server. Keeping the\n // registry populated restores them; statically analyzable call sites are still\n // rewritten to direct imports, so client bundles stay tree-shaken.\n keepDictionaryRegistry(finalConfig);\n\n return finalConfig;\n };\n};\n\nexport default createNextI18nPlugin;\n\n/**\n * A pre-instantiated Next.js plugin for next-i18next compat.\n * Wraps a NextConfig directly without requiring the factory call pattern.\n *\n * Usage:\n * ```ts\n * import { withI18next } from '@intlayer/next-i18next/plugin';\n * export default withI18next(nextConfig);\n * ```\n */\nexport const withI18next = createNextI18nPlugin();\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 { REACT_I18NEXT_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 import specifier (next-i18next, react-i18next, i18next) to\n * the `@intlayer/*` specifier that should serve it instead.\n */\nconst ALIAS_ENTRIES: { request: string; replacement: string }[] = [\n { request: 'next-i18next', replacement: '@intlayer/next-i18next' },\n { request: 'react-i18next', replacement: '@intlayer/react-i18next' },\n { request: 'i18next', replacement: '@intlayer/i18next' },\n];\n\n/**\n * Split a package specifier into its package name and export subpath.\n *\n * @param specifier - e.g. `@intlayer/react-i18next` or `i18next`.\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/react-i18next`.\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/react-i18next/...`.\n */\nconst toTurbopackAlias = (absolutePath: string): string =>\n `./${relative(process.cwd(), absolutePath).split(sep).join('/')}`;\n\n/**\n * A Next.js plugin for next-i18next compat that wraps next-intlayer's plugin\n * and configures resolve aliases so `next-i18next` imports are served by\n * `@intlayer/next-i18next`.\n */\nexport const createNextI18nPlugin = (_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,\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 return await withIntlayer(mergedConfig, {\n compatCallers: REACT_I18NEXT_CALLERS,\n });\n };\n};\n\nexport default createNextI18nPlugin;\n\n/**\n * A pre-instantiated Next.js plugin for next-i18next compat.\n * Wraps a NextConfig directly without requiring the factory call pattern.\n *\n * Usage:\n * ```ts\n * import { withI18next } from '@intlayer/next-i18next/plugin';\n * export default withI18next(nextConfig);\n * ```\n */\nexport const withI18next = createNextI18nPlugin();\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,gBAAgB,cAAc,YAAY,GAAG;;;;;AAMnD,MAAM,gBAA4D;CAChE;EAAE,SAAS;EAAgB,aAAa;CAAyB;CACjE;EAAE,SAAS;EAAiB,aAAa;CAA0B;CACnE;EAAE,SAAS;EAAW,aAAa;CAAoB;AACzD;;;;;;;;AASA,MAAM,kBACJ,cAC+C;CAC/C,MAAM,WAAW,UAAU,MAAM,GAAG;CACpC,MAAM,cAAc,UAAU,WAAW,GAAG,IACxC,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAC5B,SAAS,MAAM;CACpB,MAAM,UAAU,UAAU,MAAM,YAAY,MAAM;CAClD,OAAO;EAAE;EAAa,WAAW,YAAY,KAAK,MAAM,IAAI;CAAU;AACxE;;;;;;;;;;;;AAaA,MAAM,kBAAkB,cAA8B;CACpD,MAAM,EAAE,aAAa,cAAc,eAAe,SAAS;CAC3D,MAAM,cAAc,cAAc,GAAG,YAAY,cAAc;CAM/D,MAAM,aAAa,QACjB,cAAc,QAAQ,GAAG,YAAY,cAAc,CACrD;CAEA,MAAM,cAAc,YAAY,UAAU;CAC1C,MAAM,eACJ,OAAO,gBAAgB,WACnB,cACC,aAAa,UAAU,aAAa,WAAW,aAAa;CAGnE,IAAI,CAAC,cAAc,OAAO,cAAc,QAAQ,SAAS;CAEzD,OAAO,QAAQ,YAAY,YAAY;AACzC;;;;;;;;;;;AAYA,MAAM,oBAAoB,iBACxB,KAAK,SAAS,QAAQ,IAAI,GAAG,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG;;;;;;AAOhE,MAAa,wBAAwB,cAAuB;CAC1D,OAAO,OAAO,aAAyB,CAAC,MAA2B;EACjE,MAAM,iBAAiB,iBAAiB;EACxC,MAAM,YAAY,aAAa,cAAc;EAE7C,QACE,KACE,eAAe,OAAO,SACtB,aACA,SACA,iCACF,SACM;GACJ,UAAU,CACR,SACE,+CACA,WAAW,IACb,GACA,SACE,iDACA,WAAW,UACb,CACF,CAAC;EACH,GACA,EACE,gBAAgB,KAClB,CACF;EAEA,MAAM,gBAAgB,WAAW;EAEjC,MAAM,kBAAkB,cAAc,KAAK,EAAE,SAAS,mBAAmB;GACvE;GACA,cAAc,eAAe,WAAW;EAC1C,EAAE;EAGF,MAAM,eAAe,OAAO,YAC1B,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,YACF,CAAC,CACH;EAGA,MAAM,aAAa,OAAO,YACxB,gBAAgB,KAAK,EAAE,SAAS,mBAAmB,CACjD,SACA,iBAAiB,YAAY,CAC/B,CAAC,CACH;EAEA,MAAM,cAAc,EAClB,UAAU,QAAa,YAAiB;GACtC,OAAO,QAAQ,QAAQ;IACrB,GAAG,OAAO,QAAQ;IAClB,GAAG;GACL;GAEA,IAAI,OAAO,kBAAkB,YAC3B,OAAO,cAAc,QAAQ,OAAO;GAEtC,OAAO;EACT,EACF;EAEA,MAAM,eAA2B;GAC/B,GAAG;GACH,GAAG;GACH,WAAW;IACT,GAAI,WAAW,aAAa,CAAC;IAC7B,cAAc;KACZ,GAAI,WAAW,WAAW,gBAAgB,CAAC;KAC3C,GAAG;IACL;GACF;EACF;EAEA,OAAO,MAAM,aAAa,cAAc,EACtC,eAAe,sBACjB,CAAC;CACH;AACF;;;;;;;;;;;AAcA,MAAa,cAAc,qBAAqB"}
|
|
@@ -11,7 +11,6 @@ import { appWithTranslation as appWithTranslation$1 } from "next-i18next/pages";
|
|
|
11
11
|
* export default appWithTranslation(MyApp);
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
|
-
declare const appWithTranslation: typeof appWithTranslation$1;
|
|
14
|
+
export declare const appWithTranslation: typeof appWithTranslation$1;
|
|
15
15
|
//#endregion
|
|
16
|
-
export { appWithTranslation };
|
|
17
16
|
//# sourceMappingURL=appWithTranslation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appWithTranslation.d.ts","names":[],"sources":["../../src/appWithTranslation.tsx"],"mappings":";;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"appWithTranslation.d.ts","names":[],"sources":["../../src/appWithTranslation.tsx"],"mappings":";;;;;;;;;;;;;qBAgBa,2BAA2B"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { serverSideTranslations } from "./serverSideTranslations.js";
|
|
|
3
3
|
import { i18n as i18n$1 } from "@intlayer/i18next";
|
|
4
4
|
import { I18nContext, I18nextProvider, Trans, Translation, initReactI18next, useDictionary, useDictionaryDynamic, useTranslation, withTranslation } from "@intlayer/react-i18next";
|
|
5
5
|
//#region src/index.d.ts
|
|
6
|
-
declare const i18n: i18n$1;
|
|
6
|
+
export declare const i18n: i18n$1;
|
|
7
7
|
//#endregion
|
|
8
|
-
export { I18nContext, I18nextProvider, Trans, Translation, appWithTranslation,
|
|
8
|
+
export { I18nContext, I18nextProvider, Trans, Translation, appWithTranslation, initReactI18next, serverSideTranslations, useDictionary, useDictionaryDynamic, useTranslation, withTranslation };
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;qBAEa,MAA6B"}
|
|
@@ -5,7 +5,7 @@ import { NextConfig } from "next";
|
|
|
5
5
|
* and configures resolve aliases so `next-i18next` imports are served by
|
|
6
6
|
* `@intlayer/next-i18next`.
|
|
7
7
|
*/
|
|
8
|
-
declare const createNextI18nPlugin: (_i18nPath?: string) => (nextConfig?: NextConfig) => Promise<NextConfig>;
|
|
8
|
+
export declare const createNextI18nPlugin: (_i18nPath?: string) => (nextConfig?: NextConfig) => Promise<NextConfig>;
|
|
9
9
|
/**
|
|
10
10
|
* A pre-instantiated Next.js plugin for next-i18next compat.
|
|
11
11
|
* Wraps a NextConfig directly without requiring the factory call pattern.
|
|
@@ -16,7 +16,7 @@ declare const createNextI18nPlugin: (_i18nPath?: string) => (nextConfig?: NextCo
|
|
|
16
16
|
* export default withI18next(nextConfig);
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
declare const withI18next: (nextConfig?: NextConfig) => Promise<NextConfig>;
|
|
19
|
+
export declare const withI18next: (nextConfig?: NextConfig) => Promise<NextConfig>;
|
|
20
20
|
//#endregion
|
|
21
|
-
export { createNextI18nPlugin
|
|
21
|
+
export { createNextI18nPlugin as default };
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -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":";;;;;;;qBAkGa,uBAAoB,wBAAsB,aAC3B,eAAkB,QAAQ;;;;;;;;;;;qBA+FzC,cAAW,aA/FI,eAAkB,QAAQ"}
|
|
@@ -25,9 +25,8 @@
|
|
|
25
25
|
* });
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
declare const serverSideTranslations: (locale: string, namespacesRequired?: string[], configOverride?: Record<string, unknown>) => Promise<{
|
|
28
|
+
export declare const serverSideTranslations: (locale: string, namespacesRequired?: string[], configOverride?: Record<string, unknown>) => Promise<{
|
|
29
29
|
_nextI18Next: Record<string, unknown>;
|
|
30
30
|
}>;
|
|
31
31
|
//#endregion
|
|
32
|
-
export { serverSideTranslations };
|
|
33
32
|
//# sourceMappingURL=serverSideTranslations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverSideTranslations.d.ts","names":[],"sources":["../../src/serverSideTranslations.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"serverSideTranslations.d.ts","names":[],"sources":["../../src/serverSideTranslations.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;qBA8Ba,yBAAsB,gBACnB,+BACe,iBACZ,4BAChB;EAAU,cAAc"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/next-i18next",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "next-i18next API adapter for intlayer — serverSideTranslations, appWithTranslation, useTranslation backed by next-intlayer",
|
|
6
6
|
"keywords": [
|
|
@@ -79,28 +79,28 @@
|
|
|
79
79
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@intlayer/config": "9.
|
|
83
|
-
"@intlayer/core": "9.
|
|
84
|
-
"@intlayer/engine": "9.
|
|
85
|
-
"@intlayer/i18next": "9.
|
|
86
|
-
"@intlayer/react-i18next": "9.
|
|
87
|
-
"@intlayer/types": "9.
|
|
88
|
-
"next-intlayer": "9.
|
|
89
|
-
"react-intlayer": "9.
|
|
82
|
+
"@intlayer/config": "9.5.0",
|
|
83
|
+
"@intlayer/core": "9.5.0",
|
|
84
|
+
"@intlayer/engine": "9.5.0",
|
|
85
|
+
"@intlayer/i18next": "9.5.0",
|
|
86
|
+
"@intlayer/react-i18next": "9.5.0",
|
|
87
|
+
"@intlayer/types": "9.5.0",
|
|
88
|
+
"next-intlayer": "9.5.0",
|
|
89
|
+
"react-intlayer": "9.5.0"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@types/node": "26.
|
|
92
|
+
"@types/node": "26.5.0",
|
|
93
93
|
"@types/react": "19.2.18",
|
|
94
94
|
"@utils/ts-config": "1.0.4",
|
|
95
95
|
"@utils/ts-config-types": "1.0.4",
|
|
96
96
|
"@utils/tsdown-config": "1.0.4",
|
|
97
|
-
"i18next": "26.
|
|
97
|
+
"i18next": "26.4.2",
|
|
98
98
|
"next-i18next": "16.0.8",
|
|
99
99
|
"react-i18next": "17.0.10",
|
|
100
100
|
"rimraf": "6.1.3",
|
|
101
|
-
"tsdown": "0.
|
|
101
|
+
"tsdown": "0.23.0",
|
|
102
102
|
"typescript": "7.0.2",
|
|
103
|
-
"vitest": "
|
|
103
|
+
"vitest": "5.0.0"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
106
|
"i18next": ">=20.0.0",
|