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

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,71 @@
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');
16
13
  const compilerSfc = require('vue/compiler-sfc');
17
- const knitwork = require('knitwork');
18
- const mlly = require('mlly');
19
- const node_crypto = require('node:crypto');
14
+ const pc = require('picocolors');
15
+ const eslintUitls = require('@eslint-community/eslint-utils');
20
16
  const vueI18nExtensions = require('@intlify/vue-i18n-extensions');
21
17
  const scopeManager = require('@typescript-eslint/scope-manager');
22
18
  const typescriptEstree = require('@typescript-eslint/typescript-estree');
23
- const eslintUitls = require('@eslint-community/eslint-utils');
24
19
 
25
20
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
26
21
 
27
22
  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
23
  const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
32
- const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
24
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
25
+ const pc__default = /*#__PURE__*/_interopDefaultCompat(pc);
33
26
  const eslintUitls__default = /*#__PURE__*/_interopDefaultCompat(eslintUitls);
34
27
 
28
+ function resolveOptions(options) {
29
+ const moduleType = options.module || "vue-i18n";
30
+ let onlyLocales = [];
31
+ if (options.onlyLocales) {
32
+ onlyLocales = shared.isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
33
+ }
34
+ const forceStringify = !!options.forceStringify;
35
+ const defaultSFCLang = shared.isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
36
+ const globalSFCScope = !!options.globalSFCScope;
37
+ const runtimeOnly = shared.isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
38
+ const dropMessageCompiler = !!options.dropMessageCompiler;
39
+ const compositionOnly = moduleType === "vue-i18n" ? shared.isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
40
+ const fullInstall = moduleType === "vue-i18n" ? shared.isBoolean(options.fullInstall) ? options.fullInstall : true : false;
41
+ const ssrBuild = !!options.ssr;
42
+ const allowDynamic = !!options.allowDynamic;
43
+ const strictMessage = shared.isBoolean(options.strictMessage) ? options.strictMessage : true;
44
+ const escapeHtml = !!options.escapeHtml;
45
+ const optimizeTranslationDirective = shared.isString(options.optimizeTranslationDirective) || shared.isArray(options.optimizeTranslationDirective) ? options.optimizeTranslationDirective : !!options.optimizeTranslationDirective;
46
+ const translationIdentifiers = /* @__PURE__ */ new Map();
47
+ const transformI18nBlock = typeof options.transformI18nBlock === "function" ? options.transformI18nBlock : null;
48
+ return {
49
+ include: options.include,
50
+ exclude: options.exclude,
51
+ module: moduleType,
52
+ onlyLocales,
53
+ forceStringify,
54
+ defaultSFCLang,
55
+ globalSFCScope,
56
+ runtimeOnly,
57
+ dropMessageCompiler,
58
+ compositionOnly,
59
+ fullInstall,
60
+ ssrBuild,
61
+ allowDynamic,
62
+ strictMessage,
63
+ escapeHtml,
64
+ optimizeTranslationDirective,
65
+ translationIdentifiers,
66
+ transformI18nBlock
67
+ };
68
+ }
69
+
35
70
  const PKG_NAME = "unplugin-vue-i18n";
36
71
 
