@intlify/unplugin-vue-i18n 12.0.0-alpha.2 → 12.0.0-alpha.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
@@ -5,15 +5,16 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  const createDebug = require('debug');
6
6
  const unplugin$1 = require('unplugin');
7
7
  const defu = require('defu');
8
- const node_path = require('node:path');
8
+ const pathe = require('pathe');
9
9
  const bundleUtils = require('@intlify/bundle-utils');
10
10
  const shared = require('@intlify/shared');
11
11
  const pluginutils = require('@rollup/pluginutils');
12
- const fg = require('fast-glob');
13
12
  const knitwork = require('knitwork');
14
13
  const mlly = require('mlly');
15
14
  const node_crypto = require('node:crypto');
16
15
  const fs = require('node:fs');
16
+ const node_path = require('node:path');
17
+ const tinyglobby = require('tinyglobby');
17
18
  const compilerSfc = require('vue/compiler-sfc');
18
19
  const pc = require('picocolors');
19
20
 
@@ -21,7 +22,6 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
21
22
 
22
23
  const createDebug__default = /*#__PURE__*/_interopDefaultCompat(createDebug);
23
24
  const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
24
- const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
25
25
  const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
26
26
  const pc__default = /*#__PURE__*/_interopDefaultCompat(pc);
27
27
 
@@ -54,8 +54,8 @@ function resolveOptions(options) {
54
54
  dropMessageCompiler: false,
55
55
  transformI18nBlock: void 0
56
56
  });
57
- const include = res.include ? toArray(res.include).map((item) => node_path.normalize(item)) : void 0;
58
- const _exclude = res.exclude ? toArray(res.exclude).map((item) => node_path.normalize(item)) : void 0;
57
+ const include = res.include ? toArray(res.include).map((item) => pathe.normalize(item)) : void 0;
58
+ const _exclude = res.exclude ? toArray(res.exclude).map((item) => pathe.normalize(item)) : void 0;
59
59
  const exclude = res.include ? _exclude : ["**/**"];
60
60
  const onlyLocales = toArray(res.onlyLocales);
61
61
  const fullInstall = res.module !== "vue-i18n" ? false : res.fullInstall;
