@intlify/unplugin-vue-i18n 7.0.0-beta.0 → 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,106 +289,6 @@ 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
- }
320
- },
321
- webpack(compiler) {
322
- isProduction = compiler.options.mode !== "development";
323
- sourceMap = !!compiler.options.devtool;
324
- debug$2(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
325
- compiler.options.resolve = normalizeConfigResolveAlias(
326
- compiler.options.resolve,
327
- meta.framework
328
- );
329
- compiler.options.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath({
330
- ssr: ssrBuild,
331
- runtimeOnly
332
- });
333
- debug$2(
334
- `set ${vueI18nAliasName}: ${getVueI18nAliasPath({
335
- ssr: ssrBuild,
336
- runtimeOnly
337
- })}`
338
- );
339
- loadWebpack().then((webpack) => {
340
- if (webpack) {
341
- compiler.options.plugins.push(
342
- new webpack.DefinePlugin({
343
- __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
344
- __INTLIFY_PROD_DEVTOOLS__: "false"
345
- })
346
- );
347
- debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
348
- } else {
349
- debug$2("ignore vue-i18n feature flags with webpack.DefinePlugin");
350
- }
351
- });
352
- if (compiler.options.module) {
353
- compiler.options.module.rules.push({
354
- test: /\.(json5?|ya?ml)$/,
355
- type: "javascript/auto",
356
- include(resource) {
357
- return filter(resource);
358
- }
359
- });
360
292
  }
361
293
  },
362
294
  resolveId(id, importer) {
@@ -365,198 +297,152 @@ function resourcePlugin({
365
297
  return asVirtualId(id, meta.framework);
366
298
  }
367
299
  },
368
- async load(id) {
300
+ loadInclude(id) {
301
+ return INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework);
302
+ },
303
+ load(id) {
369
304
  debug$2("load", id);
370
- if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
371
- let resourcePaths = [];
372
- const includePaths = isArray(include) ? include : [include];
373
- for (const inc of includePaths) {
374
- 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);
375
309
  }
376
- resourcePaths = resourcePaths.filter(
377
- (el, pos) => resourcePaths.indexOf(el) === pos
378
- );
379
- const code = await generateBundleResources(
380
- resourcePaths,
381
- isProduction,
382
- {
383
- forceStringify,
384
- strictMessage,
385
- escapeHtml
386
- }
387
- );
388
- return {
389
- code,
390
- map: { mappings: "" }
391
- };
310
+ return result(code);
392
311
  }
393
312
  },
394
313
  transformInclude(id) {
395
314
  debug$2("transformInclude", id);
396
315
  if (meta.framework === "vite") {
397
316
  return true;
398
- } else {
399
- const { filename } = parseVueRequest(id);
400
- return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || /\.(json5?|ya?ml)$/.test(filename) && filter(filename);
401
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;
402
327
  },
403
328
  async transform(code, id) {
404
329
  const { filename, query } = parseVueRequest(id);
405
330
  debug$2("transform", id, JSON.stringify(query), filename);
406
- let langInfo = defaultSFCLang;
407
- let inSourceMap;
408
- if (!query.vue) {
409
- if (/\.(json5?|ya?ml|[c|m]?js)$/.test(id) && filter(id)) {
410
- langInfo = parse(filename).ext;
411
- const generate = getGenerator(langInfo);
412
- const parseOptions = getOptions(
413
- filename,
414
- isProduction,
415
- query,
416
- sourceMap,
417
- {
418
- inSourceMap,
419
- isGlobal: globalSFCScope,
420
- allowDynamic,
421
- strictMessage,
422
- escapeHtml,
423
- jit: true,
424
- onlyLocales,
425
- forceStringify
426
- }
427
- );
428
- 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 {
429
348
  const { code: generatedCode, map } = generate(code, parseOptions);
430
349
  debug$2("generated code", generatedCode);
431
- debug$2("sourcemap", map, sourceMap);
350
+ debug$2("sourcemap", map, ctx.sourceMap);
432
351
  if (code === generatedCode)
433
352
  return;
434
- return {
435
- code: generatedCode,
436
- // prettier-ignore
437
- map: { mappings: "" }
438
- };
439
- }
440
- } else {
441
- if (isCustomBlock(query)) {
442
- if (isString(query.lang)) {
443
- langInfo = query.src ? query.lang === "i18n" ? defaultSFCLang : query.lang : query.lang;
444
- } else if (defaultSFCLang) {
445
- 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;
446
364
  }
447
- debug$2("langInfo", langInfo);
448
- const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
449
- const parseOptions = getOptions(
450
- filename,
451
- isProduction,
452
- query,
453
- sourceMap,
454
- {
455
- inSourceMap,
456
- isGlobal: globalSFCScope,
457
- jit: true,
458
- strictMessage,
459
- escapeHtml,
460
- onlyLocales,
461
- forceStringify
462
- }
463
- );
464
- debug$2("parseOptions", parseOptions);
465
- let source = await getCode(
466
- code,
467
- filename,
468
- sourceMap,
469
- query,
470
- getSfcParser(),
471
- meta.framework
472
- );
473
- if (typeof transformI18nBlock === "function") {
474
- const modifiedSource = transformI18nBlock(source);
475
- if (modifiedSource && typeof modifiedSource === "string") {
476
- source = modifiedSource;
477
- } else {
478
- warn("transformI18nBlock should return a string");
479
- }
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");
480
393
  }
481
- const { code: generatedCode, map } = generate(source, parseOptions);
482
- debug$2("generated code", generatedCode);
483
- debug$2("sourcemap", map, sourceMap);
484
- if (code === generatedCode)
485
- return;
486
- return {
487
- code: generatedCode,
488
- // prettier-ignore
489
- map: { mappings: "" }
490
- };
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);
491
401
  }
492
402
  }
493
403
  }
494
404
  };