37
72
  function warn(...args) {
@@ -68,63 +103,11 @@ function normalizePath(id) {
68
103
  return path__default.posix.normalize(isWindows ? slash(id) : id);
69
104
  }
70
105
 
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
106
  function parseVueRequest(id) {
122
107
  const [filename, rawQuery] = id.split(`?`, 2);
123
108
  const params = new URLSearchParams(rawQuery);
124
109
  const ret = {};
125
- const langPart = Object.keys(Object.fromEntries(params)).find(
126
- (key) => /lang\./i.test(key)
127
- );
110
+ const langPart = Object.keys(Object.fromEntries(params)).find((key) => /lang\./i.test(key));
128
111
  ret.vue = params.has("vue");
129
112
  ret.global = params.has("global");
130
113
  ret.src = params.has("src");
@@ -185,85 +168,72 @@ function getDescriptor(filename, code, options) {
185
168
 
186
169
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
187
170
  const VIRTUAL_PREFIX = "\0";
171
+ const RE_INTLIFY_BUNDLE_IMPORT_ID = new RegExp(`^${INTLIFY_BUNDLE_IMPORT_ID}$`);
172
+ const RE_VIRTUAL_PREFIXED_INTLIFY_BUNDLE_IMPORT_ID = new RegExp(
173
+ `^${VIRTUAL_PREFIX}${INTLIFY_BUNDLE_IMPORT_ID}$`
174
+ );
175
+ const RE_RESOURCE_FORMAT = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
176
+ const RE_SFC_I18N_CUSTOM_BLOCK = /\?vue&type=i18n/;
177
+ const RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK = /blockType=i18n/;
188
178
  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);
204
- }
205
- }
206
- function result(code) {
207
- if (meta.framework === "vite") {
208
- return { code, map: { mappings: "" } };
179
+ function resourcePlugin({
180
+ onlyLocales,
181
+ include,
182
+ exclude,
183
+ module,
184
+ forceStringify,
185
+ defaultSFCLang,
186
+ globalSFCScope,
187
+ runtimeOnly,
188
+ dropMessageCompiler,
189
+ compositionOnly,
190
+ fullInstall,
191
+ ssrBuild,
192
+ strictMessage,
193
+ allowDynamic,
194
+ escapeHtml,
195
+ transformI18nBlock
196
+ }, meta) {
197
+ function resolveInclude() {
198
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
199
+ if (shared.isArray(include)) {
200
+ return [...include, customBlockInclude];
201
+ } else if (shared.isString(include)) {
202
+ return [include, customBlockInclude];
203
+ } else {
204
+ return [RE_RESOURCE_FORMAT, customBlockInclude];
209
205
  }
210
- return { code };
211
206
  }
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}'`);
234
- } else {
235
- debug$2(
236
- `ignore vue-i18n feature flags with ${meta.framework}.DefinePlugin`
237
- );
238
- }
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
- });
247
- }
248
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
207
+ const filter = pluginutils.createFilter(resolveInclude(), exclude);
208
+ const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
209
+ return `${module}/dist/${module}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
210
+ };
211
+ let isProduction = false;
212
+ let sourceMap = false;
213
+ const vueI18nAliasName = module;
214
+ debug$2(`vue-i18n alias name: ${vueI18nAliasName}`);
215
+ let vuePlugin = null;
216
+ const getSfcParser = () => {
217
+ return vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
218
+ };
249
219
  return {
250
220
  name: resolveNamespace("resource"),
251
221
  /**
252
222
  * 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
223
  *
256
- * webpack/rspack: late ('post') transform because we rely on vue-loader to generate the request queries.
224
+ * For vite, If we have json (including SFC's custom block),
225
+ * transform it first because it will be transformed into javascript code by `vite:json` plugin.
226
+ *
227
+ * For webpack, This plugin will handle with ‘post’, because vue-loader generate the request query.
257
228
  */
258
229
  enforce: meta.framework === "vite" ? "pre" : "post",
259
- rspack: sharedWebpackLikePlugin,
260
- webpack: sharedWebpackLikePlugin,
261
230
  vite: {
262
231
  config() {
263
232
  const defineConfig = {
264
233
  define: {
265
- __VUE_I18N_FULL_INSTALL__: opts.fullInstall,
266
- __INTLIFY_DROP_MESSAGE_COMPILER__: opts.dropMessageCompiler,
234
+ __VUE_I18N_LEGACY_API__: !compositionOnly,
235
+ __VUE_I18N_FULL_INSTALL__: fullInstall,
236
+ __INTLIFY_DROP_MESSAGE_COMPILER__: dropMessageCompiler,
267
237
  __VUE_I18N_PROD_DEVTOOLS__: false
268
238
  }
269
239
  };
@@ -271,7 +241,10 @@ function resourcePlugin(opts, meta) {
271
241
  const aliasConfig = {
272
242
  resolve: {
273
243
  alias: {
274
- [opts.module]: opts.vueI18nAliasPath
244
+ [vueI18nAliasName]: getVueI18nAliasPath({
245
+ ssr: ssrBuild,
246
+ runtimeOnly
247
+ })
275
248
  }
276
249
  }
277
250
  };
@@ -283,136 +256,194 @@ function resourcePlugin(opts, meta) {
283
256
  if (!checkVuePlugin(vuePlugin)) {
284
257
  return;
285
258
  }
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;
297
- }
298
- const { query } = parseVueRequest(id);
299
- if (query.vue) {
300
- return;
301
- }
302
- debug$2("org json plugin");
303
- return orgTransform.apply(this, [code, id]);
304
- };
259
+ isProduction = config.isProduction;
260
+ sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
261
+ debug$2(`configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
262
+ },
263
+ async handleHotUpdate({ file, server }) {
264
+ if (RE_RESOURCE_FORMAT.test(file)) {
265
+ const module2 = server.moduleGraph.getModuleById(
266
+ asVirtualId(INTLIFY_BUNDLE_IMPORT_ID, meta.framework)
267
+ );
268
+ if (module2) {
269
+ server.moduleGraph.invalidateModule(module2);
270
+ return [module2];
271
+ }
305
272
  }
306
273
  }
