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

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.mjs CHANGED
@@ -2,13 +2,17 @@ import { createUnplugin } from 'unplugin';
2
2
  import createDebug from 'debug';
3
3
  import pc from 'picocolors';
4
4
  import path from 'node:path';
5
- import { normalize, parse } from 'pathe';
6
- import { isArray, isString, isBoolean, assign, isNumber, isEmptyObject, generateCodeFrame } from '@intlify/shared';
7
- import { generateJSON, generateYAML, generateJavaScript } from '@intlify/bundle-utils';
5
+ import defu from 'defu';
6
+ import { normalize, resolve, dirname, parse } from 'pathe';
7
+ import { DynamicResourceError, generateJSON, generateYAML, generateJavaScript } from '@intlify/bundle-utils';
8
+ import { assign, isEmptyObject, generateCodeFrame, isBoolean } from '@intlify/shared';
8
9
  import { createFilter } from '@rollup/pluginutils';
9
10
  import fg from 'fast-glob';
10
- import { promises } from 'node:fs';
11
+ import fs from 'node:fs';
11
12
  import { parse as parse$1 } from 'vue/compiler-sfc';
13
+ import { genSafeVariableName, genImport } from 'knitwork';
14
+ import { findStaticImports } from 'mlly';
15
+ import { createHash } from 'node:crypto';
12
16
  import { transformVTDirective } from '@intlify/vue-i18n-extensions';
13
17
  import { analyze } from '@typescript-eslint/scope-manager';
