@intlify/unplugin-vue-i18n 7.0.0-beta.2 → 11.0.0-beta.4

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/lib/index.cjs CHANGED
@@ -2,36 +2,72 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const unplugin$1 = require('unplugin');
6
5
  const createDebug = require('debug');
7
- const pc = require('picocolors');
8
- const path = require('node:path');
9
- const defu = require('defu');
10
- const pathe = require('pathe');
11
- const bundleUtils = require('@intlify/bundle-utils');
6
+ const unplugin$1 = require('unplugin');
12
7
  const shared = require('@intlify/shared');
8
+ const bundleUtils = require('@intlify/bundle-utils');
13
9
  const pluginutils = require('@rollup/pluginutils');
14
10
  const fg = require('fast-glob');
15
- const fs = require('node:fs');
11
+ const node_fs = require('node:fs');
12
+ const path = require('node:path');
13
+ const pathe = require('pathe');
16
14
  const compilerSfc = require('vue/compiler-sfc');
17
- const knitwork = require('knitwork');
18
- const mlly = require('mlly');
19
- const node_crypto = require('node:crypto');
15
+ const pc = require('picocolors');
16
+ const eslintUitls = require('@eslint-community/eslint-utils');
20
17
  const vueI18nExtensions = require('@intlify/vue-i18n-extensions');
21
18
  const scopeManager = require('@typescript-eslint/scope-manager');
22
19
  const typescriptEstree = require('@typescript-eslint/typescript-estree');
23
- const eslintUitls = require('@eslint-community/eslint-utils');
24
20
 
25
21
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
26
22
 
27
23
  const createDebug__default = /*#__PURE__*/_interopDefaultCompat(createDebug);
28
- const pc__default = /*#__PURE__*/_interopDefaultCompat(pc);
29
- const path__default = /*#__PURE__*/_interopDefaultCompat(path);
30
- const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
31
24
  const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
32
- const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
25
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
26
+ const pc__default = /*#__PURE__*/_interopDefaultCompat(pc);
33
27
  const eslintUitls__default = /*#__PURE__*/_interopDefaultCompat(eslintUitls);
34
28
 
29
+ function resolveOptions(options) {
30
+ const moduleType = options.module || "vue-i18n";
31
+ let onlyLocales = [];
32
+ if (options.onlyLocales) {
33
+ onlyLocales = shared.isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
34
+ }
35
+ const forceStringify = !!options.forceStringify;
36
+ const defaultSFCLang = shared.isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
37
+ const globalSFCScope = !!options.globalSFCScope;
38
+ const runtimeOnly = shared.isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
39
+ const dropMessageCompiler = !!options.dropMessageCompiler;
40
+ const compositionOnly = moduleType === "vue-i18n" ? shared.isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
41
+ const fullInstall = moduleType === "vue-i18n" ? shared.isBoolean(options.fullInstall) ? options.fullInstall : true : false;
42
+ const ssrBuild = !!options.ssr;
43
+ const allowDynamic = !!options.allowDynamic;
44
+ const strictMessage = shared.isBoolean(options.strictMessage) ? options.strictMessage : true;
45
+ const escapeHtml = !!options.escapeHtml;
46
+ const optimizeTranslationDirective = shared.isString(options.optimizeTranslationDirective) || shared.isArray(options.optimizeTranslationDirective) ? options.optimizeTranslationDirective : !!options.optimizeTranslationDirective;
47
+ const translationIdentifiers = /* @__PURE__ */ new Map();
48
+ const transformI18nBlock = typeof options.transformI18nBlock === "function" ? options.transformI18nBlock : null;
49
+ return {
50
+ include: options.include,
51
+ exclude: options.exclude,
52
+ module: moduleType,
53
+ onlyLocales,
54
+ forceStringify,
55
+ defaultSFCLang,
56
+ globalSFCScope,
57
+ runtimeOnly,
58
+ dropMessageCompiler,
59
+ compositionOnly,
60
+ fullInstall,
61
+ ssrBuild,
62
+ allowDynamic,
63
+ strictMessage,
64
+ escapeHtml,
65
+ optimizeTranslationDirective,
66
+ translationIdentifiers,
67
+ transformI18nBlock
68
+ };
69
+ }
70
+
35
71
  const PKG_NAME = "unplugin-vue-i18n";
36
72
 