307
274
  },
308
- resolveId(id, importer) {
309
- debug$2("resolveId", id, importer);
310
- if (id === INTLIFY_BUNDLE_IMPORT_ID) {
311
- return asVirtualId(id, meta.framework);
312
- }
313
- },
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);
275
+ webpack(compiler) {
276
+ isProduction = compiler.options.mode !== "development";
277
+ sourceMap = !!compiler.options.devtool;
278
+ debug$2(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
279
+ compiler.options.resolve = normalizeConfigResolveAlias(
280
+ compiler.options.resolve,
281
+ meta.framework
282
+ );
283
+ compiler.options.resolve.alias[vueI18nAliasName] = getVueI18nAliasPath({
284
+ ssr: ssrBuild,
285
+ runtimeOnly
286
+ });
287
+ debug$2(
288
+ `set ${vueI18nAliasName}: ${getVueI18nAliasPath({
289
+ ssr: ssrBuild,
290
+ runtimeOnly
291
+ })}`
292
+ );
293
+ loadWebpack().then((webpack) => {
294
+ if (webpack) {
295
+ compiler.options.plugins.push(
296
+ new webpack.DefinePlugin({
297
+ __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
298
+ __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
299
+ __INTLIFY_PROD_DEVTOOLS__: "false"
300
+ })
301
+ );
302
+ debug$2(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
303
+ debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
304
+ } else {
305
+ debug$2("ignore vue-i18n feature flags with webpack.DefinePlugin");
323
306
  }
324
- return result(code);
307
+ });
308
+ if (compiler.options.module) {
309
+ compiler.options.module.rules.push({
310
+ test: RE_RESOURCE_FORMAT,
311
+ type: "javascript/auto",
312
+ include(resource) {
313
+ return filter(resource);
314
+ }
315
+ });
325
316
  }
326
317
  },
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);
318
+ resolveId: {
319
+ filter: {
320
+ id: RE_INTLIFY_BUNDLE_IMPORT_ID
321
+ },
322
+ handler(id) {
323
+ return asVirtualId(id, meta.framework);
339
324
  }
340
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
341
325
  },
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);
351
- }
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);
363
- 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
374
- );
375
- return `export default {}`;
376
- } else {
377
- throw err;
326
+ load: {
327
+ filter: {
328
+ id: RE_VIRTUAL_PREFIXED_INTLIFY_BUNDLE_IMPORT_ID
329
+ },
330
+ async handler(id) {
331
+ debug$2("load", id);
332
+ if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
333
+ let resourcePaths = [];
334
+ const includePaths = shared.isArray(include) ? include : [include];
335
+ for (const inc of includePaths) {
336
+ resourcePaths = [...resourcePaths, ...await fg__default(inc)];
378
337
  }
338
+ resourcePaths = resourcePaths.filter((el, pos) => resourcePaths.indexOf(el) === pos);
339
+ const code = await generateBundleResources(resourcePaths, isProduction, {
340
+ forceStringify,
341
+ strictMessage,
342
+ escapeHtml
343
+ });
344
+ return {
345
+ moduleType: "js",
346
+ code,
347
+ map: { mappings: "" }
348
+ };
379
349
  }
380
350
  }
381
- if (isCustomBlock(query)) {
382
- langInfo = opts.defaultSFCLang;
383
- if (query.lang && query.lang !== "i18n") {
384
- langInfo = query.lang;
351
+ },
352
+ transform: {
353
+ filter: {
354
+ id: {
355
+ include: resolveInclude(),
356
+ exclude
385
357
  }
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");
358
+ },
359
+ async handler(code, id) {
360
+ const { filename, query } = parseVueRequest(id);
361
+ debug$2("transform", id, JSON.stringify(query), filename);
362
+ let langInfo = defaultSFCLang;
363
+ let inSourceMap;
364
+ if (!query.vue) {
365
+ langInfo = path.parse(filename).ext;
366
+ const generate = getGenerator(langInfo);
367
+ const parseOptions = getOptions(
368
+ filename,
369
+ isProduction,
370
+ query,
371
+ sourceMap,
372
+ {
373
+ inSourceMap,
374
+ isGlobal: globalSFCScope,
375
+ allowDynamic,
376
+ strictMessage,
377
+ escapeHtml,
378
+ jit: true,
379
+ onlyLocales,
380
+ forceStringify
381
+ }
382
+ );
383
+ debug$2("parseOptions", parseOptions);
384
+ const { code: generatedCode, map } = await generate(code, parseOptions);
385
+ debug$2("generated code", generatedCode);
386
+ debug$2("sourcemap", map, sourceMap);
387
+ if (code === generatedCode) return;
388
+ return {
389
+ moduleType: "js",
390
+ code: generatedCode,
391
+ // prettier-ignore
392
+ map: { mappings: "" }
393
+ };
394
+ } else {
395
+ if (isCustomBlock(query)) {
396
+ if (shared.isString(query.lang)) {
397
+ langInfo = query.src ? query.lang === "i18n" ? defaultSFCLang : query.lang : query.lang;
398
+ } else if (defaultSFCLang) {
399
+ langInfo = defaultSFCLang;
400
+ }
401
+ debug$2("langInfo", langInfo);
402
+ const generate = /\.?json5?/.test(langInfo) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
403
+ const parseOptions = getOptions(
404
+ filename,
405
+ isProduction,
406
+ query,
407
+ sourceMap,
408
+ {
409
+ inSourceMap,
410
+ isGlobal: globalSFCScope,
411
+ jit: true,
412
+ strictMessage,
413
+ escapeHtml,
414
+ onlyLocales,
415
+ forceStringify
416
+ }
417
+ );
418
+ debug$2("parseOptions", parseOptions);
419
+ let source = await getCode(
420
+ code,
421
+ filename,
422
+ sourceMap,
423
+ query,
424
+ getSfcParser(),
425
+ meta.framework
426
+ );
427
+ if (typeof transformI18nBlock === "function") {
428
+ const modifiedSource = transformI18nBlock(source);
429
+ if (modifiedSource && typeof modifiedSource === "string") {
430
+ source = modifiedSource;
431
+ } else {
432
+ warn("transformI18nBlock should return a string");
433
+ }
434
+ }
435
+ const { code: generatedCode, map } = generate(source, parseOptions);
436
+ debug$2("generated code", generatedCode);
437
+ debug$2("sourcemap", map, sourceMap);
438
+ if (code === generatedCode) return;
439
+ return {
440
+ moduleType: "js",
441
+ code: generatedCode,
442
+ // prettier-ignore
443
+ map: { mappings: "" }
444
+ };
407
445
  }
408
446
  }
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
447
  }
417
448
  }
418
449
  };
@@ -424,39 +455,75 @@ function getGenerator(ext, fallback = bundleUtils.generateJSON) {
424
455
  if (/\.ya?ml$/.test(ext)) {
425
456
  return bundleUtils.generateYAML;
426
457
  }
427
- if (/\.[c|m]?[j|t]s$/.test(ext)) {
458
+ if (/\.[c|m]?js$/.test(ext)) {
428
459
  return bundleUtils.generateJavaScript;
429
460
  }
461
+ if (/\.[c|m]?ts$/.test(ext)) {
462
+ return bundleUtils.generateTypescript;
463
+ }
430
464
  return fallback;
431
465
  }
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;
466
+ function normalizeConfigResolveAlias(resolve, framework) {
467
+ if (resolve && resolve.alias) {
468
+ return resolve;
469
+ }
470
+ if (!resolve) {
471
+ if (framework === "vite") {
472
+ return { alias: [] };
473
+ } else if (framework === "webpack") {
474
+ return { alias: {} };
475
+ }
476
+ } else if (!resolve.alias) {
477
+ if (framework === "vite") {
478
+ resolve.alias = [];
479
+ return resolve;
480
+ } else if (framework === "webpack") {
481
+ resolve.alias = {};
482
+ return resolve;
483
+ }
484
+ }
439
485
  }
440
- function generateBundleResources(resources) {
486
+ async function loadWebpack() {
487
+ let webpack = null;
488
+ try {
489
+ webpack = await import('webpack').then((m) => m.default || m);
490
+ } catch (_e) {
491
+ warn(`webpack not found, please install webpack.`);
492
+ }
493
+ return webpack;
494
+ }
495
+ async function generateBundleResources(resources, isProduction, {
496
+ forceStringify = false,
497
+ isGlobal = false,
498
+ onlyLocales = [],
499
+ strictMessage = true,
500
+ escapeHtml = false,
501
+ jit = true,
502
+ transformI18nBlock = void 0
503
+ }) {
441
504
  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}`);
505
+ for (const res of resources) {
506
+ debug$2(`${res} bundle loading ...`);
507
+ if (/\.(json5?|ya?ml)$/.test(res)) {
508
+ const { ext, name } = path.parse(res);
509
+ const source = await getRaw(res);
510
+ const generate = /json5?/.test(ext) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
511
+ const parseOptions = getOptions(res, isProduction, {}, false, {
512
+ isGlobal,
513
+ jit,
514
+ onlyLocales,
515
+ strictMessage,
516
+ escapeHtml,
517
+ forceStringify,
518
+ transformI18nBlock
519
+ });
520
+ parseOptions.type = "bare";
521
+ const { code } = generate(source, parseOptions);
522
+ debug$2("generated code", code);
523
+ codes.push(`${JSON.stringify(name)}: ${code}`);
524
+ }
454
525
  }
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);
526
+ return `const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);
460
527
 
461
528
  const mergeDeep = (target, ...sources) => {
462
529
  if (!sources.length) return target;
@@ -477,73 +544,96 @@ const mergeDeep = (target, ...sources) => {
477
544
  }
478
545
 
479
546
  export default mergeDeep({},
480
- ${codes.map((code) => `{ ${code} }`).join(",\n ")}
547
+ ${codes.map((code) => `{${code}}`).join(",\n")}
481
548
  );`;
482
549
  }
483
- function getCode(source, filename, sourceMap, query, parser, meta) {
484
- if (query.index == null) {
485
- raiseError(`unexpected index: ${query.index}`);
550
+ async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
551
+ const { index, issuerPath } = query;
552
+ if (!shared.isNumber(index)) {
553
+ raiseError(`unexpected index: ${index}`);
486
554
  }
487
- if (meta.framework === "vite") {
555
+ if (framework === "webpack") {
556
+ if (issuerPath) {
557
+ debug$2(`getCode (webpack) ${index} via issuerPath`, issuerPath);
558
+ return await getRaw(filename);
559
+ } else {
560
+ const result = parser(await getRaw(filename), {
561
+ sourceMap,
562
+ filename
563
+ });
564
+ const block = result.descriptor.customBlocks[index];
565
+ if (block) {
566
+ const code = block.src ? await getRaw(block.src) : block.content;
567
+ debug$2(`getCode (webpack) ${index} from SFC`, code);
568
+ return code;
569
+ } else {
570
+ return source;
571
+ }
572
+ }
573
+ } else {
488
574
  return source;
489
575
  }
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
576
  }
506
577
  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)
578
+ return !shared.isEmptyObject(query) && "vue" in query && (query["type"] === "custom" || // for webpack (vue-loader)
579
+ query["type"] === "i18n" || // for vite (@vite/plugin-vue)
509
580
  query["blockType"] === "i18n");
510
581
  }
511
- function getOptions(filename, ctx, query, opts) {
582
+ function getOptions(filename, isProduction, query, sourceMap, {
583
+ inSourceMap = void 0,
584
+ forceStringify = false,
585
+ isGlobal = false,
586
+ onlyLocales = [],
587
+ allowDynamic = false,
588
+ strictMessage = true,
589
+ escapeHtml = false,
590
+ jit = true,
591
+ transformI18nBlock = null
592
+ }) {
593
+ const mode = isProduction ? "production" : "development";
512
594
  const baseOptions = {
513
- ...opts,
514
595
  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}`),
596
+ sourceMap,
597
+ inSourceMap,
598
+ forceStringify,
599
+ allowDynamic,
600
+ strictMessage,
601
+ escapeHtml,
602
+ jit,
603
+ onlyLocales,
604
+ env: mode,
605
+ transformI18nBlock,
606
+ onWarn: (msg) => {
607
+ warn(`${filename} ${msg}`);
608
+ },
520
609
  onError: (msg, extra) => {
521
610
  const codeFrame = shared.generateCodeFrame(
522
611
  extra?.source || extra?.location?.source || "",
523
612
  extra?.location?.start.column,
524
613
  extra?.location?.end.column
525
614
  );
526
- const errMessage = `${msg} (error code: ${extra?.code}) in ${filename}
615
+ const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
527
616
  target message: ${extra?.source}
528
617
  target message path: ${extra?.path}
529
618
 
530
619
  ${codeFrame}
531
620
  `;
532
- error(errMessage);
533
- throw new Error(errMessage);
621
+ error(errMssage);
622
+ throw new Error(errMssage);
534
623
  }
535
624
  };
536
625
  if (isCustomBlock(query)) {
537
626
  return shared.assign(baseOptions, {
538
627
  type: "sfc",
539
- locale: query.locale ?? "",
540
- isGlobal: opts.globalSFCScope || !!query.global
628
+ locale: shared.isString(query.locale) ? query.locale : "",
629
+ isGlobal: isGlobal || !!query.global
630
+ });
631
+ } else {
632
+ return shared.assign(baseOptions, {
633
+ type: "plain",
634
+ isGlobal: false
541
635
  });
542
636
  }
543
- return shared.assign(baseOptions, {
544
- type: "plain",
545
- isGlobal: false
546
- });
547
637
  }