14
18
  import { parse as parse$2, simpleTraverse, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
@@ -50,54 +54,53 @@ function normalizePath(id) {
50
54
  return path.posix.normalize(isWindows ? slash(id) : id);
51
55
  }
52
56
 
57
+ function toArray(value) {
58
+ return Array.isArray(value) ? value : [value];
59
+ }
60
+
61
+ const getVueI18nAliasPath = (opts) => {
62
+ const filename = [
63
+ opts.module,
64
+ opts.runtimeOnly ? "runtime" : "",
65
+ !opts.ssr ? "esm-bundler" : "node",
66
+ "js"
67
+ ].filter(Boolean).join(".");
68
+ return `${opts.module}/dist/${filename}`;
69
+ };
53
70
  function resolveOptions(options) {
54
- const moduleType = options.module || "vue-i18n";
55
- let onlyLocales = [];
56
- if (options.onlyLocales) {
57
- onlyLocales = isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
58
- }
59
- let include = options.include;
60
- let exclude = void 0;
61
- if (include) {
62
- if (isArray(include)) {
63
- include = include.map((item) => normalize(item));
64
- } else if (isString(include)) {
65
- include = normalize(include);
66
- }
67
- } else {
68
- exclude = "**/**";
69
- }
70
- const forceStringify = !!options.forceStringify;
71
- const defaultSFCLang = isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
72
- const globalSFCScope = !!options.globalSFCScope;
73
- const runtimeOnly = isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
74
- const dropMessageCompiler = !!options.dropMessageCompiler;
75
- const fullInstall = moduleType === "vue-i18n" ? isBoolean(options.fullInstall) ? options.fullInstall : true : false;
76
- const ssrBuild = !!options.ssr;
77
- const allowDynamic = !!options.allowDynamic;
78
- const strictMessage = isBoolean(options.strictMessage) ? options.strictMessage : true;
79
- const escapeHtml = !!options.escapeHtml;
80
- const optimizeTranslationDirective = isString(options.optimizeTranslationDirective) || isArray(options.optimizeTranslationDirective) ? options.optimizeTranslationDirective : !!options.optimizeTranslationDirective;
71
+ const res = defu(options, {
72
+ ssr: false,
73
+ module: "vue-i18n",
74
+ escapeHtml: false,
75
+ onlyLocales: [],
76
+ fullInstall: true,
77
+ runtimeOnly: true,
78
+ strictMessage: true,
79
+ allowDynamic: false,
80
+ globalSFCScope: false,
81
+ forceStringify: false,
82
+ defaultSFCLang: "json",
83
+ dropMessageCompiler: false,
84
+ transformI18nBlock: void 0,
85
+ optimizeTranslationDirective: false
86
+ });
87
+ const include = res.include ? toArray(res.include).map((item) => normalize(item)) : void 0;
88
+ const _exclude = res.exclude ? toArray(res.exclude).map((item) => normalize(item)) : void 0;
89
+ const exclude = res.include ? _exclude : ["**/**"];
90
+ const onlyLocales = toArray(res.onlyLocales);
91
+ const fullInstall = res.module !== "vue-i18n" ? false : res.fullInstall;
92
+ const optimizeTranslationDirective = typeof res.optimizeTranslationDirective === "boolean" ? res.optimizeTranslationDirective : toArray(res.optimizeTranslationDirective);
81
93
  const translationIdentifiers = /* @__PURE__ */ new Map();
82
- const transformI18nBlock = typeof options.transformI18nBlock === "function" ? options.transformI18nBlock : null;
94
+ const vueI18nAliasPath = getVueI18nAliasPath(res);
83
95
  return {
96
+ ...res,
84
97
  include,
85
98
  exclude,
86
- module: moduleType,
87
- onlyLocales,
88
- forceStringify,
89
- defaultSFCLang,
90
- globalSFCScope,
91
- runtimeOnly,
92
- dropMessageCompiler,
93
99
  fullInstall,
94
- ssrBuild,
95
- allowDynamic,
96
- strictMessage,
97
- escapeHtml,
98
- optimizeTranslationDirective,
100
+ onlyLocales,
101
+ vueI18nAliasPath,
99
102
  translationIdentifiers,
100
- transformI18nBlock
103
+ optimizeTranslationDirective
101
104
  };
102
105
  }
103
106
 
@@ -169,52 +172,84 @@ function getDescriptor(filename, code, options) {
169
172
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
170
173
  const VIRTUAL_PREFIX = "\0";
171
174
  const debug$2 = createDebug(resolveNamespace("resource"));
172
- function resourcePlugin({
173
- onlyLocales,
174
- include,
175
- exclude,
176
- module,
177
- forceStringify,
178
- defaultSFCLang,
179
- globalSFCScope,
180
- runtimeOnly,
181
- dropMessageCompiler,
182
- fullInstall,
183
- ssrBuild,
184
- strictMessage,
185
- allowDynamic,
186
- escapeHtml,
187
- transformI18nBlock
188
- }, meta) {
189
- const filter = createFilter(include, exclude);
190
- const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
191
- return `${module}/dist/${module}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.js"}`;
175
+ function resourcePlugin(opts, meta) {
176
+ const _filter = createFilter(opts.include, opts.exclude);
177
+ const importedResources = /* @__PURE__ */ new Set();
178
+ const filter = (val) => _filter(val) || importedResources.has(val);
179
+ debug$2(`vue-i18n alias name: ${opts.module}`);
180
+ const ctx = {
181
+ prod: false,
182
+ sourceMap: false
192
183
  };
193
- let isProduction = false;
194
- let sourceMap = false;
195
- const vueI18nAliasName = module;
196
- debug$2(`vue-i18n alias name: ${vueI18nAliasName}`);
197
184
  let vuePlugin = null;
198
- const getSfcParser = () => {
199
- return vuePlugin ? getVueCompiler(vuePlugin).parse : parse$1;
200
- };
185
+ const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : parse$1;
186
+ const resourcePaths = /* @__PURE__ */ new Set();
187
+ for (const inc of opts.include || []) {
188
+ for (const resourcePath of fg.sync(inc, { ignore: opts.exclude })) {
189
+ resourcePaths.add(resourcePath);
190
+ }
191
+ }
192
+ function result(code) {
193
+ if (meta.framework === "vite") {
194
+ return { code, map: { mappings: "" } };
195
+ }
196
+ return { code };
197
+ }
198
+ function sharedWebpackLikePlugin(compiler) {
199
+ ctx.prod = compiler.options.mode !== "development";
200
+ ctx.sourceMap = !!compiler.options.devtool;
201
+ debug$2(
202
+ `${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`
203
+ );
204
+ compiler.options.resolve.alias = {
205
+ ...compiler.options.resolve.alias,
206
+ [opts.module]: opts.vueI18nAliasPath
207
+ };
208
+ debug$2(`set ${opts.module}: ${opts.vueI18nAliasPath}`);
209
+ const loader = meta.framework === "webpack" ? loadWebpack : loadRspack;
210
+ loader().then((mod) => {
211
+ if (mod) {
212
+ compiler.options.plugins.push(
213
+ // @ts-expect-error type issue
214
+ new mod.DefinePlugin({
215
+ __VUE_I18N_FULL_INSTALL__: JSON.stringify(opts.fullInstall),
216
+ __INTLIFY_PROD_DEVTOOLS__: "false"
217
+ })
218
+ );
219
+ debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${opts.fullInstall}'`);
220
+ } else {
221
+ debug$2(
222
+ `ignore vue-i18n feature flags with ${meta.framework}.DefinePlugin`
223
+ );
224
+ }
225
+ }).catch((_e) => {
226
+ warn(`${meta.framework} not found, please install ${meta.framework}.`);
227
+ });
228
+ compiler.options.module.rules.push({
229
+ test: /\.(json5?|ya?ml)$/,
230
+ type: "javascript/auto",
231
+ include: (resource) => filter(resource)
232
+ });
233
+ }
234
+ const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
201
235
  return {
202
236
  name: resolveNamespace("resource"),
203
237
  /**
204
238
  * NOTE:
239
+ * vite: early ('pre') transform for json and SFC's custom blocks
240
+ * because these are transformed into javascript code by `vite:json` plugin.
205
241
  *
206
- * For vite, If we have json (including SFC's custom block),
207
- * transform it first because it will be transformed into javascript code by `vite:json` plugin.
208
- *
209
- * For webpack, This plugin will handle with ‘post’, because vue-loader generate the request query.
242
+ * webpack/rspack: late ('post') transform because we rely on vue-loader to generate the request queries.
210
243
  */
211
244
  enforce: meta.framework === "vite" ? "pre" : "post",
245
+ rspack: sharedWebpackLikePlugin,
246
+ webpack: sharedWebpackLikePlugin,
212
247
  vite: {
213
248
  config() {
214
249
  const defineConfig = {
215
250
  define: {
216
- __VUE_I18N_FULL_INSTALL__: fullInstall,
217
- __INTLIFY_DROP_MESSAGE_COMPILER__: dropMessageCompiler,
251
+ __VUE_I18N_FULL_INSTALL__: opts.fullInstall,
252
+ __INTLIFY_DROP_MESSAGE_COMPILER__: opts.dropMessageCompiler,
218
253
  __VUE_I18N_PROD_DEVTOOLS__: false
219
254
  }
220
255
  };
@@ -222,10 +257,7 @@ function resourcePlugin({
222
257
  const aliasConfig = {
223
258
  resolve: {
224
259
  alias: {
225
- [vueI18nAliasName]: getVueI18nAliasPath({
226
- ssr: ssrBuild,
227
- runtimeOnly
228
- })
260
+ [opts.module]: opts.vueI18nAliasPath
229
261
  }
230
262
  }
231
263
  };
@@ -237,10 +269,10 @@ function resourcePlugin({
237
269
  if (!checkVuePlugin(vuePlugin)) {
238
270
  return;
239
271
  }
240
- isProduction = config.isProduction;
241
- sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
272
+ ctx.prod = config.isProduction;
273
+ ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
242
274
  debug$2(
243
- `configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
275
+ `configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`
244
276
  );
245
277
  const jsonPlugin = getVitePlugin(config, "vite:json");
246
278
  if (jsonPlugin) {
@@ -257,93 +289,8 @@ function resourcePlugin({
257
289
  return orgTransform.apply(this, [code, id]);
258
290
  };
259
291
  }
260
- const esbuildPlugin = getVitePlugin(config, "vite:esbuild");
261
- if (esbuildPlugin) {
262
- const orgTransform = esbuildPlugin.transform;
263
- esbuildPlugin.transform = async function(code, id) {
264
- const result = await orgTransform.apply(this, [
265
- code,
266
- id
267
- ]);
268
- if (result == null) {
269
- return result;
270
- }
271
- const { filename, query } = parseVueRequest(id);
272
- if (!query.vue && filter(id) && /\.[c|m]?ts$/.test(id)) {
273
- const [_code, inSourceMap] = isString(result) ? [result, void 0] : [result.code, result.map];
274
- let langInfo = defaultSFCLang;
275
- langInfo = parse(filename).ext;
276
- const generate = getGenerator(langInfo);
277
- const parseOptions = getOptions(
278
- filename,
279
- isProduction,
280
- query,
281
- sourceMap,
282
- {
283
- inSourceMap,
284
- isGlobal: globalSFCScope,
285
- allowDynamic,
286
- strictMessage,
287
- escapeHtml,
288
- jit: true,
289
- onlyLocales,
290
- forceStringify
291
- }
292
- );
293
- debug$2("parseOptions", parseOptions);
294
- const { code: generatedCode, map } = generate(_code, parseOptions);
295
- debug$2("generated code", generatedCode);
296
- debug$2("sourcemap", map, sourceMap);
297
- if (_code === generatedCode)
298
- return;
299
- return {
300
- code: generatedCode,
301
- map: { mappings: "" }
302
- };
303
- } else {
304
- return result;
305
- }
306
- };
307
- }
308
- },
309
- async handleHotUpdate({ file, server }) {
310
- if (/\.(json5?|ya?ml)$/.test(file)) {
311
- const module2 = server.moduleGraph.getModuleById(
312
- asVirtualId(INTLIFY_BUNDLE_IMPORT_ID, meta.framework)
313
- );
314
- if (module2) {
315
- server.moduleGraph.invalidateModule(module2);
316
- return [module2];
317
- }
318
- }
319
292
  }
320
293
  },
321
- webpack(compiler) {
322
- webpackLike(compiler, "webpack", {
323
- isProduction,
324
- meta,
325
- sourceMap,
326
- getVueI18nAliasPath,
327
- vueI18nAliasName,
328
- ssrBuild,
329
- runtimeOnly,
330
- fullInstall,
331
- filter
332
- });
333
- },
334
- rspack(compiler) {
335
- webpackLike(compiler, "rspack", {
336
- isProduction,
337
- meta,
338
- sourceMap,
339
- getVueI18nAliasPath,
340
- vueI18nAliasName,
341
- ssrBuild,
342
- runtimeOnly,
343
- fullInstall,
344
- filter
345
- });
346
- },
347
294
  resolveId(id, importer) {
348
295
  debug$2("resolveId", id, importer);
349
296
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
@@ -353,263 +300,149 @@ function resourcePlugin({
353
300
  loadInclude(id) {
354
301
  return INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework);
355
302
  },
356
- async load(id) {
303
+ load(id) {
357
304
  debug$2("load", id);
358
- if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
359
- let resourcePaths = [];
360
- const includePaths = isArray(include) ? include : [include];
361
- for (const inc of includePaths) {
362
- resourcePaths = [...resourcePaths, ...await fg(inc)];
305
+ if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
306
+ const code = generateBundleResources(resourcePaths);
307
+ for (const p of resourcePaths) {
308
+ this.addWatchFile(p);
363
309
  }
364
- resourcePaths = resourcePaths.filter(
365
- (el, pos) => resourcePaths.indexOf(el) === pos
366
- );
367
- const code = await generateBundleResources(
368
- resourcePaths,
369
- isProduction,
370
- {
371
- forceStringify,
372
- strictMessage,
373
- escapeHtml
374
- }
375
- );
376
- return {
377
- code,
378
- map: { mappings: "" }
379
- };
310
+ return result(code);
380
311
  }
381
312
  },
382
313
  transformInclude(id) {
383
314
  debug$2("transformInclude", id);
384
315
  if (meta.framework === "vite") {
385
316
  return true;
386
- } else {
387
- const { filename } = parseVueRequest(id);
388
- return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || /\.(json5?|ya?ml)$/.test(filename) && filter(filename);
389
317
  }
318
+ const { filename, query } = parseVueRequest(id);
319
+ if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
320
+ return true;
321
+ }
322
+ let isResourcePath = resourcePaths.has(id);
323
+ if (!isResourcePath && "issuerPath" in query) {
324
+ isResourcePath = resourcePaths.has(query.issuerPath);
325
+ }
326
+ return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
390
327
  },
391
328
  async transform(code, id) {
392
329
  const { filename, query } = parseVueRequest(id);
393
330
  debug$2("transform", id, JSON.stringify(query), filename);
394
- let langInfo = defaultSFCLang;
395
- let inSourceMap;
396
- if (!query.vue) {
397
- if (/\.(json5?|ya?ml|[c|m]?js)$/.test(id) && filter(id)) {
398
- langInfo = parse(filename).ext;
399
- const generate = getGenerator(langInfo);
400
- const parseOptions = getOptions(
401
- filename,
402
- isProduction,
403
- query,
404
- sourceMap,
405
- {
406
- inSourceMap,
407
- isGlobal: globalSFCScope,
408
- allowDynamic,
409
- strictMessage,
410
- escapeHtml,
411
- jit: true,
412
- onlyLocales,
413
- forceStringify
414
- }
415
- );
416
- debug$2("parseOptions", parseOptions);
331
+ let langInfo = opts.defaultSFCLang;
332
+ if (filter(id)) {
333
+ const imports = findStaticImports(code);
334
+ for (const p of imports) {
335
+ const res = resolve(dirname(id), p.specifier);
336
+ importedResources.add(res);
337
+ }
338
+ }
339
+ if (!query.vue && supportedFileExtensionsRE.test(id) && filter(id)) {
340
+ langInfo = parse(filename).ext;
341
+ const generate = getGenerator(langInfo);
342
+ const parseOptions = getOptions(filename, ctx, query, {
343
+ ...opts,
344
+ transformI18nBlock: void 0
345
+ });
346
+ debug$2("parseOptions", parseOptions);
347
+ try {
417
348
  const { code: generatedCode, map } = generate(code, parseOptions);
418
349
  debug$2("generated code", generatedCode);
419
- debug$2("sourcemap", map, sourceMap);
350
+ debug$2("sourcemap", map, ctx.sourceMap);
420
351
  if (code === generatedCode)
421
352
  return;
422
- return {
423
- code: generatedCode,
424
- // prettier-ignore
425
- map: { mappings: "" }
426
- };
427
- }
428
- } else {
429
- if (isCustomBlock(query)) {
430
- if (isString(query.lang)) {
431
- langInfo = query.src ? query.lang === "i18n" ? defaultSFCLang : query.lang : query.lang;
432
- } else if (defaultSFCLang) {
433
- langInfo = defaultSFCLang;
353
+ return result(generatedCode);
354
+ } catch (err) {
355
+ if (err instanceof DynamicResourceError) {
356
+ error(
357
+ `Unable to precompile or optimize \`${filename}\` - excluding from virtual bundle \`${INTLIFY_BUNDLE_IMPORT_ID}\`.
358
+ `,
359
+ err
360
+ );
361
+ return `export default {}`;
362
+ } else {
363
+ throw err;
434
364
  }
435
- debug$2("langInfo", langInfo);
436
- const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
437
- const parseOptions = getOptions(
438
- filename,
439
- isProduction,
440
- query,
441
- sourceMap,
442
- {
443
- inSourceMap,
444
- isGlobal: globalSFCScope,
445
- jit: true,
446
- strictMessage,
447
- escapeHtml,
448
- onlyLocales,
449
- forceStringify
450
- }
451
- );
452
- debug$2("parseOptions", parseOptions);
453
- let source = await getCode(
454
- code,
455
- filename,
456
- sourceMap,
457
- query,
458
- getSfcParser(),
459
- meta.framework
460
- );
461
- if (typeof transformI18nBlock === "function") {
462
- const modifiedSource = transformI18nBlock(source);
463
- if (modifiedSource && typeof modifiedSource === "string") {
464
- source = modifiedSource;
465
- } else {
466
- warn("transformI18nBlock should return a string");
467
- }
365
+ }
366
+ }
367
+ if (isCustomBlock(query)) {
368
+ langInfo = opts.defaultSFCLang;
369
+ if (query.lang && query.lang !== "i18n") {
370
+ langInfo = query.lang;
371
+ }
372
+ debug$2("langInfo", langInfo);
373
+ const parseOptions = getOptions(filename, ctx, query, {
374
+ ...opts,
375
+ allowDynamic: false,
376
+ transformI18nBlock: void 0
377
+ });
378
+ debug$2("parseOptions", parseOptions);
379
+ let source = getCode(
380
+ code,
381
+ filename,
382
+ ctx.sourceMap,
383
+ query,
384
+ getSfcParser(),
385
+ meta
386
+ );
387
+ if (typeof opts.transformI18nBlock === "function") {
388
+ const modifiedSource = opts.transformI18nBlock(source);
389
+ if (modifiedSource && typeof modifiedSource === "string") {
390
+ source = modifiedSource;
391
+ } else {
392
+ warn("transformI18nBlock should return a string");
468
393
  }
469
- const { code: generatedCode, map } = generate(source, parseOptions);
470
- debug$2("generated code", generatedCode);
471
- debug$2("sourcemap", map, sourceMap);
472
- if (code === generatedCode)
473
- return;
474
- return {
475
- code: generatedCode,
476
- // prettier-ignore
477
- map: { mappings: "" }
478
- };
394
+ }
395
+ const generate = getGenerator(langInfo, generateYAML);
396
+ const { code: generatedCode, map } = generate(source, parseOptions);
397
+ debug$2("generated code", generatedCode);
398
+ debug$2("sourcemap", map, ctx.sourceMap);
399
+ if (code !== generatedCode) {
400
+ return result(generatedCode);
479
401
  }
480
402
  }
481
403
  }
482
404
  };
483
405
  }
484
- function getGenerator(ext, defaultGen = generateJSON) {
485
- return /\.?json5?$/.test(ext) ? generateJSON : /\.ya?ml$/.test(ext) ? generateYAML : /\.([c|m]?js|[c|m]?ts)$/.test(ext) ? generateJavaScript : defaultGen;
486
- }
487
- function webpackLike(compiler, framework, {
488
- isProduction,
489
- sourceMap,
490
- meta,
491
- getVueI18nAliasPath,
492
- vueI18nAliasName,
493
- ssrBuild,
494
- runtimeOnly,
495
- fullInstall,
496
- filter
497
- }) {
498
- isProduction = compiler.options.mode !== "development";
499
- sourceMap = !!compiler.options.devtool;
500
- debug$2(
501
- `${framework}: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
502
- );
503
- compiler.options.resolve = normalizeConfigResolveAlias(
504
- compiler.options.resolve,
505
- meta.framework
506
- );
507
- compiler.options.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath({
508
- ssr: ssrBuild,
509
- runtimeOnly
510
- });
511
- debug$2(
512
- `set ${vueI18nAliasName}: ${getVueI18nAliasPath({
513
- ssr: ssrBuild,
514
- runtimeOnly
515
- })}`
516
- );
517
- const loader = framework === "webpack" ? loadWebpack : loadRspack;
518
- loader().then((mod) => {
519
- if (mod) {
520
- compiler.options.plugins.push(
521
- // @ts-expect-error type issue
522
- new mod.DefinePlugin({
523
- __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
524
- __INTLIFY_PROD_DEVTOOLS__: "false"
525
- })
526
- );
527
- debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
528
- } else {
529
- debug$2(`ignore vue-i18n feature flags with ${framework}.DefinePlugin`);
530
- }
531
- });
532
- if (compiler.options.module) {
533
- compiler.options.module.rules.push({
534
- test: /\.(json5?|ya?ml)$/,
535
- type: "javascript/auto",
536
- include(resource) {
537
- return filter(resource);
538
- }
539
- });
406
+ function getGenerator(ext, fallback = generateJSON) {
407
+ if (/\.?json5?$/.test(ext)) {
408
+ return generateJSON;
540
409
  }
541
- }
542
- function normalizeConfigResolveAlias(resolve, framework) {
543
- if (resolve && resolve.alias) {
544
- return resolve;
410
+ if (/\.ya?ml$/.test(ext)) {
411
+ return generateYAML;
545
412
  }
546
- const webpackLike2 = framework === "webpack" || framework === "rspack";
547
- if (!resolve) {
548
- if (framework === "vite") {
549
- return { alias: [] };
550
- } else if (webpackLike2) {
551
- return { alias: {} };
552
- }
553
- } else if (!resolve.alias) {
554
- if (framework === "vite") {
555
- resolve.alias = [];
556
- return resolve;
557
- } else if (webpackLike2) {
558
- resolve.alias = {};
559
- return resolve;
560
- }
413
+ if (/\.[c|m]?[j|t]s$/.test(ext)) {
414
+ return generateJavaScript;
561
415
  }
416
+ return fallback;
562
417
  }
563
418
  async function loadWebpack() {
564
- try {
565
- const mod = await import('webpack');
566
- return mod.default || mod;
567
- } catch (_e) {
568
- warn(`webpack not found, please install webpack.`);
569
- }
570
- return null;
419
+ const mod = await import('webpack');
420
+ return mod.default || mod;
571
421
  }
572
422
  async function loadRspack() {
573
- try {
574
- const { rspack } = await import('@rspack/core');
575
- return rspack;
576
- } catch (_e) {
577
- warn(`rspack not found, please install rspack.`);
578
- }
579
- return null;
423
+ const { rspack } = await import('@rspack/core');
424
+ return rspack;
580
425
  }
581
- async function generateBundleResources(resources, isProduction, {
582
- forceStringify = false,
583
- isGlobal = false,
584
- onlyLocales = [],
585
- strictMessage = true,
586
- escapeHtml = false,
587
- jit = true,
588
- transformI18nBlock = void 0
589
- }) {
426
+ function generateBundleResources(resources) {
590
427
  const codes = [];
591
- for (const res of resources) {
592
- debug$2(`${res} bundle loading ...`);
593
- if (/\.(json5?|ya?ml)$/.test(res)) {
594
- const { ext, name } = parse(res);
595
- const source = await getRaw(res);
596
- const generate = /json5?/.test(ext) ? generateJSON : generateYAML;
597
- const parseOptions = getOptions(res, isProduction, {}, false, {
598
- isGlobal,
599
- jit,
600
- onlyLocales,
601
- strictMessage,
602
- escapeHtml,
603
- forceStringify,
604
- transformI18nBlock
605
- });
606
- parseOptions.type = "bare";
607
- const { code } = generate(source, parseOptions);
608
- debug$2("generated code", code);
609
- codes.push(`${JSON.stringify(name)}: ${code}`);
610
- }
428
+ const imports = [];
429
+ for (const filename of resources) {
430
+ debug$2(`${filename} bundle loading ...`);
431
+ const { name } = parse(filename);
432
+ const varName = genSafeVariableName(
433
+ [
434
+ name,
435
+ createHash("sha256").update(filename).digest("hex").substring(0, 8)
436
+ ].join("_")
437
+ );
438
+ imports.push({ statement: genImport(filename, varName), varName });
439
+ codes.push(`${JSON.stringify(name)}: ${varName}`);
611
440
  }
612
- return `const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);
441
+ const importStatements = imports.map((x) => x.statement).join("\n");
442
+ return `
443
+ ${importStatements}
444
+
445
+ const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);
613
446
 
614
447
  const mergeDeep = (target, ...sources) => {
615
448
  if (!sources.length) return target;
@@ -630,96 +463,73 @@ const mergeDeep = (target, ...sources) => {
630
463
  }
631
464
 
632
465
  export default mergeDeep({},
633
- ${codes.map((code) => `{${code}}`).join(",\n")}
466
+ ${codes.map((code) => `{ ${code} }`).join(",\n ")}
634
467
  );`;
635
468
  }
636
- async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
637
- const { index, issuerPath } = query;
638
- if (!isNumber(index)) {
639
- raiseError(`unexpected index: ${index}`);
469
+ function getCode(source, filename, sourceMap, query, parser, meta) {
470
+ if (query.index == null) {
471
+ raiseError(`unexpected index: ${query.index}`);
640
472
  }
641
- if (framework === "webpack" || framework === "rspack") {
642
- if (issuerPath) {
643
- debug$2(`getCode (${framework}) ${index} via issuerPath`, issuerPath);
644
- return await getRaw(filename);
645
- } else {
646
- const result = parser(await getRaw(filename), {
647
- sourceMap,
648
- filename
649
- });
650
- const block = result.descriptor.customBlocks[index];
651
- if (block) {
652
- const code = block.src ? await getRaw(block.src) : block.content;
653
- debug$2(`getCode (${framework}) ${index} from SFC`, code);
654
- return code;
655
- } else {
656
- return source;
657
- }
658
- }
659
- } else {
473
+ if (meta.framework === "vite") {
660
474
  return source;
661
475
  }
476
+ if (query.issuerPath) {
477
+ debug$2(
478
+ `getCode (${meta.framework}) ${query.index} via issuerPath`,
479
+ query.issuerPath
480
+ );
481
+ return readFile(filename);
482
+ }
483
+ const result = parser(readFile(filename), { sourceMap, filename });
484
+ const block = result.descriptor.customBlocks[query.index];
485
+ if (block) {
486
+ const code = block.src ? readFile(block.src) : block.content;
487
+ debug$2(`getCode (${meta.framework}) ${query.index} from SFC`, code);
488
+ return code;
489
+ }
490
+ return source;
662
491
  }
663
492
  function isCustomBlock(query) {
664
493
  return !isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || // for vite (@vite-plugin-vue)
665
494
  query["type"] === "i18n" || // for webpack (vue-loader)
666
495
  query["blockType"] === "i18n");
667
496
  }
668
- function getOptions(filename, isProduction, query, sourceMap, {
669
- inSourceMap = void 0,
670
- forceStringify = false,
671
- isGlobal = false,
672
- onlyLocales = [],
673
- allowDynamic = false,
674
- strictMessage = true,
675
- escapeHtml = false,
676
- jit = true,
677
- transformI18nBlock = null
678
- }) {
679
- const mode = isProduction ? "production" : "development";
497
+ function getOptions(filename, ctx, query, opts) {
680
498
  const baseOptions = {
499
+ ...opts,
681
500
  filename,
682
- sourceMap,
683
- inSourceMap,
684
- forceStringify,
685
- allowDynamic,
686
- strictMessage,
687
- escapeHtml,
688
- jit,
689
- onlyLocales,
690
- env: mode,
691
- transformI18nBlock,
692
- onWarn: (msg) => {
693
- warn(`${filename} ${msg}`);
694
- },
501
+ jit: true,
502
+ // allow overriding ctx.sourceMap with opts
503
+ sourceMap: opts.sourceMap ?? ctx.sourceMap,
504
+ env: ctx.prod ? "production" : "development",
505
+ onWarn: (msg) => warn(`${filename} ${msg}`),
695
506
  onError: (msg, extra) => {
696
507
  const codeFrame = generateCodeFrame(
697
508
  extra?.source || extra?.location?.source || "",
698
509
  extra?.location?.start.column,
699
510
  extra?.location?.end.column
700
511
  );
701
- const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
512
+ const errMessage = `${msg} (error code: ${extra?.code}) in ${filename}
702
513
  target message: ${extra?.source}
703
514
  target message path: ${extra?.path}
704
515
 
705
516
  ${codeFrame}
706
517
  `;
707
- error(errMssage);
708
- throw new Error(errMssage);
518
+ error(errMessage);
519
+ throw new Error(errMessage);
709
520
  }
710
521
  };
711
522
  if (isCustomBlock(query)) {
712
523
  return assign(baseOptions, {
713
524
  type: "sfc",
714
- locale: isString(query.locale) ? query.locale : "",
715
- isGlobal: isGlobal || !!query.global
716
- });
717
- } else {
718
- return assign(baseOptions, {
719
- type: "plain",
720
- isGlobal: false
525
+ locale: query.locale ?? "",
526
+ isGlobal: opts.globalSFCScope || !!query.global
721
527
  });
722
528
  }
529
+ return assign(baseOptions, {
530
+ type: "plain",
531
+ isGlobal: false
532
+ });
723
533
  }
724
534
  function getVirtualId(id, framework = "vite") {
725
535
  return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
@@ -727,8 +537,8 @@ function getVirtualId(id, framework = "vite") {
727
537
  function asVirtualId(id, framework = "vite") {
728
538
  return framework === "vite" ? VIRTUAL_PREFIX + id : id;
729
539
  }
730
- async function getRaw(path) {
731
- return promises.readFile(path, { encoding: "utf-8" });
540
+ function readFile(path) {
541
+ return fs.readFileSync(path, "utf-8");
732
542
  }
733
543
 
734
544
  const debug$1 = createDebug(resolveNamespace("directive"));