37
73
  function warn(...args) {
@@ -68,63 +104,11 @@ function normalizePath(id) {
68
104
  return path__default.posix.normalize(isWindows ? slash(id) : id);
69
105
  }
70
106
 
71
- function toArray(value) {
72
- return Array.isArray(value) ? value : [value];
73
- }
74
-
75
- const getVueI18nAliasPath = (opts) => {
76
- const filename = [
77
- opts.module,
78
- opts.runtimeOnly ? "runtime" : "",
79
- !opts.ssr ? "esm-bundler" : "node",
80
- "js"
81
- ].filter(Boolean).join(".");
82
- return `${opts.module}/dist/${filename}`;
83
- };
84
- function resolveOptions(options) {
85
- const res = defu__default(options, {
86
- ssr: false,
87
- module: "vue-i18n",
88
- escapeHtml: false,
89
- onlyLocales: [],
90
- fullInstall: true,
91
- runtimeOnly: true,
92
- strictMessage: true,
93
- allowDynamic: false,
94
- globalSFCScope: false,
95
- forceStringify: false,
96
- defaultSFCLang: "json",
97
- dropMessageCompiler: false,
98
- transformI18nBlock: void 0,
99
- optimizeTranslationDirective: false
100
- });
101
- const include = res.include ? toArray(res.include).map((item) => pathe.normalize(item)) : void 0;
102
- const _exclude = res.exclude ? toArray(res.exclude).map((item) => pathe.normalize(item)) : void 0;
103
- const exclude = res.include ? _exclude : ["**/**"];
104
- const onlyLocales = toArray(res.onlyLocales);
105
- const fullInstall = res.module !== "vue-i18n" ? false : res.fullInstall;
106
- const optimizeTranslationDirective = typeof res.optimizeTranslationDirective === "boolean" ? res.optimizeTranslationDirective : toArray(res.optimizeTranslationDirective);
107
- const translationIdentifiers = /* @__PURE__ */ new Map();
108
- const vueI18nAliasPath = getVueI18nAliasPath(res);
109
- return {
110
- ...res,
111
- include,
112
- exclude,
113
- fullInstall,
114
- onlyLocales,
115
- vueI18nAliasPath,
116
- translationIdentifiers,
117
- optimizeTranslationDirective
118
- };
119
- }
120
-
121
107
  function parseVueRequest(id) {
122
108
  const [filename, rawQuery] = id.split(`?`, 2);
123
109
  const params = new URLSearchParams(rawQuery);
124
110
  const ret = {};
125
- const langPart = Object.keys(Object.fromEntries(params)).find(
126
- (key) => /lang\./i.test(key)
127
- );
111
+ const langPart = Object.keys(Object.fromEntries(params)).find((key) => /lang\./i.test(key));
128
112
  ret.vue = params.has("vue");
129
113
  ret.global = params.has("global");
130
114
  ret.src = params.has("src");
@@ -185,85 +169,119 @@ function getDescriptor(filename, code, options) {
185
169
 
186
170
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
187
171
  const VIRTUAL_PREFIX = "\0";
172
+ const RE_INTLIFY_BUNDLE_IMPORT_ID = new RegExp(`^${INTLIFY_BUNDLE_IMPORT_ID}$`);
173
+ const RE_VIRTUAL_PREFIXED_INTLIFY_BUNDLE_IMPORT_ID = new RegExp(
174
+ `^${VIRTUAL_PREFIX}${INTLIFY_BUNDLE_IMPORT_ID}$`
175
+ );
176
+ const RE_RESOURCE_FORMAT = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
177
+ const RE_SFC_I18N_CUSTOM_BLOCK = /\?vue&type=i18n/;
178
+ const RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK = /blockType=i18n/;
188
179
  const debug$2 = createDebug__default(resolveNamespace("resource"));
189
- function resourcePlugin(opts, meta) {
190
- const _filter = pluginutils.createFilter(opts.include, opts.exclude);
191
- const importedResources = /* @__PURE__ */ new Set();
192
- const filter = (val) => _filter(val) || importedResources.has(val);
193
- debug$2(`vue-i18n alias name: ${opts.module}`);
194
- const ctx = {
195
- prod: false,
196
- sourceMap: false
197
- };
198
- let vuePlugin = null;
199
- const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
200
- const resourcePaths = /* @__PURE__ */ new Set();
201
- for (const inc of opts.include || []) {
202
- for (const resourcePath of fg__default.sync(inc, { ignore: opts.exclude })) {
203
- resourcePaths.add(resourcePath);
180
+ function resourcePlugin({
181
+ onlyLocales,
182
+ include,
183
+ exclude,
184
+ module,
185
+ forceStringify,
186
+ defaultSFCLang,
187
+ globalSFCScope,
188
+ runtimeOnly,
189
+ dropMessageCompiler,
190
+ compositionOnly,
191
+ fullInstall,
192
+ ssrBuild,
193
+ strictMessage,
194
+ allowDynamic,
195
+ escapeHtml,
196
+ transformI18nBlock
197
+ }, meta) {
198
+ let viteModule = null;
199
+ async function getViteModule() {
200
+ if (viteModule != null) {
201
+ return viteModule;
202
+ }
203
+ try {
204
+ viteModule = await import('vite');
205
+ } catch (e) {
206
+ error(`vite not found, please install vite.`, e.message);
207
+ throw e;
208
+ }
209
+ return viteModule;
210
+ }
211
+ function resolveIncludeExclude() {
212
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
213
+ if (shared.isArray(include)) {
214
+ return [[...include, customBlockInclude], exclude];
215
+ } else if (shared.isString(include)) {
216
+ return [[include, customBlockInclude], exclude];
217
+ } else {
218
+ return [[RE_RESOURCE_FORMAT, customBlockInclude], exclude];
204
219
  }
205
220
  }
206
- function result(code) {
207
- if (meta.framework === "vite") {
208
- return { code, map: { mappings: "" } };
221
+ function resolveIncludeExcludeForLegacy() {
222
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
223
+ let _include = void 0;
224
+ let _exclude = void 0;
225
+ if (include) {
226
+ if (shared.isArray(include)) {
227
+ _include = [...include.map((item) => pathe.normalize(item)), customBlockInclude];
228
+ } else if (shared.isString(include)) {
229
+ _include = [pathe.normalize(include), customBlockInclude];
230
+ }
231
+ } else {
232
+ _exclude = "**/**";
209
233
  }
210
- return { code };
234
+ return [_include, _exclude];
211
235
  }
212
- function sharedWebpackLikePlugin(compiler) {
213
- ctx.prod = compiler.options.mode !== "development";
214
- ctx.sourceMap = !!compiler.options.devtool;
215
- debug$2(
216
- `${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`
217
- );
218
- compiler.options.resolve.alias = {
219
- ...compiler.options.resolve.alias,
220
- [opts.module]: opts.vueI18nAliasPath
221
- };
222
- debug$2(`set ${opts.module}: ${opts.vueI18nAliasPath}`);
223
- const loader = meta.framework === "webpack" ? loadWebpack : loadRspack;
224
- loader().then((mod) => {
225
- if (mod) {
226
- compiler.options.plugins.push(
227
- // @ts-expect-error type issue
228
- new mod.DefinePlugin({
229
- __VUE_I18N_FULL_INSTALL__: JSON.stringify(opts.fullInstall),
230
- __INTLIFY_PROD_DEVTOOLS__: "false"
231
- })
232
- );
233
- debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${opts.fullInstall}'`);
236
+ let _filter = null;
237
+ async function getFilter() {
238
+ if (_filter != null) {
239
+ return _filter;
240
+ }
241
+ if (meta.framework == "webpack") {
242
+ debug$2("Using filter for webpack");
243
+ _filter = pluginutils.createFilter(...resolveIncludeExclude());
244
+ } else {
245
+ const viteModule2 = await getViteModule();
246
+ if (viteModule2.rolldownVersion) {
247
+ debug$2("Using filter for rolldown-vite");
248
+ _filter = pluginutils.createFilter(...resolveIncludeExclude());
234
249
  } else {
235
- debug$2(
236
- `ignore vue-i18n feature flags with ${meta.framework}.DefinePlugin`
237
- );
250
+ debug$2("Using filter for rollup-vite");
251
+ _filter = pluginutils.createFilter(...resolveIncludeExcludeForLegacy());
238
252
  }
239
- }).catch((_e) => {
240
- warn(`${meta.framework} not found, please install ${meta.framework}.`);
241
- });
242
- compiler.options.module.rules.push({
243
- test: /\.(json5?|ya?ml)$/,
244
- type: "javascript/auto",
245
- include: (resource) => filter(resource)
246
- });
253
+ }
254
+ return _filter;
247
255
  }
248
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
256
+ const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
257
+ return `${module}/dist/${module}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
258
+ };
259
+ let isProduction = false;
260
+ let sourceMap = false;
261
+ const vueI18nAliasName = module;
262
+ debug$2(`vue-i18n alias name: ${vueI18nAliasName}`);
263
+ let vuePlugin = null;
264
+ const getSfcParser = () => {
265
+ return vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
266
+ };
249
267
  return {
250
268
  name: resolveNamespace("resource"),
251
269
  /**
252
270
  * NOTE:
253
- * vite: early ('pre') transform for json and SFC's custom blocks
254
- * because these are transformed into javascript code by `vite:json` plugin.
255
271
  *
256
- * webpack/rspack: late ('post') transform because we rely on vue-loader to generate the request queries.
272
+ * For vite, If we have json (including SFC's custom block),
273
+ * transform it first because it will be transformed into javascript code by `vite:json` plugin.
274
+ *
275
+ * For webpack, This plugin will handle with 'post', because vue-loader generate the request query.
257
276
  */
258
277
  enforce: meta.framework === "vite" ? "pre" : "post",
259
- rspack: sharedWebpackLikePlugin,
260
- webpack: sharedWebpackLikePlugin,
261
278
  vite: {
262
279
  config() {
263
280
  const defineConfig = {
264
281
  define: {
265
- __VUE_I18N_FULL_INSTALL__: opts.fullInstall,
266
- __INTLIFY_DROP_MESSAGE_COMPILER__: opts.dropMessageCompiler,
282
+ __VUE_I18N_LEGACY_API__: !compositionOnly,
283
+ __VUE_I18N_FULL_INSTALL__: fullInstall,
284
+ __INTLIFY_DROP_MESSAGE_COMPILER__: dropMessageCompiler,
267
285
  __VUE_I18N_PROD_DEVTOOLS__: false
268
286
  }
269
287
  };
@@ -271,148 +289,227 @@ function resourcePlugin(opts, meta) {
271
289
  const aliasConfig = {
272
290
  resolve: {
273
291
  alias: {
274
- [opts.module]: opts.vueI18nAliasPath
292
+ [vueI18nAliasName]: getVueI18nAliasPath({
293
+ ssr: ssrBuild,
294
+ runtimeOnly
295
+ })
275
296
  }
276
297
  }
277
298
  };
278
299
  debug$2("alias Config:", aliasConfig);
279
300
  return shared.assign(defineConfig, aliasConfig);
280
301
  },
281
- configResolved(config) {
302
+ async configResolved(config) {
282
303
  vuePlugin = getVitePlugin(config, "vite:vue");
283
304
  if (!checkVuePlugin(vuePlugin)) {
284
305
  return;
285
306
  }
286
- ctx.prod = config.isProduction;
287
- ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
288
- debug$2(
289
- `configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`
290
- );
291
- const jsonPlugin = getVitePlugin(config, "vite:json");
292
- if (jsonPlugin) {
293
- const orgTransform = jsonPlugin.transform;
294
- jsonPlugin.transform = async function(code, id) {
295
- if (!/\.json$/.test(id) || filter(id)) {
296
- return;
307
+ isProduction = config.isProduction;
308
+ sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
309
+ debug$2(`configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
310
+ const isRolldownVite = !!(await getViteModule()).rolldownVersion;
311
+ debug$2(`Using ${isRolldownVite ? "rolldown-vite" : "vite"} for the build`);
312
+ if (!isRolldownVite) {
313
+ const jsonPlugin = getVitePlugin(config, "vite:json");
314
+ if (jsonPlugin) {
315
+ const orgTransform = "handler" in jsonPlugin.transform ? jsonPlugin.transform.handler : jsonPlugin.transform;
316
+ async function overrideJson(code, id) {
317
+ const filter = await getFilter();
318
+ if (!/\.json$/.test(id) || filter(id)) {
319
+ return;
320
+ }
321
+ const { query } = parseVueRequest(id);
322
+ if (query.vue) {
323
+ return;
324
+ }
325
+ debug$2("org json plugin");
326
+ return orgTransform.apply(this, [code, id]);
297
327
  }
298
- const { query } = parseVueRequest(id);
299
- if (query.vue) {
300
- return;
328
+ jsonPlugin.transform = overrideJson;
329
+ if ("handler" in jsonPlugin.transform) {
330
+ jsonPlugin.transform.handler = overrideJson;
301
331
  }
302
- debug$2("org json plugin");
303
- return orgTransform.apply(this, [code, id]);
304
- };
332
+ }
333
+ }
334
+ },
335
+ async handleHotUpdate({ file, server }) {
336
+ if (RE_RESOURCE_FORMAT.test(file)) {
337
+ const module2 = server.moduleGraph.getModuleById(
338
+ asVirtualId(INTLIFY_BUNDLE_IMPORT_ID, meta.framework)
339
+ );
340
+ if (module2) {
341
+ server.moduleGraph.invalidateModule(module2);
342
+ return [module2];
343
+ }
305
344
  }
306
345
  }
307
346
  },
308
- resolveId(id, importer) {
309
- debug$2("resolveId", id, importer);
310
- if (id === INTLIFY_BUNDLE_IMPORT_ID) {
311
- return asVirtualId(id, meta.framework);
347
+ webpack(compiler) {
348
+ isProduction = compiler.options.mode !== "development";
349
+ sourceMap = !!compiler.options.devtool;
350
+ debug$2(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
351
+ compiler.options.resolve = normalizeConfigResolveAlias(
352
+ compiler.options.resolve,
353
+ meta.framework
354
+ );
355
+ compiler.options.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath({
356
+ ssr: ssrBuild,
357
+ runtimeOnly
358
+ });
359
+ debug$2(
360
+ `set ${vueI18nAliasName}: ${getVueI18nAliasPath({
361
+ ssr: ssrBuild,
362
+ runtimeOnly
363
+ })}`
364
+ );
365
+ compiler.options.plugins.push(
366
+ new compiler.webpack.DefinePlugin({
367
+ __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
368
+ __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
369
+ __INTLIFY_PROD_DEVTOOLS__: "false"
370
+ })
371
+ );
372
+ debug$2(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
373
+ debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
374
+ const filter = pluginutils.createFilter(...resolveIncludeExclude());
375
+ if (compiler.options.module) {
376
+ compiler.options.module.rules.push({
377
+ test: RE_RESOURCE_FORMAT,
378
+ type: "javascript/auto",
379
+ include(resource) {
380
+ debug$2("webpack resource include", resource);
381
+ return filter(resource);
382
+ }
383
+ });
312
384
  }
313
385
  },
314
- loadInclude(id) {
315
- return INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework);
316
- },
317
- load(id) {
318
- debug$2("load", id);
319
- if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
320
- const code = generateBundleResources(resourcePaths);
321
- for (const p of resourcePaths) {
322
- this.addWatchFile(p);
323
- }
324
- return result(code);
386
+ resolveId: {
387
+ filter: {
388
+ id: RE_INTLIFY_BUNDLE_IMPORT_ID
389
+ },
390
+ handler(id) {
391
+ return asVirtualId(id, meta.framework);
325
392
  }
326
393
  },
327
- transformInclude(id) {
328
- debug$2("transformInclude", id);
329
- if (meta.framework === "vite") {
330
- return true;
331
- }
332
- const { filename, query } = parseVueRequest(id);
333
- if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
334
- return true;
335
- }
336
- let isResourcePath = resourcePaths.has(id);
337
- if (!isResourcePath && "issuerPath" in query) {
338
- isResourcePath = resourcePaths.has(query.issuerPath);
394
+ load: {
395
+ filter: {
396
+ id: RE_VIRTUAL_PREFIXED_INTLIFY_BUNDLE_IMPORT_ID
397
+ },
398
+ async handler(id) {
399
+ debug$2("load", id);
400
+ if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
401
+ let resourcePaths = [];
402
+ const includePaths = shared.isArray(include) ? include : [include];
403
+ for (const inc of includePaths) {
404
+ resourcePaths = [...resourcePaths, ...await fg__default(inc)];
405
+ }
406
+ resourcePaths = resourcePaths.filter((el, pos) => resourcePaths.indexOf(el) === pos);
407
+ const code = await generateBundleResources(resourcePaths, isProduction, {
408
+ forceStringify,
409
+ strictMessage,
410
+ escapeHtml
411
+ });
412
+ return {
413
+ moduleType: "js",
414
+ code,
415
+ map: { mappings: "" }
416
+ };
417
+ }
339
418
  }
340
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
341
419
  },
342
- async transform(code, id) {
343
- const { filename, query } = parseVueRequest(id);
344
- debug$2("transform", id, JSON.stringify(query), filename);
345
- let langInfo = opts.defaultSFCLang;
346
- if (filter(id)) {
347
- const imports = mlly.findStaticImports(code);
348
- for (const p of imports) {
349
- const res = pathe.resolve(pathe.dirname(id), p.specifier);
350
- importedResources.add(res);
420
+ transform: {
421
+ async handler(code, id) {
422
+ const filter = await getFilter();
423
+ if (!filter(id)) {
424
+ return;
351
425
  }
352
- }
353
- if (!query.vue && supportedFileExtensionsRE.test(id) && filter(id)) {
354
- langInfo = pathe.parse(filename).ext;
355
- const generate = getGenerator(langInfo);
356
- const parseOptions = getOptions(filename, ctx, query, {
357
- ...opts,
358
- transformI18nBlock: void 0
359
- });
360
- debug$2("parseOptions", parseOptions);
361
- try {
362
- const { code: generatedCode, map } = generate(code, parseOptions);
426
+ const { filename, query } = parseVueRequest(id);
427
+ debug$2("transform", id, JSON.stringify(query), filename);
428
+ let langInfo = defaultSFCLang;
429
+ let inSourceMap;
430
+ if (!query.vue) {
431
+ langInfo = path.parse(filename).ext;
432
+ const generate = getGenerator(langInfo);
433
+ const parseOptions = getOptions(
434
+ filename,
435
+ isProduction,
436
+ query,
437
+ sourceMap,
438
+ {
439
+ inSourceMap,
440
+ isGlobal: globalSFCScope,
441
+ allowDynamic,
442
+ strictMessage,
443
+ escapeHtml,
444
+ jit: true,
445
+ onlyLocales,
446
+ forceStringify
447
+ }
448
+ );
449
+ debug$2("parseOptions", parseOptions);
450
+ const { code: generatedCode, map } = await generate(code, parseOptions);
363
451
  debug$2("generated code", generatedCode);
364
- debug$2("sourcemap", map, ctx.sourceMap);
365
- if (code === generatedCode)
366
- return;
367
- return result(generatedCode);
368
- } catch (err) {
369
- if (err instanceof bundleUtils.DynamicResourceError) {
370
- error(
371
- `Unable to precompile or optimize \`${filename}\` - excluding from virtual bundle \`${INTLIFY_BUNDLE_IMPORT_ID}\`.
372
- `,
373
- err
452
+ debug$2("sourcemap", map, sourceMap);
453
+ if (code === generatedCode) return;
454
+ return {
455
+ moduleType: "js",
456
+ code: generatedCode,
457
+ // prettier-ignore
458
+ map: { mappings: "" }
459
+ };
460
+ } else {
461
+ if (isCustomBlock(query)) {
462
+ if (shared.isString(query.lang)) {
463
+ langInfo = query.src ? query.lang === "i18n" ? defaultSFCLang : query.lang : query.lang;
464
+ } else if (defaultSFCLang) {
465
+ langInfo = defaultSFCLang;
466
+ }
467
+ debug$2("langInfo", langInfo);
468
+ const generate = /\.?json5?/.test(langInfo) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
469
+ const parseOptions = getOptions(
470
+ filename,
471
+ isProduction,
472
+ query,
473
+ sourceMap,
474
+ {
475
+ inSourceMap,
476
+ isGlobal: globalSFCScope,
477
+ jit: true,
478
+ strictMessage,
479
+ escapeHtml,
480
+ onlyLocales,
481
+ forceStringify
482
+ }
374
483
  );
375
- return `export default {}`;
376
- } else {
377
- throw err;
378
- }
379
- }
380
- }
381
- if (isCustomBlock(query)) {
382
- langInfo = opts.defaultSFCLang;
383
- if (query.lang && query.lang !== "i18n") {
384
- langInfo = query.lang;
385
- }
386
- debug$2("langInfo", langInfo);
387
- const parseOptions = getOptions(filename, ctx, query, {
388
- ...opts,
389
- allowDynamic: false,
390
- transformI18nBlock: void 0
391
- });
392
- debug$2("parseOptions", parseOptions);
393
- let source = getCode(
394
- code,
395
- filename,
396
- ctx.sourceMap,
397
- query,
398
- getSfcParser(),
399
- meta
400
- );
401
- if (typeof opts.transformI18nBlock === "function") {
402
- const modifiedSource = opts.transformI18nBlock(source);
403
- if (modifiedSource && typeof modifiedSource === "string") {
404
- source = modifiedSource;
405
- } else {
406
- warn("transformI18nBlock should return a string");
484
+ debug$2("parseOptions", parseOptions);
485
+ let source = await getCode(
486
+ code,
487
+ filename,
488
+ sourceMap,
489
+ query,
490
+ getSfcParser(),
491
+ meta.framework
492
+ );
493
+ if (typeof transformI18nBlock === "function") {
494
+ const modifiedSource = transformI18nBlock(source);
495
+ if (modifiedSource && typeof modifiedSource === "string") {
496
+ source = modifiedSource;
497
+ } else {
498
+ warn("transformI18nBlock should return a string");
499
+ }
500
+ }
501
+ const { code: generatedCode, map } = generate(source, parseOptions);
502
+ debug$2("generated code", generatedCode);
503
+ debug$2("sourcemap", map, sourceMap);
504
+ if (code === generatedCode) return;
505
+ return {
506
+ moduleType: "js",
507
+ code: generatedCode,
508
+ // prettier-ignore
509
+ map: { mappings: "" }
510
+ };
407
511
  }
408
512
  }
409
- const generate = getGenerator(langInfo, bundleUtils.generateYAML);
410
- const { code: generatedCode, map } = generate(source, parseOptions);
411
- debug$2("generated code", generatedCode);
412
- debug$2("sourcemap", map, ctx.sourceMap);
413
- if (code !== generatedCode) {
414
- return result(generatedCode);
415
- }
416
513
  }
417
514
  }
418
515
  };
@@ -424,39 +521,66 @@ function getGenerator(ext, fallback = bundleUtils.generateJSON) {
424
521
  if (/\.ya?ml$/.test(ext)) {
425
522
  return bundleUtils.generateYAML;
426
523
  }
427
- if (/\.[c|m]?[j|t]s$/.test(ext)) {
524
+ if (/\.[c|m]?js$/.test(ext)) {
428
525
  return bundleUtils.generateJavaScript;
429
526
  }
527
+ if (/\.[c|m]?ts$/.test(ext)) {
528
+ return bundleUtils.generateTypescript;
529
+ }
430
530
  return fallback;
431
531
  }
432
- async function loadWebpack() {
433
- const mod = await import('webpack');
434
- return mod.default || mod;
435
- }
436
- async function loadRspack() {
437
- const { rspack } = await import('@rspack/core');
438
- return rspack;
532
+ function normalizeConfigResolveAlias(resolve, framework) {
533
+ if (resolve && resolve.alias) {
534
+ return resolve;
535
+ }
536
+ if (!resolve) {
537
+ if (framework === "vite") {
538
+ return { alias: [] };
539
+ } else if (framework === "webpack") {
540
+ return { alias: {} };
541
+ }
542
+ } else if (!resolve.alias) {
543
+ if (framework === "vite") {
544
+ resolve.alias = [];
545
+ return resolve;
546
+ } else if (framework === "webpack") {
547
+ resolve.alias = {};
548
+ return resolve;
549
+ }
550
+ }
439
551
  }
440
- function generateBundleResources(resources) {
552
+ async function generateBundleResources(resources, isProduction, {
553
+ forceStringify = false,
554
+ isGlobal = false,
555
+ onlyLocales = [],
556
+ strictMessage = true,
557
+ escapeHtml = false,
558
+ jit = true,
559
+ transformI18nBlock = void 0
560
+ }) {
441
561
  const codes = [];
442
- const imports = [];
443
- for (const filename of resources) {
444
- debug$2(`${filename} bundle loading ...`);
445
- const { name } = pathe.parse(filename);
446
- const varName = knitwork.genSafeVariableName(
447
- [
448
- name,
449
- node_crypto.createHash("sha256").update(filename).digest("hex").substring(0, 8)
450
- ].join("_")
451
- );
452
- imports.push({ statement: knitwork.genImport(filename, varName), varName });
453
- codes.push(`${JSON.stringify(name)}: ${varName}`);
562
+ for (const res of resources) {
563
+ debug$2(`${res} bundle loading ...`);
564
+ if (/\.(json5?|ya?ml)$/.test(res)) {
565
+ const { ext, name } = path.parse(res);
566
+ const source = await getRaw(res);
567
+ const generate = /json5?/.test(ext) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
568
+ const parseOptions = getOptions(res, isProduction, {}, false, {
569
+ isGlobal,
570
+ jit,
571
+ onlyLocales,
572
+ strictMessage,
573
+ escapeHtml,
574
+ forceStringify,
575
+ transformI18nBlock
576
+ });
577
+ parseOptions.type = "bare";
578
+ const { code } = generate(source, parseOptions);
579
+ debug$2("generated code", code);
580
+ codes.push(`${JSON.stringify(name)}: ${code}`);
581
+ }
454
582
  }
455
- const importStatements = imports.map((x) => x.statement).join("\n");
456
- return `
457
- ${importStatements}
458
-
459
- const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);
583
+ return `const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);
460
584
 
461
585
  const mergeDeep = (target, ...sources) => {
462
586
  if (!sources.length) return target;
@@ -477,73 +601,96 @@ const mergeDeep = (target, ...sources) => {
477
601
  }
478
602
 
479
603
  export default mergeDeep({},
480
- ${codes.map((code) => `{ ${code} }`).join(",\n ")}
604
+ ${codes.map((code) => `{${code}}`).join(",\n")}
481
605
  );`;
482
606
  }
483
- function getCode(source, filename, sourceMap, query, parser, meta) {
484
- if (query.index == null) {
485
- raiseError(`unexpected index: ${query.index}`);
607
+ async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
608
+ const { index, issuerPath } = query;
609
+ if (!shared.isNumber(index)) {
610
+ raiseError(`unexpected index: ${index}`);
486
611
  }
487
- if (meta.framework === "vite") {
612
+ if (framework === "webpack") {
613
+ if (issuerPath) {
614
+ debug$2(`getCode (webpack) ${index} via issuerPath`, issuerPath);
615
+ return await getRaw(filename);
616
+ } else {
617
+ const result = parser(await getRaw(filename), {
618
+ sourceMap,
619
+ filename
620
+ });
621
+ const block = result.descriptor.customBlocks[index];
622
+ if (block) {
623
+ const code = block.src ? await getRaw(block.src) : block.content;
624
+ debug$2(`getCode (webpack) ${index} from SFC`, code);
625
+ return code;
626
+ } else {
627
+ return source;
628
+ }
629
+ }
630
+ } else {
488
631
  return source;
489
632
  }
490
- if (query.issuerPath) {
491
- debug$2(
492
- `getCode (${meta.framework}) ${query.index} via issuerPath`,
493
- query.issuerPath
494
- );
495
- return readFile(filename);
496
- }
497
- const result = parser(readFile(filename), { sourceMap, filename });
498
- const block = result.descriptor.customBlocks[query.index];
499
- if (block) {
500
- const code = block.src ? readFile(block.src) : block.content;
501
- debug$2(`getCode (${meta.framework}) ${query.index} from SFC`, code);
502
- return code;
503
- }
504
- return source;
505
633
  }
506
634
  function isCustomBlock(query) {
507
- return !shared.isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || // for vite (@vite-plugin-vue)
508
- query["type"] === "i18n" || // for webpack (vue-loader)
635
+ return !shared.isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || // for webpack (vue-loader)
636
+ query["type"] === "i18n" || // for vite (@vite/plugin-vue)
509
637
  query["blockType"] === "i18n");
510
638
  }
511
- function getOptions(filename, ctx, query, opts) {
639
+ function getOptions(filename, isProduction, query, sourceMap, {
640
+ inSourceMap = void 0,
641
+ forceStringify = false,
642
+ isGlobal = false,
643
+ onlyLocales = [],
644
+ allowDynamic = false,
645
+ strictMessage = true,
646
+ escapeHtml = false,
647
+ jit = true,
648
+ transformI18nBlock = null
649
+ }) {
650
+ const mode = isProduction ? "production" : "development";
512
651
  const baseOptions = {
513
- ...opts,
514
652
  filename,
515
- jit: true,
516
- // allow overriding ctx.sourceMap with opts
517
- sourceMap: opts.sourceMap ?? ctx.sourceMap,
518
- env: ctx.prod ? "production" : "development",
519
- onWarn: (msg) => warn(`${filename} ${msg}`),
653
+ sourceMap,
654
+ inSourceMap,
655
+ forceStringify,
656
+ allowDynamic,
657
+ strictMessage,
658
+ escapeHtml,
659
+ jit,
660
+ onlyLocales,
661
+ env: mode,
662
+ transformI18nBlock,
663
+ onWarn: (msg) => {
664
+ warn(`${filename} ${msg}`);
665
+ },
520
666
  onError: (msg, extra) => {
521
667
  const codeFrame = shared.generateCodeFrame(
522
668
  extra?.source || extra?.location?.source || "",
523
669
  extra?.location?.start.column,
524
670
  extra?.location?.end.column
525
671
  );
526
- const errMessage = `${msg} (error code: ${extra?.code}) in ${filename}
672
+ const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
527
673
  target message: ${extra?.source}
528
674
  target message path: ${extra?.path}
529
675
 
530
676
  ${codeFrame}
531
677
  `;
532
- error(errMessage);
533
- throw new Error(errMessage);
678
+ error(errMssage);
679
+ throw new Error(errMssage);
534
680
  }
535
681
  };
536
682
  if (isCustomBlock(query)) {
537
683
  return shared.assign(baseOptions, {
538
684
  type: "sfc",
539
- locale: query.locale ?? "",
540
- isGlobal: opts.globalSFCScope || !!query.global
685
+ locale: shared.isString(query.locale) ? query.locale : "",
686
+ isGlobal: isGlobal || !!query.global
687
+ });
688
+ } else {
689
+ return shared.assign(baseOptions, {
690
+ type: "plain",
691
+ isGlobal: false
541
692
  });
542
693
  }
543
- return shared.assign(baseOptions, {
544
- type: "plain",
545
- isGlobal: false
546
- });
547
694
  }
548
695
  function getVirtualId(id, framework = "vite") {
549
696
  return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
@@ -551,8 +698,8 @@ function getVirtualId(id, framework = "vite") {
551
698
  function asVirtualId(id, framework = "vite") {
552
699
  return framework === "vite" ? VIRTUAL_PREFIX + id : id;
553
700
  }
554
- function readFile(path) {
555
- return fs__default.readFileSync(path, "utf-8");
701
+ async function getRaw(path) {
702
+ return node_fs.promises.readFile(path, { encoding: "utf-8" });
556
703
  }
557
704
 
558
705
  const debug$1 = createDebug__default(resolveNamespace("directive"));
@@ -612,17 +759,14 @@ function directivePlugin({
612
759
  };
613
760
  }
614
761
  function resolveVueOptions(vuePlugin, optimizeTranslationDirective, translationIdentifiers) {
615
- var _a, _b;
616
762
  const vueOptions = vuePlugin.api.options;
617
- vueOptions.template || (vueOptions.template = {});
618
- (_a = vueOptions.template).compilerOptions || (_a.compilerOptions = {});
619
- (_b = vueOptions.template.compilerOptions).directiveTransforms || (_b.directiveTransforms = {});
763
+ vueOptions.template ||= {};
764
+ vueOptions.template.compilerOptions ||= {};
765
+ vueOptions.template.compilerOptions.directiveTransforms ||= {};
620
766
  const translationSignatureResolver = (context, baseResolver) => {
621
767
  const { filename } = context;
622
768
  const vuePluginOptions = getVuePluginOptions(vuePlugin);
623
- const normalizedFilename = normalizePath(
624
- path__default.relative(vuePluginOptions.root, filename)
625
- );
769
+ const normalizedFilename = normalizePath(path__default.relative(vuePluginOptions.root, filename));
626
770
  const resolveIdentifier2 = translationIdentifiers.get(normalizedFilename);
627
771
  debug$1("resolved vue-i18n Identifier", resolveIdentifier2);
628
772
  if (resolveIdentifier2 == null) {
@@ -663,9 +807,7 @@ function analyzeIdentifiers(descriptor, { root }, translationIdentifiers) {
663
807
  debug$1("importLocalName", importLocalName);
664
808
  const resolvedIdentifier = getVueI18nIdentifier(scope, importLocalName);
665
809
  if (resolvedIdentifier) {
666
- const normalizedFilename = normalizePath(
667
- path__default.relative(root, descriptor.filename)
668
- );
810
+ const normalizedFilename = normalizePath(path__default.relative(root, descriptor.filename));
669
811
  debug$1("set vue-i18n resolved identifier: ", resolvedIdentifier);
670
812
  translationIdentifiers.set(normalizedFilename, resolvedIdentifier);
671
813
  }
@@ -735,14 +877,16 @@ function getCallExpressionAndReturnStatement(scope, local) {
735
877
  return EMPTY_NODE_RETURN;
736
878
  }
737
879
  let returnStatement = null;
738
- if (callExpressionRef.from.type === "function" && callExpressionRef.from.block.type === typescriptEstree.AST_NODE_TYPES.FunctionExpression && callExpressionRef.from.block.parent.type === typescriptEstree.AST_NODE_TYPES.Property && callExpressionRef.from.block.parent.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && callExpressionRef.from.block.parent.key.name === "setup") {
739
- returnStatement = callExpressionRef.from.block.body.body.find(
740
- (statement) => {
741
- return statement.type === typescriptEstree.AST_NODE_TYPES.ReturnStatement;
742
- }
743
- );
880
+ if (callExpressionRef.from.type === "function" && callExpressionRef.from.block.type === typescriptEstree.AST_NODE_TYPES.FunctionExpression && // @ts-expect-error -- FIXME: type error
881
+ callExpressionRef.from.block.parent.type === typescriptEstree.AST_NODE_TYPES.Property && // @ts-expect-error -- FIXME: type error
882
+ callExpressionRef.from.block.parent.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && // @ts-expect-error -- FIXME: type error
883
+ callExpressionRef.from.block.parent.key.name === "setup") {
884
+ returnStatement = callExpressionRef.from.block.body.body.find((statement) => {
885
+ return statement.type === typescriptEstree.AST_NODE_TYPES.ReturnStatement;
886
+ });
744
887
  }
745
888
  return {
889
+ // @ts-expect-error -- FIXME: type error
746
890
  callExpression: callExpressionRef.identifier.parent,
747
891
  returnStatement
748
892
  };
@@ -809,9 +953,7 @@ function resolveIdentifier(localVariables, returnVariable) {
809
953
  } else {
810
954
  const variable = localVariables.find((pair) => pair.key === "t");
811
955
  if (variable && variable.value) {
812
- const returnVar = returnVariable.find(
813
- (pair) => pair.value === variable.value
814
- );
956
+ const returnVar = returnVariable.find((pair) => pair.value === variable.value);
815
957
  if (returnVar && returnVar.key) {
816
958
  return { type: "identifier", key: returnVar.key };
817
959
  }
@@ -819,9 +961,7 @@ function resolveIdentifier(localVariables, returnVariable) {
819
961
  const identifierOnly = localVariables.find((pair) => pair.value === null);
820
962
  if (identifierOnly && identifierOnly.key) {
821
963
  const targetKey = identifierOnly.key;
822
- const returnVar = returnVariable.find(
823
- (pair) => pair.value?.startsWith(targetKey)
824
- );
964
+ const returnVar = returnVariable.find((pair) => pair.value?.startsWith(targetKey));
825
965
  if (returnVar && returnVar.key) {
826
966
  return { type: "object", key: returnVar.key, style: "setup-hook" };
827
967
  }
@@ -833,17 +973,17 @@ function resolveIdentifier(localVariables, returnVariable) {
833
973
  const debug = createDebug__default(resolveNamespace("root"));
834
974
  const unpluginFactory = (options = {}, meta) => {
835
975
  debug("meta framework", meta.framework);
836
- if (!["vite", "webpack", "rspack"].includes(meta.framework)) {
837
- raiseError(`This plugin is supported 'vite', 'webpack' and 'rspack' only`);
976
+ if (!["vite", "webpack"].includes(meta.framework)) {
977
+ raiseError(`This plugin is supported 'vite' and 'webpack' only`);
838
978
  }
839
979
  debug("plugin options (resolving):", options);
840
980
  const resolvedOptions = resolveOptions(options);
841
981
  debug("plugin options (resolved):", resolvedOptions);
842
982
  const plugins = [resourcePlugin(resolvedOptions, meta)];
843
983
  if (resolvedOptions.optimizeTranslationDirective) {
844
- if (meta.framework === "webpack" || meta.framework === "rspack") {
984
+ if (meta.framework === "webpack") {
845
985
  raiseError(
846
- `The 'optimizeTranslationDirective' option still is not supported for ${meta.framework}.
986
+ `The 'optimizeTranslationDirective' option still is not supported for webpack.
847
987
  We are waiting for your Pull Request \u{1F642}.`
848
988
  );
849
989
  }