548
638
  function getVirtualId(id, framework = "vite") {
549
639
  return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
@@ -551,8 +641,8 @@ function getVirtualId(id, framework = "vite") {
551
641
  function asVirtualId(id, framework = "vite") {
552
642
  return framework === "vite" ? VIRTUAL_PREFIX + id : id;
553
643
  }
554
- function readFile(path) {
555
- return fs__default.readFileSync(path, "utf-8");
644
+ async function getRaw(path) {
645
+ return node_fs.promises.readFile(path, { encoding: "utf-8" });
556
646
  }
557
647
 
558
648
  const debug$1 = createDebug__default(resolveNamespace("directive"));
@@ -612,17 +702,14 @@ function directivePlugin({
612
702
  };
613
703
  }
614
704
  function resolveVueOptions(vuePlugin, optimizeTranslationDirective, translationIdentifiers) {
615
- var _a, _b;
616
705
  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 = {});
706
+ vueOptions.template ||= {};
707
+ vueOptions.template.compilerOptions ||= {};
708
+ vueOptions.template.compilerOptions.directiveTransforms ||= {};
620
709
  const translationSignatureResolver = (context, baseResolver) => {
621
710
  const { filename } = context;
622
711
  const vuePluginOptions = getVuePluginOptions(vuePlugin);
623
- const normalizedFilename = normalizePath(
624
- path__default.relative(vuePluginOptions.root, filename)
625
- );
712
+ const normalizedFilename = normalizePath(path__default.relative(vuePluginOptions.root, filename));
626
713
  const resolveIdentifier2 = translationIdentifiers.get(normalizedFilename);
627
714
  debug$1("resolved vue-i18n Identifier", resolveIdentifier2);
628
715
  if (resolveIdentifier2 == null) {
@@ -663,9 +750,7 @@ function analyzeIdentifiers(descriptor, { root }, translationIdentifiers) {
663
750
  debug$1("importLocalName", importLocalName);
664
751
  const resolvedIdentifier = getVueI18nIdentifier(scope, importLocalName);
665
752
  if (resolvedIdentifier) {
666
- const normalizedFilename = normalizePath(
667
- path__default.relative(root, descriptor.filename)
668
- );
753
+ const normalizedFilename = normalizePath(path__default.relative(root, descriptor.filename));
669
754
  debug$1("set vue-i18n resolved identifier: ", resolvedIdentifier);
670
755
  translationIdentifiers.set(normalizedFilename, resolvedIdentifier);
671
756
  }
@@ -735,14 +820,16 @@ function getCallExpressionAndReturnStatement(scope, local) {
735
820
  return EMPTY_NODE_RETURN;
736
821
  }
737
822
  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
- );
823
+ if (callExpressionRef.from.type === "function" && callExpressionRef.from.block.type === typescriptEstree.AST_NODE_TYPES.FunctionExpression && // @ts-expect-error -- FIXME: type error
824
+ callExpressionRef.from.block.parent.type === typescriptEstree.AST_NODE_TYPES.Property && // @ts-expect-error -- FIXME: type error
825
+ callExpressionRef.from.block.parent.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && // @ts-expect-error -- FIXME: type error
826
+ callExpressionRef.from.block.parent.key.name === "setup") {
827
+ returnStatement = callExpressionRef.from.block.body.body.find((statement) => {
828
+ return statement.type === typescriptEstree.AST_NODE_TYPES.ReturnStatement;
829
+ });
744
830
  }
745
831
  return {
832
+ // @ts-expect-error -- FIXME: type error
746
833
  callExpression: callExpressionRef.identifier.parent,
747
834
  returnStatement
748
835
  };
@@ -809,9 +896,7 @@ function resolveIdentifier(localVariables, returnVariable) {
809
896
  } else {
810
897
  const variable = localVariables.find((pair) => pair.key === "t");
811
898
  if (variable && variable.value) {
812
- const returnVar = returnVariable.find(
813
- (pair) => pair.value === variable.value
814
- );
899
+ const returnVar = returnVariable.find((pair) => pair.value === variable.value);
815
900
  if (returnVar && returnVar.key) {
816
901
  return { type: "identifier", key: returnVar.key };
817
902
  }
@@ -819,9 +904,7 @@ function resolveIdentifier(localVariables, returnVariable) {
819
904
  const identifierOnly = localVariables.find((pair) => pair.value === null);
820
905
  if (identifierOnly && identifierOnly.key) {
821
906
  const targetKey = identifierOnly.key;
822
- const returnVar = returnVariable.find(
823
- (pair) => pair.value?.startsWith(targetKey)
824
- );
907
+ const returnVar = returnVariable.find((pair) => pair.value?.startsWith(targetKey));
825
908
  if (returnVar && returnVar.key) {
826
909
  return { type: "object", key: returnVar.key, style: "setup-hook" };
827
910
  }
@@ -833,17 +916,17 @@ function resolveIdentifier(localVariables, returnVariable) {
833
916
  const debug = createDebug__default(resolveNamespace("root"));
834
917
  const unpluginFactory = (options = {}, meta) => {
835
918
  debug("meta framework", meta.framework);
836
- if (!["vite", "webpack", "rspack"].includes(meta.framework)) {
837
- raiseError(`This plugin is supported 'vite', 'webpack' and 'rspack' only`);
919
+ if (!["vite", "webpack"].includes(meta.framework)) {
920
+ raiseError(`This plugin is supported 'vite' and 'webpack' only`);
838
921
  }
839
922
  debug("plugin options (resolving):", options);
840
923
  const resolvedOptions = resolveOptions(options);
841
924
  debug("plugin options (resolved):", resolvedOptions);
842
925
  const plugins = [resourcePlugin(resolvedOptions, meta)];
843
926
  if (resolvedOptions.optimizeTranslationDirective) {
844
- if (meta.framework === "webpack" || meta.framework === "rspack") {
927
+ if (meta.framework === "webpack") {
845
928
  raiseError(
846
- `The 'optimizeTranslationDirective' option still is not supported for ${meta.framework}.
929
+ `The 'optimizeTranslationDirective' option still is not supported for webpack.
847
930
  We are waiting for your Pull Request \u{1F642}.`
848
931
  );
849
932
  }