495
405
  }
496
- function getGenerator(ext, defaultGen = generateJSON) {
497
- return /\.?json5?$/.test(ext) ? generateJSON : /\.ya?ml$/.test(ext) ? generateYAML : /\.([c|m]?js|[c|m]?ts)$/.test(ext) ? generateJavaScript : defaultGen;
498
- }
499
- function normalizeConfigResolveAlias(resolve, framework) {
500
- if (resolve && resolve.alias) {
501
- return resolve;
406
+ function getGenerator(ext, fallback = generateJSON) {
407
+ if (/\.?json5?$/.test(ext)) {
408
+ return generateJSON;
502
409
  }
503
- if (!resolve) {
504
- if (framework === "vite") {
505
- return { alias: [] };
506
- } else if (framework === "webpack") {
507
- return { alias: {} };
508
- }
509
- } else if (!resolve.alias) {
510
- if (framework === "vite") {
511
- resolve.alias = [];
512
- return resolve;
513
- } else if (framework === "webpack") {
514
- resolve.alias = {};
515
- return resolve;
516
- }
410
+ if (/\.ya?ml$/.test(ext)) {
411
+ return generateYAML;
412
+ }
413
+ if (/\.[c|m]?[j|t]s$/.test(ext)) {
414
+ return generateJavaScript;
517
415
  }
416
+ return fallback;
518
417
  }
519
418
  async function loadWebpack() {
520
- let webpack = null;
521
- try {
522
- webpack = await import('webpack').then((m) => m.default || m);
523
- } catch (_e) {
524
- warn(`webpack not found, please install webpack.`);
525
- }
526
- return webpack;
527
- }
528
- async function generateBundleResources(resources, isProduction, {
529
- forceStringify = false,
530
- isGlobal = false,
531
- onlyLocales = [],
532
- strictMessage = true,
533
- escapeHtml = false,
534
- jit = true,
535
- transformI18nBlock = void 0
536
- }) {
419
+ const mod = await import('webpack');
420
+ return mod.default || mod;
421
+ }
422
+ async function loadRspack() {
423
+ const { rspack } = await import('@rspack/core');
424
+ return rspack;
425
+ }
426
+ function generateBundleResources(resources) {
537
427
  const codes = [];
538
- for (const res of resources) {
539
- debug$2(`${res} bundle loading ...`);
540
- if (/\.(json5?|ya?ml)$/.test(res)) {
541
- const { ext, name } = parse(res);
542
- const source = await getRaw(res);
543
- const generate = /json5?/.test(ext) ? generateJSON : generateYAML;
544
- const parseOptions = getOptions(res, isProduction, {}, false, {
545
- isGlobal,
546
- jit,
547
- onlyLocales,
548
- strictMessage,
549
- escapeHtml,
550
- forceStringify,
551
- transformI18nBlock
552
- });
553
- parseOptions.type = "bare";
554
- const { code } = generate(source, parseOptions);
555
- debug$2("generated code", code);
556
- codes.push(`${JSON.stringify(name)}: ${code}`);
557
- }
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}`);
558
440
  }
559
- 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);
560
446
 
561
447
  const mergeDeep = (target, ...sources) => {
562
448
  if (!sources.length) return target;
@@ -577,96 +463,73 @@ const mergeDeep = (target, ...sources) => {
577
463
  }
578
464
 
579
465
  export default mergeDeep({},
580
- ${codes.map((code) => `{${code}}`).join(",\n")}
466
+ ${codes.map((code) => `{ ${code} }`).join(",\n ")}
581
467
  );`;
582
468
  }
583
- async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
584
- const { index, issuerPath } = query;
585
- if (!isNumber(index)) {
586
- raiseError(`unexpected index: ${index}`);
469
+ function getCode(source, filename, sourceMap, query, parser, meta) {
470
+ if (query.index == null) {
471
+ raiseError(`unexpected index: ${query.index}`);
587
472
  }
588
- if (framework === "webpack") {
589
- if (issuerPath) {
590
- debug$2(`getCode (webpack) ${index} via issuerPath`, issuerPath);
591
- return await getRaw(filename);
592
- } else {
593
- const result = parser(await getRaw(filename), {
594
- sourceMap,
595
- filename
596
- });
597
- const block = result.descriptor.customBlocks[index];
598
- if (block) {
599
- const code = block.src ? await getRaw(block.src) : block.content;
600
- debug$2(`getCode (webpack) ${index} from SFC`, code);
601
- return code;
602
- } else {
603
- return source;
604
- }
605
- }
606
- } else {
473
+ if (meta.framework === "vite") {
607
474
  return source;
608
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;
609
491
  }
610
492
  function isCustomBlock(query) {
611
493
  return !isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || // for vite (@vite-plugin-vue)
612
494
  query["type"] === "i18n" || // for webpack (vue-loader)
613
495
  query["blockType"] === "i18n");
614
496
  }
615
- function getOptions(filename, isProduction, query, sourceMap, {
616
- inSourceMap = void 0,
617
- forceStringify = false,
618
- isGlobal = false,
619
- onlyLocales = [],
620
- allowDynamic = false,
621
- strictMessage = true,
622
- escapeHtml = false,
623
- jit = true,
624
- transformI18nBlock = null
625
- }) {
626
- const mode = isProduction ? "production" : "development";
497
+ function getOptions(filename, ctx, query, opts) {
627
498
  const baseOptions = {
499
+ ...opts,
628
500
  filename,
629
- sourceMap,
630
- inSourceMap,
631
- forceStringify,
632
- allowDynamic,
633
- strictMessage,
634
- escapeHtml,
635
- jit,
636
- onlyLocales,
637
- env: mode,
638
- transformI18nBlock,
639
- onWarn: (msg) => {
640
- warn(`${filename} ${msg}`);
641
- },
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}`),
642
506
  onError: (msg, extra) => {
643
507
  const codeFrame = generateCodeFrame(
644
508
  extra?.source || extra?.location?.source || "",
645
509
  extra?.location?.start.column,
646
510
  extra?.location?.end.column
647
511
  );
648
- const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
512
+ const errMessage = `${msg} (error code: ${extra?.code}) in ${filename}
649
513
  target message: ${extra?.source}
650
514
  target message path: ${extra?.path}
651
515
 
652
516
  ${codeFrame}
653
517
  `;
654
- error(errMssage);
655
- throw new Error(errMssage);
518
+ error(errMessage);
519
+ throw new Error(errMessage);
656
520
  }
657
521
  };
658
522
  if (isCustomBlock(query)) {
659
523
  return assign(baseOptions, {
660
524
  type: "sfc",
661
- locale: isString(query.locale) ? query.locale : "",
662
- isGlobal: isGlobal || !!query.global
663
- });
664
- } else {
665
- return assign(baseOptions, {
666
- type: "plain",
667
- isGlobal: false
525
+ locale: query.locale ?? "",
526
+ isGlobal: opts.globalSFCScope || !!query.global
668
527
  });
669
528
  }
529
+ return assign(baseOptions, {
530
+ type: "plain",
531
+ isGlobal: false
532
+ });
670
533
  }
671
534
  function getVirtualId(id, framework = "vite") {
672
535
  return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
@@ -674,8 +537,8 @@ function getVirtualId(id, framework = "vite") {
674
537
  function asVirtualId(id, framework = "vite") {
675
538
  return framework === "vite" ? VIRTUAL_PREFIX + id : id;
676
539
  }
677
- async function getRaw(path) {
678
- return promises.readFile(path, { encoding: "utf-8" });
540
+ function readFile(path) {
541
+ return fs.readFileSync(path, "utf-8");
679
542
  }
680
543
 
681
544
  const debug$1 = createDebug(resolveNamespace("directive"));
@@ -956,17 +819,17 @@ function resolveIdentifier(localVariables, returnVariable) {
956
819
  const debug = createDebug(resolveNamespace("root"));
957
820
  const unpluginFactory = (options = {}, meta) => {
958
821
  debug("meta framework", meta.framework);
959
- if (!["vite", "webpack"].includes(meta.framework)) {
960
- raiseError(`This plugin is supported 'vite' and 'webpack' only`);
822
+ if (!["vite", "webpack", "rspack"].includes(meta.framework)) {
823
+ raiseError(`This plugin is supported 'vite', 'webpack' and 'rspack' only`);
961
824
  }
962
825
  debug("plugin options (resolving):", options);
963
826
  const resolvedOptions = resolveOptions(options);
964
827
  debug("plugin options (resolved):", resolvedOptions);
965
828
  const plugins = [resourcePlugin(resolvedOptions, meta)];
966
829
  if (resolvedOptions.optimizeTranslationDirective) {
967
- if (meta.framework === "webpack") {
830
+ if (meta.framework === "webpack" || meta.framework === "rspack") {
968
831
  raiseError(
969
- `The 'optimizeTranslationDirective' option still is not supported for webpack.
832
+ `The 'optimizeTranslationDirective' option still is not supported for ${meta.framework}.
970
833
  We are waiting for your Pull Request \u{1F642}.`
971
834
  );
972
835
  }