@@ -88,23 +88,6 @@ function resolveNamespace(name) {
88
88
  function getVitePlugin(config, name) {
89
89
  return config.plugins.find((p) => p.name === name);
90
90
  }
91
- function getVitePluginTransform(plugin) {
92
- if (plugin.transform) {
93
- return "handler" in plugin.transform ? [plugin.transform.handler, "handler"] : [plugin.transform, "transform"];
94
- } else {
95
- return [void 0, void 0];
96
- }
97
- }
98
- function overrideVitePluginTransform(plugin, override, to) {
99
- if (plugin.transform == void 0) {
100
- throw new Error("plugin.transform is undefined");
101
- }
102
- if (to === "handler" && "handler" in plugin.transform) {
103
- plugin.transform.handler = override;
104
- } else {
105
- plugin.transform = override;
106
- }
107
- }
108
91
  function checkVuePlugin(vuePlugin) {
109
92
  if (vuePlugin == null || !vuePlugin.api) {
110
93
  error(
@@ -157,11 +140,53 @@ function getVueCompiler(vuePlugin) {
157
140
 
158
141
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
159
142
  const VIRTUAL_PREFIX = "\0";
143
+ const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
144
+ const RE_SFC_I18N_CUSTOM_BLOCK = /\?vue&type=i18n/;
145
+ const RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK = /blockType=i18n/;
160
146
  const debug$1 = createDebug__default(resolveNamespace("resource"));
161
147
  function resourcePlugin(opts, meta) {
162
- const _filter = pluginutils.createFilter(opts.include, opts.exclude);
163
148
  const importedResources = /* @__PURE__ */ new Set();
164
- const filter = (val) => _filter(val) || importedResources.has(val);
149
+ function resolveIncludeExclude() {
150
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
151
+ return opts.include ? [[...opts.include, customBlockInclude], opts.exclude] : [[supportedFileExtensionsRE, customBlockInclude], void 0];
152
+ }
153
+ function resolveIncludeExcludeForLegacy() {
154
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
155
+ return opts.include ? [[...opts.include, customBlockInclude], opts.exclude] : [void 0, opts.exclude];
156
+ }
157
+ let _filter = null;
158
+ let hasViteJsonPlugin = false;
159
+ async function getFilter() {
160
+ if (_filter == null) {
161
+ if (meta.framework === "webpack" || meta.framework === "rspack") {
162
+ debug$1("Using filter for webpack/rspack");
163
+ _filter = pluginutils.createFilter(...resolveIncludeExclude());
164
+ } else if (hasViteJsonPlugin) {
165
+ debug$1("Using filter for rollup-vite");
166
+ _filter = pluginutils.createFilter(...resolveIncludeExcludeForLegacy());
167
+ } else {
168
+ debug$1("Using filter for rolldown-vite");
169
+ _filter = pluginutils.createFilter(...resolveIncludeExclude());
170
+ }
171
+ }
172
+ return (val) => _filter(val) || importedResources.has(val);
173
+ }
174
+ const VITE_VIRTUAL_PREFIX = "\0intlify-i18n-";
175
+ const virtualIdToRealPath = /* @__PURE__ */ new Map();
176
+ const realPathToVirtualId = /* @__PURE__ */ new Map();
177
+ let virtualCounter = 0;
178
+ function intlifyVirtualize(realPath) {
179
+ let virtualId = realPathToVirtualId.get(realPath);
180
+ if (!virtualId) {
181
+ virtualId = `${VITE_VIRTUAL_PREFIX}${virtualCounter++}`;
182
+ virtualIdToRealPath.set(virtualId, realPath);
183
+ realPathToVirtualId.set(realPath, virtualId);
184
+ }
185
+ return virtualId;
186
+ }
187
+ function isIntlifyVirtualId(id) {
188
+ return virtualIdToRealPath.has(id);
189
+ }
165
190
  debug$1(`vue-i18n alias name: ${opts.module}`);
166
191
  const ctx = {
167
192
  prod: false,
@@ -171,7 +196,11 @@ function resourcePlugin(opts, meta) {
171
196
  const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
172
197
  const resourcePaths = /* @__PURE__ */ new Set();
173
198
  for (const inc of opts.include || []) {
174
- for (const resourcePath of fg__default.sync(inc, { ignore: opts.exclude })) {
199
+ for (const resourcePath of tinyglobby.globSync(inc, {
200
+ ignore: opts.exclude,
201
+ expandDirectories: false,
202
+ absolute: true
203
+ })) {
175
204
  resourcePaths.add(resourcePath);
176
205
  }
177
206
  }
@@ -185,6 +214,8 @@ function resourcePlugin(opts, meta) {
185
214
  ctx.prod = compiler.options.mode !== "development";
186
215
  ctx.sourceMap = !!compiler.options.devtool;
187
216
  debug$1(`${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
217
+ const syncFilter = pluginutils.createFilter(...resolveIncludeExclude());
218
+ _filter = syncFilter;
188
219
  compiler.options.resolve.alias = {
189
220
  ...compiler.options.resolve.alias,
190
221
  [opts.module]: opts.vueI18nAliasPath
@@ -210,10 +241,9 @@ function resourcePlugin(opts, meta) {
210
241
  compiler.options.module.rules.push({
211
242
  test: /\.(json5?|ya?ml)$/,
212
243
  type: "javascript/auto",
213
- include: (resource) => filter(resource)
244
+ include: (resource) => syncFilter(resource) || importedResources.has(resource)
214
245
  });
215
246
  }
216
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
217
247
  return {
218
248
  name: resolveNamespace("resource"),
219
249
  /**
@@ -246,7 +276,7 @@ function resourcePlugin(opts, meta) {
246
276
  debug$1("alias Config:", aliasConfig);
247
277
  return shared.assign(defineConfig, aliasConfig);
248
278
  },
249
- configResolved(config) {
279
+ async configResolved(config) {
250
280
  vuePlugin = getVitePlugin(config, "vite:vue");
251
281
  if (!checkVuePlugin(vuePlugin)) {
252
282
  return;
@@ -255,12 +285,13 @@ function resourcePlugin(opts, meta) {
255
285
  ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
256
286
  debug$1(`configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
257
287
  const jsonPlugin = getVitePlugin(config, "vite:json");
258
- if (jsonPlugin) {
259
- const [orgTransform, transformWay] = getVitePluginTransform(jsonPlugin);
260
- if (!orgTransform) {
261
- throw new Error("vite:json plugin not found!");
262
- }
263
- async function overrideViteJsonPlugin(code, id) {
288
+ hasViteJsonPlugin = !!jsonPlugin;
289
+ if (jsonPlugin && jsonPlugin.transform) {
290
+ const transform = jsonPlugin.transform;
291
+ const isObjectHook = typeof transform !== "function" && "handler" in transform;
292
+ const orgTransform = isObjectHook ? transform.handler : transform;
293
+ async function overrideJson(code, id) {
294
+ const filter = await getFilter();
264
295
  if (!/\.json$/.test(id) || filter(id)) {
265
296
  return;
266
297
  }
@@ -271,20 +302,45 @@ function resourcePlugin(opts, meta) {
271
302
  debug$1("org json plugin");
272
303
  return orgTransform.apply(this, [code, id]);
273
304
  }
274
- overrideVitePluginTransform(jsonPlugin, overrideViteJsonPlugin, transformWay);
305
+ if (isObjectHook) {
306
+ transform.handler = overrideJson;
307
+ } else {
308
+ jsonPlugin.transform = overrideJson;
309
+ }
275
310
  }
276
311
  }
277
312
  },
278
- resolveId(id, importer) {
279
- debug$1("resolveId", id, importer);
313
+ async resolveId(id, importer) {
314
+ debug$1("resolveId", id, "from", importer);
280
315
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
281
316
  return asVirtualId(id, meta.framework);
282
317
  }
318
+ if (meta.framework === "vite" && !hasViteJsonPlugin) {
319
+ if (id.includes("?vue&type=i18n") && /[?&]lang\.(?:json|json5)(?:$|&)/.test(id)) {
320
+ return intlifyVirtualize(id);
321
+ }
322
+ const idPath = id.split("?")[0];
323
+ if (!supportedFileExtensionsRE.test(idPath)) return;
324
+ let resolvedPath;
325
+ if (idPath.startsWith(".")) {
326
+ const realImporter = importer && isIntlifyVirtualId(importer) ? virtualIdToRealPath.get(importer) : importer;
327
+ if (!realImporter) return;
328
+ resolvedPath = node_path.resolve(node_path.dirname(realImporter), idPath);
329
+ } else if (idPath.startsWith("/") || /^[a-z]:[/\\]/i.test(idPath)) {
330
+ resolvedPath = idPath;
331
+ } else {
332
+ return;
333
+ }
334
+ const filter = await getFilter();
335
+ if (!filter(resolvedPath)) return;
336
+ return intlifyVirtualize(resolvedPath);
337
+ }
283
338
  },
284
339
  loadInclude(id) {
285
- return INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework);
340
+ if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework)) return true;
341
+ return isIntlifyVirtualId(id);
286
342
  },
287
- load(id) {
343
+ async load(id) {
288
344
  debug$1("load", id);
289
345
  if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
290
346
  const code = generateBundleResources(resourcePaths);
@@ -293,12 +349,78 @@ function resourcePlugin(opts, meta) {
293
349
  }
294
350
  return result(code);
295
351
  }
352
+ if (isIntlifyVirtualId(id)) {
353
+ const realId = virtualIdToRealPath.get(id);
354
+ if (realId.includes("?vue&type=i18n")) {
355
+ const { filename, query } = parseVueRequest(realId);
356
+ this.addWatchFile(filename);
357
+ const sfcSource = readFile(filename);
358
+ const { descriptor } = getSfcParser()(sfcSource, {
359
+ sourceMap: ctx.sourceMap,
360
+ filename
361
+ });
362
+ const block = descriptor.customBlocks[query.index];
363
+ if (!block) return;
364
+ let source = block.src ? readFile(block.src) : block.content;
365
+ if (typeof opts.transformI18nBlock === "function") {
366
+ const modifiedSource = opts.transformI18nBlock(source);
367
+ if (modifiedSource && typeof modifiedSource === "string") {
368
+ source = modifiedSource;
369
+ } else {
370
+ warn("transformI18nBlock should return a string");
371
+ }
372
+ }
373
+ const langInfo2 = query.lang || opts.defaultSFCLang;
374
+ const generate2 = getGenerator(langInfo2, bundleUtils.generateYAML);
375
+ const parseOptions2 = getOptions(filename, ctx, query, {
376
+ ...opts,
377
+ allowDynamic: false,
378
+ transformI18nBlock: void 0
379
+ });
380
+ const { code: generatedCode } = generate2(source, parseOptions2);
381
+ return result(generatedCode);
382
+ }
383
+ const realPath = realId;
384
+ this.addWatchFile(realPath);
385
+ const code = readFile(realPath);
386
+ const imports = mlly.findStaticImports(code);
387
+ for (const p of imports) {
388
+ const res = node_path.resolve(node_path.dirname(realPath), p.specifier);
389
+ importedResources.add(res);
390
+ }
391
+ const langInfo = node_path.parse(realPath).ext;
392
+ const generate = getGenerator(langInfo);
393
+ const parseOptions = getOptions(realPath, ctx, {}, {
394
+ ...opts,
395
+ transformI18nBlock: void 0
396
+ });
397
+ try {
398
+ const { code: generatedCode } = generate(code, parseOptions);
399
+ return result(generatedCode);
400
+ } catch (err) {
401
+ if (err instanceof bundleUtils.DynamicResourceError) {
402
+ error(
403
+ `Unable to precompile or optimize \`${realPath}\` - excluding from virtual bundle \`${INTLIFY_BUNDLE_IMPORT_ID}\`.
404
+ `,
405
+ err
406
+ );
407
+ return `export default {}`;
408
+ } else {
409
+ throw err;
410
+ }
411
+ }
412
+ }
296
413
  },
297
414
  transformInclude(id) {
298
415
  debug$1("transformInclude", id);
299
416
  if (meta.framework === "vite") {
300
417
  return true;
301
418
  }
419
+ const f = _filter ?? pluginutils.createFilter(...resolveIncludeExclude());
420
+ if (_filter == null) {
421
+ _filter = f;
422
+ }
423
+ const filterWithImported = (v) => f(v) || importedResources.has(v);
302
424
  const { filename, query } = parseVueRequest(id);
303
425
  if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
304
426
  return true;
@@ -307,12 +429,14 @@ function resourcePlugin(opts, meta) {
307
429
  if (!isResourcePath && "issuerPath" in query) {
308
430
  isResourcePath = resourcePaths.has(query.issuerPath);
309
431
  }
310
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
432
+ return supportedFileExtensionsRE.test(filename) && filterWithImported(filename) && isResourcePath;
311
433
  },
312
434
  async transform(code, id) {
435
+ if (isIntlifyVirtualId(id)) return;
313
436
  const { filename, query } = parseVueRequest(id);
314
437
  debug$1("transform", id, JSON.stringify(query), filename);
315
438
  let langInfo = opts.defaultSFCLang;
439
+ const filter = await getFilter();
316
440
  if (filter(id)) {
317
441
  const imports = mlly.findStaticImports(code);
318
442
  for (const p of imports) {
@@ -329,7 +453,7 @@ function resourcePlugin(opts, meta) {
329
453
  });
330
454
  debug$1("parseOptions", parseOptions);
331
455
  try {
332
- const { code: generatedCode, map } = await generate(code, parseOptions);
456
+ const { code: generatedCode, map } = generate(code, parseOptions);
333
457
  debug$1("generated code", generatedCode);
334
458
  debug$1("sourcemap", map, ctx.sourceMap);
335
459
  if (code === generatedCode) return;
@@ -369,7 +493,7 @@ function resourcePlugin(opts, meta) {
369
493
  }
370
494
  }
371
495
  const generate = getGenerator(langInfo, bundleUtils.generateYAML);
372
- const { code: generatedCode, map } = await generate(source, parseOptions);
496
+ const { code: generatedCode, map } = generate(source, parseOptions);
373
497
  debug$1("generated code", generatedCode);
374
498
  debug$1("sourcemap", map, ctx.sourceMap);
375
499
  if (code !== generatedCode) {
package/lib/index.mjs CHANGED
@@ -1,15 +1,16 @@
1
1
  import createDebug from 'debug';
2
2
  import { createUnplugin } from 'unplugin';
3
3
  import defu from 'defu';
4
- import { normalize, resolve, dirname, parse } from 'node:path';
5
- import { generateJSON, DynamicResourceError, generateYAML, generateJavaScript, generateTypescript } from '@intlify/bundle-utils';
4
+ import { normalize } from 'pathe';
5
+ import { DynamicResourceError, generateJSON, generateYAML, generateJavaScript, generateTypescript } from '@intlify/bundle-utils';
6
6
  import { assign, isEmptyObject, generateCodeFrame } from '@intlify/shared';
7
7
  import { createFilter } from '@rollup/pluginutils';
8
- import fg from 'fast-glob';
9
8
  import { genSafeVariableName, genImport } from 'knitwork';
10
9
  import { findStaticImports } from 'mlly';
11
10
  import { createHash } from 'node:crypto';
12
11
  import fs from 'node:fs';
12
+ import { resolve, dirname, parse } from 'node:path';
13
+ import { globSync } from 'tinyglobby';
13
14
  import { parse as parse$1 } from 'vue/compiler-sfc';
14
15
  import pc from 'picocolors';
15
16
 
@@ -76,23 +77,6 @@ function resolveNamespace(name) {
76
77
  function getVitePlugin(config, name) {
77
78
  return config.plugins.find((p) => p.name === name);
78
79
  }
79
- function getVitePluginTransform(plugin) {
80
- if (plugin.transform) {
81
- return "handler" in plugin.transform ? [plugin.transform.handler, "handler"] : [plugin.transform, "transform"];
82
- } else {
83
- return [void 0, void 0];
84
- }
85
- }
86
- function overrideVitePluginTransform(plugin, override, to) {
87
- if (plugin.transform == void 0) {
88
- throw new Error("plugin.transform is undefined");
89
- }
90
- if (to === "handler" && "handler" in plugin.transform) {
91
- plugin.transform.handler = override;
92
- } else {
93
- plugin.transform = override;
94
- }
95
- }
96
80
  function checkVuePlugin(vuePlugin) {
97
81
  if (vuePlugin == null || !vuePlugin.api) {
98
82
  error(
@@ -145,11 +129,53 @@ function getVueCompiler(vuePlugin) {
145
129
 
146
130
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
147
131
  const VIRTUAL_PREFIX = "\0";
132
+ const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
133
+ const RE_SFC_I18N_CUSTOM_BLOCK = /\?vue&type=i18n/;
134
+ const RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK = /blockType=i18n/;
148
135
  const debug$1 = createDebug(resolveNamespace("resource"));
149
136
  function resourcePlugin(opts, meta) {
150
- const _filter = createFilter(opts.include, opts.exclude);
151
137
  const importedResources = /* @__PURE__ */ new Set();
152
- const filter = (val) => _filter(val) || importedResources.has(val);
138
+ function resolveIncludeExclude() {
139
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
140
+ return opts.include ? [[...opts.include, customBlockInclude], opts.exclude] : [[supportedFileExtensionsRE, customBlockInclude], void 0];
141
+ }
142
+ function resolveIncludeExcludeForLegacy() {
143
+ const customBlockInclude = meta.framework === "vite" ? RE_SFC_I18N_CUSTOM_BLOCK : RE_SFC_I18N_WEBPACK_CUSTOM_BLOCK;
144
+ return opts.include ? [[...opts.include, customBlockInclude], opts.exclude] : [void 0, opts.exclude];
145
+ }
146
+ let _filter = null;
147
+ let hasViteJsonPlugin = false;
148
+ async function getFilter() {
149
+ if (_filter == null) {
150
+ if (meta.framework === "webpack" || meta.framework === "rspack") {
151
+ debug$1("Using filter for webpack/rspack");
152
+ _filter = createFilter(...resolveIncludeExclude());
153
+ } else if (hasViteJsonPlugin) {
154
+ debug$1("Using filter for rollup-vite");
155
+ _filter = createFilter(...resolveIncludeExcludeForLegacy());
156
+ } else {
157
+ debug$1("Using filter for rolldown-vite");
158
+ _filter = createFilter(...resolveIncludeExclude());
159
+ }
160
+ }
161
+ return (val) => _filter(val) || importedResources.has(val);
162
+ }
163
+ const VITE_VIRTUAL_PREFIX = "\0intlify-i18n-";
164
+ const virtualIdToRealPath = /* @__PURE__ */ new Map();
165
+ const realPathToVirtualId = /* @__PURE__ */ new Map();
166
+ let virtualCounter = 0;
167
+ function intlifyVirtualize(realPath) {
168
+ let virtualId = realPathToVirtualId.get(realPath);
169
+ if (!virtualId) {
170
+ virtualId = `${VITE_VIRTUAL_PREFIX}${virtualCounter++}`;
171
+ virtualIdToRealPath.set(virtualId, realPath);
172
+ realPathToVirtualId.set(realPath, virtualId);
173
+ }
174
+ return virtualId;
175
+ }
176
+ function isIntlifyVirtualId(id) {
177
+ return virtualIdToRealPath.has(id);
178
+ }
153
179
  debug$1(`vue-i18n alias name: ${opts.module}`);
154
180
  const ctx = {
155
181
  prod: false,
@@ -159,7 +185,11 @@ function resourcePlugin(opts, meta) {
159
185
  const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : parse$1;
160
186
  const resourcePaths = /* @__PURE__ */ new Set();
161
187
  for (const inc of opts.include || []) {
162
- for (const resourcePath of fg.sync(inc, { ignore: opts.exclude })) {
188
+ for (const resourcePath of globSync(inc, {
189
+ ignore: opts.exclude,
190
+ expandDirectories: false,
191
+ absolute: true
192
+ })) {
163
193
  resourcePaths.add(resourcePath);
164
194
  }
165
195
  }
@@ -173,6 +203,8 @@ function resourcePlugin(opts, meta) {
173
203
  ctx.prod = compiler.options.mode !== "development";
174
204
  ctx.sourceMap = !!compiler.options.devtool;
175
205
  debug$1(`${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
206
+ const syncFilter = createFilter(...resolveIncludeExclude());
207
+ _filter = syncFilter;
176
208
  compiler.options.resolve.alias = {
177
209
  ...compiler.options.resolve.alias,
178
210
  [opts.module]: opts.vueI18nAliasPath
@@ -198,10 +230,9 @@ function resourcePlugin(opts, meta) {
198
230
  compiler.options.module.rules.push({
199
231
  test: /\.(json5?|ya?ml)$/,
200
232
  type: "javascript/auto",
201
- include: (resource) => filter(resource)
233
+ include: (resource) => syncFilter(resource) || importedResources.has(resource)
202
234
  });
203
235
  }
204
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
205
236
  return {
206
237
  name: resolveNamespace("resource"),
207
238
  /**
@@ -234,7 +265,7 @@ function resourcePlugin(opts, meta) {
234
265
  debug$1("alias Config:", aliasConfig);
235
266
  return assign(defineConfig, aliasConfig);
236
267
  },
237
- configResolved(config) {
268
+ async configResolved(config) {
238
269
  vuePlugin = getVitePlugin(config, "vite:vue");
239
270
  if (!checkVuePlugin(vuePlugin)) {
240
271
  return;
@@ -243,12 +274,13 @@ function resourcePlugin(opts, meta) {
243
274
  ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
244
275
  debug$1(`configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
245
276
  const jsonPlugin = getVitePlugin(config, "vite:json");
246
- if (jsonPlugin) {
247
- const [orgTransform, transformWay] = getVitePluginTransform(jsonPlugin);
248
- if (!orgTransform) {
249
- throw new Error("vite:json plugin not found!");
250
- }
251
- async function overrideViteJsonPlugin(code, id) {
277
+ hasViteJsonPlugin = !!jsonPlugin;
278
+ if (jsonPlugin && jsonPlugin.transform) {
279
+ const transform = jsonPlugin.transform;
280
+ const isObjectHook = typeof transform !== "function" && "handler" in transform;
281
+ const orgTransform = isObjectHook ? transform.handler : transform;
282
+ async function overrideJson(code, id) {
283
+ const filter = await getFilter();
252
284
  if (!/\.json$/.test(id) || filter(id)) {
253
285
  return;
254
286
  }
@@ -259,20 +291,45 @@ function resourcePlugin(opts, meta) {
259
291
  debug$1("org json plugin");
260
292
  return orgTransform.apply(this, [code, id]);
261
293
  }
262
- overrideVitePluginTransform(jsonPlugin, overrideViteJsonPlugin, transformWay);
294
+ if (isObjectHook) {
295
+ transform.handler = overrideJson;
296
+ } else {
297
+ jsonPlugin.transform = overrideJson;
298
+ }
263
299
  }
264
300
  }
265
301
  },
266
- resolveId(id, importer) {
267
- debug$1("resolveId", id, importer);
302
+ async resolveId(id, importer) {
303
+ debug$1("resolveId", id, "from", importer);
268
304
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
269
305
  return asVirtualId(id, meta.framework);
270
306
  }
307
+ if (meta.framework === "vite" && !hasViteJsonPlugin) {
308
+ if (id.includes("?vue&type=i18n") && /[?&]lang\.(?:json|json5)(?:$|&)/.test(id)) {
309
+ return intlifyVirtualize(id);
310
+ }
311
+ const idPath = id.split("?")[0];
312
+ if (!supportedFileExtensionsRE.test(idPath)) return;
313
+ let resolvedPath;
314
+ if (idPath.startsWith(".")) {
315
+ const realImporter = importer && isIntlifyVirtualId(importer) ? virtualIdToRealPath.get(importer) : importer;
316
+ if (!realImporter) return;
317
+ resolvedPath = resolve(dirname(realImporter), idPath);
318
+ } else if (idPath.startsWith("/") || /^[a-z]:[/\\]/i.test(idPath)) {
319
+ resolvedPath = idPath;
320
+ } else {
321
+ return;
322
+ }
323
+ const filter = await getFilter();
324
+ if (!filter(resolvedPath)) return;
325
+ return intlifyVirtualize(resolvedPath);
326
+ }
271
327
  },
272
328
  loadInclude(id) {
273
- return INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework);
329
+ if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework)) return true;
330
+ return isIntlifyVirtualId(id);
274
331
  },
275
- load(id) {
332
+ async load(id) {
276
333
  debug$1("load", id);
277
334
  if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
278
335
  const code = generateBundleResources(resourcePaths);
@@ -281,12 +338,78 @@ function resourcePlugin(opts, meta) {
281
338
  }
282
339
  return result(code);
283
340
  }
341
+ if (isIntlifyVirtualId(id)) {
342
+ const realId = virtualIdToRealPath.get(id);
343
+ if (realId.includes("?vue&type=i18n")) {
344
+ const { filename, query } = parseVueRequest(realId);
345
+ this.addWatchFile(filename);
346
+ const sfcSource = readFile(filename);
347
+ const { descriptor } = getSfcParser()(sfcSource, {
348
+ sourceMap: ctx.sourceMap,
349
+ filename
350
+ });
351
+ const block = descriptor.customBlocks[query.index];
352
+ if (!block) return;
353
+ let source = block.src ? readFile(block.src) : block.content;
354
+ if (typeof opts.transformI18nBlock === "function") {
355
+ const modifiedSource = opts.transformI18nBlock(source);
356
+ if (modifiedSource && typeof modifiedSource === "string") {
357
+ source = modifiedSource;
358
+ } else {
359
+ warn("transformI18nBlock should return a string");
360
+ }
361
+ }
362
+ const langInfo2 = query.lang || opts.defaultSFCLang;
363
+ const generate2 = getGenerator(langInfo2, generateYAML);
364
+ const parseOptions2 = getOptions(filename, ctx, query, {
365
+ ...opts,
366
+ allowDynamic: false,
367
+ transformI18nBlock: void 0
368
+ });
369
+ const { code: generatedCode } = generate2(source, parseOptions2);
370
+ return result(generatedCode);
371
+ }
372
+ const realPath = realId;
373
+ this.addWatchFile(realPath);
374
+ const code = readFile(realPath);
375
+ const imports = findStaticImports(code);
376
+ for (const p of imports) {
377
+ const res = resolve(dirname(realPath), p.specifier);
378
+ importedResources.add(res);
379
+ }
380
+ const langInfo = parse(realPath).ext;
381
+ const generate = getGenerator(langInfo);
382
+ const parseOptions = getOptions(realPath, ctx, {}, {
383
+ ...opts,
384
+ transformI18nBlock: void 0
385
+ });
386
+ try {
387
+ const { code: generatedCode } = generate(code, parseOptions);
388
+ return result(generatedCode);
389
+ } catch (err) {
390
+ if (err instanceof DynamicResourceError) {
391
+ error(
392
+ `Unable to precompile or optimize \`${realPath}\` - excluding from virtual bundle \`${INTLIFY_BUNDLE_IMPORT_ID}\`.
393
+ `,
394
+ err
395
+ );
396
+ return `export default {}`;
397
+ } else {
398
+ throw err;
399
+ }
400
+ }
401
+ }
284
402
  },
285
403
  transformInclude(id) {
286
404
  debug$1("transformInclude", id);
287
405
  if (meta.framework === "vite") {
288
406
  return true;
289
407
  }
408
+ const f = _filter ?? createFilter(...resolveIncludeExclude());
409
+ if (_filter == null) {
410
+ _filter = f;
411
+ }
412
+ const filterWithImported = (v) => f(v) || importedResources.has(v);
290
413
  const { filename, query } = parseVueRequest(id);
291
414
  if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
292
415
  return true;
@@ -295,12 +418,14 @@ function resourcePlugin(opts, meta) {
295
418
  if (!isResourcePath && "issuerPath" in query) {
296
419
  isResourcePath = resourcePaths.has(query.issuerPath);
297
420
  }
298
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
421
+ return supportedFileExtensionsRE.test(filename) && filterWithImported(filename) && isResourcePath;
299
422
  },
300
423
  async transform(code, id) {
424
+ if (isIntlifyVirtualId(id)) return;
301
425
  const { filename, query } = parseVueRequest(id);
302
426
  debug$1("transform", id, JSON.stringify(query), filename);
303
427
  let langInfo = opts.defaultSFCLang;
428
+ const filter = await getFilter();
304
429
  if (filter(id)) {
305
430
  const imports = findStaticImports(code);
306
431
  for (const p of imports) {
@@ -317,7 +442,7 @@ function resourcePlugin(opts, meta) {
317
442
  });
318
443
  debug$1("parseOptions", parseOptions);
319
444
  try {
320
- const { code: generatedCode, map } = await generate(code, parseOptions);
445
+ const { code: generatedCode, map } = generate(code, parseOptions);
321
446
  debug$1("generated code", generatedCode);
322
447
  debug$1("sourcemap", map, ctx.sourceMap);
323
448
  if (code === generatedCode) return;
@@ -357,7 +482,7 @@ function resourcePlugin(opts, meta) {
357
482
  }
358
483
  }
359
484
  const generate = getGenerator(langInfo, generateYAML);
360
- const { code: generatedCode, map } = await generate(source, parseOptions);
485
+ const { code: generatedCode, map } = generate(source, parseOptions);
361
486
  debug$1("generated code", generatedCode);
362
487
  debug$1("sourcemap", map, ctx.sourceMap);
363
488
  if (code !== generatedCode) {
package/lib/rspack.cjs CHANGED
@@ -4,15 +4,16 @@ const unplugin = require('unplugin');
4
4
  const index = require('./index.cjs');
5
5
  require('debug');
6
6
  require('defu');
7
- require('node:path');
7
+ require('pathe');
8
8
  require('@intlify/bundle-utils');
9
9
  require('@intlify/shared');
10
10
  require('@rollup/pluginutils');
11
- require('fast-glob');
12
11
  require('knitwork');
13
12
  require('mlly');
14
13
  require('node:crypto');
15
14
  require('node:fs');
15
+ require('node:path');
16
+ require('tinyglobby');
16
17
  require('vue/compiler-sfc');
17
18
  require('picocolors');
18
19
 
package/lib/rspack.mjs CHANGED
@@ -2,15 +2,16 @@ import { createRspackPlugin } from 'unplugin';
2
2
  import { unpluginFactory } from './index.mjs';
3
3
  import 'debug';
4
4
  import 'defu';
5
- import 'node:path';
5
+ import 'pathe';
6
6
  import '@intlify/bundle-utils';
7
7
  import '@intlify/shared';
8
8
  import '@rollup/pluginutils';
9
- import 'fast-glob';
10
9
  import 'knitwork';
11
10
  import 'mlly';
12
11
  import 'node:crypto';
13
12
  import 'node:fs';
13
+ import 'node:path';
14
+ import 'tinyglobby';
14
15
  import 'vue/compiler-sfc';
15
16
  import 'picocolors';
16
17
 
package/lib/vite.cjs CHANGED
@@ -4,15 +4,16 @@ const unplugin = require('unplugin');
4
4
  const index = require('./index.cjs');
5
5
  require('debug');
6
6
  require('defu');
7
- require('node:path');
7
+ require('pathe');
8
8
  require('@intlify/bundle-utils');
9
9
  require('@intlify/shared');
10
10
  require('@rollup/pluginutils');
11
- require('fast-glob');
12
11
  require('knitwork');
13
12
  require('mlly');
14
13
  require('node:crypto');
15
14
  require('node:fs');
15
+ require('node:path');
16
+ require('tinyglobby');
16
17
  require('vue/compiler-sfc');
17
18
  require('picocolors');
18
19
 
package/lib/vite.mjs CHANGED
@@ -2,15 +2,16 @@ import { createVitePlugin } from 'unplugin';
2
2
  import { unpluginFactory } from './index.mjs';
3
3
  import 'debug';
4
4
  import 'defu';
5
- import 'node:path';
5
+ import 'pathe';
6
6
  import '@intlify/bundle-utils';
7
7
  import '@intlify/shared';
8
8
  import '@rollup/pluginutils';
9
- import 'fast-glob';
10
9
  import 'knitwork';
11
10
  import 'mlly';
12
11
  import 'node:crypto';
13
12
  import 'node:fs';
13
+ import 'node:path';
14
+ import 'tinyglobby';
14
15
  import 'vue/compiler-sfc';
15
16
  import 'picocolors';
16
17
 
package/lib/webpack.cjs CHANGED
@@ -4,15 +4,16 @@ const unplugin = require('unplugin');
4
4
  const index = require('./index.cjs');
5
5
  require('debug');
6
6
  require('defu');
7
- require('node:path');
7
+ require('pathe');
8
8
  require('@intlify/bundle-utils');
9
9
  require('@intlify/shared');
10
10
  require('@rollup/pluginutils');
11
- require('fast-glob');
12
11
  require('knitwork');
13
12
  require('mlly');
14
13
  require('node:crypto');
15
14
  require('node:fs');
15
+ require('node:path');
16
+ require('tinyglobby');
16
17
  require('vue/compiler-sfc');
17
18
  require('picocolors');
18
19
 
package/lib/webpack.mjs CHANGED
@@ -2,15 +2,16 @@ import { createWebpackPlugin } from 'unplugin';
2
2
  import { unpluginFactory } from './index.mjs';
3
3
  import 'debug';
4
4
  import 'defu';
5
- import 'node:path';
5
+ import 'pathe';
6
6
  import '@intlify/bundle-utils';
7
7
  import '@intlify/shared';
8
8
  import '@rollup/pluginutils';
9
- import 'fast-glob';
10
9
  import 'knitwork';
11
10
  import 'mlly';
12
11
  import 'node:crypto';
13
12
  import 'node:fs';
13
+ import 'node:path';
14
+ import 'tinyglobby';
14
15
  import 'vue/compiler-sfc';
15
16
  import 'picocolors';
16
17
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@intlify/unplugin-vue-i18n",
3
3
  "type": "module",
4
- "version": "12.0.0-alpha.2",
4
+ "version": "12.0.0-alpha.3",
5
5
  "description": "unplugin for Vue I18n",
6
6
  "author": {
7
7
  "name": "kazuya kawaguchi",
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "peerDependencies": {
14
14
  "petite-vue-i18n": "^12.0.0-alpha.2",
15
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
15
16
  "vue": "^3.2.25",
16
17
  "vue-i18n": "^12.0.0-alpha.2"
17
18
  },
@@ -19,6 +20,9 @@
19
20
  "petite-vue-i18n": {
20
21
  "optional": true
21
22
  },
23
+ "vite": {
24
+ "optional": true
25
+ },
22
26
  "vue-i18n": {
23
27
  "optional": true
24
28
  }
@@ -28,33 +32,35 @@
28
32
  "@rollup/pluginutils": "^5.1.0",
29
33
  "debug": "^4.3.3",
30
34
  "defu": "^6.1.4",
31
- "fast-glob": "^3.2.12",
32
35
  "knitwork": "^1.2.0",
33
36
  "mlly": "^1.2.0",
37
+ "pathe": "^2.0.3",
34
38
  "picocolors": "^1.0.0",
39
+ "tinyglobby": "^0.2.15",
35
40
  "unplugin": "^2.2.0",
36
- "vue": "^3.5.13",
37
- "@intlify/bundle-utils": "12.0.0-alpha.2"
41
+ "vue": "~3.5.34",
42
+ "@intlify/bundle-utils": "12.0.0-alpha.3"
38
43
  },
39
44
  "devDependencies": {
40
45
  "@intlify/core-base": "next",
41
46
  "@rspack/core": "^1.2.7",
42
47
  "@types/debug": "^4.1.5",
43
- "@types/jsdom": "^16.2.5",
48
+ "@types/jsdom": "^28.0.0",
44
49
  "@types/memory-fs": "^0.3.2",
45
- "@types/node": "^22.13.11",
46
- "@vitejs/plugin-vue": "^5.2.3",
47
- "jsdom": "^25.0.1",
50
+ "@types/node": "^25.7.0",
51
+ "@vitejs/plugin-vue": "^6.0.6",
52
+ "jsdom": "^29.0.0",
48
53
  "memory-fs": "^0.5.0",
49
- "ts-loader": "^9.5.2",
50
- "unbuild": "^3.5.0",
51
- "vite": "^6.2.2",
52
- "vue-loader": "^16.8.3",
53
- "webpack": "^5.92.0",
54
+ "rollup-vite": "npm:vite@6.4.2",
55
+ "ts-loader": "~9.5.7",
56
+ "unbuild": "^3.6.1",
57
+ "vite": "^8.0.0",
58
+ "vue-loader": "~17.4.2",
59
+ "webpack": "~5.106.2",
54
60
  "webpack-merge": "^5.9.0"
55
61
  },
56
62
  "engines": {
57
- "node": ">= 20"
63
+ "node": ">= 22.13"
58
64
  },
59
65
  "files": [
60
66
  "lib",