@intlify/unplugin-vue-i18n 12.0.0-alpha.1 → 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;
@@ -140,11 +140,53 @@ function getVueCompiler(vuePlugin) {
140
140
 
141
141
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
142
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/;
143
146
  const debug$1 = createDebug__default(resolveNamespace("resource"));
144
147
  function resourcePlugin(opts, meta) {
145
- const _filter = pluginutils.createFilter(opts.include, opts.exclude);
146
148
  const importedResources = /* @__PURE__ */ new Set();
147
- 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
+ }
148
190
  debug$1(`vue-i18n alias name: ${opts.module}`);
149
191
  const ctx = {
150
192
  prod: false,
@@ -154,7 +196,11 @@ function resourcePlugin(opts, meta) {
154
196
  const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
155
197
  const resourcePaths = /* @__PURE__ */ new Set();
156
198
  for (const inc of opts.include || []) {
157
- 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
+ })) {
158
204
  resourcePaths.add(resourcePath);
159
205
  }
160
206
  }
@@ -168,6 +214,8 @@ function resourcePlugin(opts, meta) {
168
214
  ctx.prod = compiler.options.mode !== "development";
169
215
  ctx.sourceMap = !!compiler.options.devtool;
170
216
  debug$1(`${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
217
+ const syncFilter = pluginutils.createFilter(...resolveIncludeExclude());
218
+ _filter = syncFilter;
171
219
  compiler.options.resolve.alias = {
172
220
  ...compiler.options.resolve.alias,
173
221
  [opts.module]: opts.vueI18nAliasPath
@@ -193,10 +241,9 @@ function resourcePlugin(opts, meta) {
193
241
  compiler.options.module.rules.push({
194
242
  test: /\.(json5?|ya?ml)$/,
195
243
  type: "javascript/auto",
196
- include: (resource) => filter(resource)
244
+ include: (resource) => syncFilter(resource) || importedResources.has(resource)
197
245
  });
198
246
  }
199
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
200
247
  return {
201
248
  name: resolveNamespace("resource"),
202
249
  /**
@@ -229,7 +276,7 @@ function resourcePlugin(opts, meta) {
229
276
  debug$1("alias Config:", aliasConfig);
230
277
  return shared.assign(defineConfig, aliasConfig);
231
278
  },
232
- configResolved(config) {
279
+ async configResolved(config) {
233
280
  vuePlugin = getVitePlugin(config, "vite:vue");
234
281
  if (!checkVuePlugin(vuePlugin)) {
235
282
  return;
@@ -238,9 +285,13 @@ function resourcePlugin(opts, meta) {
238
285
  ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
239
286
  debug$1(`configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
240
287
  const jsonPlugin = getVitePlugin(config, "vite:json");
241
- if (jsonPlugin) {
242
- const orgTransform = jsonPlugin.transform;
243
- jsonPlugin.transform = async function(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();
244
295
  if (!/\.json$/.test(id) || filter(id)) {
245
296
  return;
246
297
  }
@@ -250,20 +301,46 @@ function resourcePlugin(opts, meta) {
250
301
  }
251
302
  debug$1("org json plugin");
252
303
  return orgTransform.apply(this, [code, id]);
253
- };
304
+ }
305
+ if (isObjectHook) {
306
+ transform.handler = overrideJson;
307
+ } else {
308
+ jsonPlugin.transform = overrideJson;
309
+ }
254
310
  }
255
311
  }
256
312
  },
257
- resolveId(id, importer) {
258
- debug$1("resolveId", id, importer);
313
+ async resolveId(id, importer) {
314
+ debug$1("resolveId", id, "from", importer);
259
315
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
260
316
  return asVirtualId(id, meta.framework);
261
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
+ }
262
338
  },
263
339
  loadInclude(id) {
264
- 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);
265
342
  },
266
- load(id) {
343
+ async load(id) {
267
344
  debug$1("load", id);
268
345
  if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
269
346
  const code = generateBundleResources(resourcePaths);
@@ -272,12 +349,78 @@ function resourcePlugin(opts, meta) {
272
349
  }
273
350
  return result(code);
274
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
+ }
275
413
  },
276
414
  transformInclude(id) {
277
415
  debug$1("transformInclude", id);
278
416
  if (meta.framework === "vite") {
279
417
  return true;
280
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);
281
424
  const { filename, query } = parseVueRequest(id);
282
425
  if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
283
426
  return true;
@@ -286,12 +429,14 @@ function resourcePlugin(opts, meta) {
286
429
  if (!isResourcePath && "issuerPath" in query) {
287
430
  isResourcePath = resourcePaths.has(query.issuerPath);
288
431
  }
289
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
432
+ return supportedFileExtensionsRE.test(filename) && filterWithImported(filename) && isResourcePath;
290
433
  },
291
434
  async transform(code, id) {
435
+ if (isIntlifyVirtualId(id)) return;
292
436
  const { filename, query } = parseVueRequest(id);
293
437
  debug$1("transform", id, JSON.stringify(query), filename);
294
438
  let langInfo = opts.defaultSFCLang;
439
+ const filter = await getFilter();
295
440
  if (filter(id)) {
296
441
  const imports = mlly.findStaticImports(code);
297
442
  for (const p of imports) {
@@ -311,8 +456,7 @@ function resourcePlugin(opts, meta) {
311
456
  const { code: generatedCode, map } = generate(code, parseOptions);
312
457
  debug$1("generated code", generatedCode);
313
458
  debug$1("sourcemap", map, ctx.sourceMap);
314
- if (code === generatedCode)
315
- return;
459
+ if (code === generatedCode) return;
316
460
  return result(generatedCode);
317
461
  } catch (err) {
318
462
  if (err instanceof bundleUtils.DynamicResourceError) {
@@ -366,9 +510,12 @@ function getGenerator(ext, fallback = bundleUtils.generateJSON) {
366
510
  if (/\.ya?ml$/.test(ext)) {
367
511
  return bundleUtils.generateYAML;
368
512
  }
369
- if (/\.[c|m]?[j|t]s$/.test(ext)) {
513
+ if (/\.[c|m]?js$/.test(ext)) {
370
514
  return bundleUtils.generateJavaScript;
371
515
  }
516
+ if (/\.[c|m]?ts$/.test(ext)) {
517
+ return bundleUtils.generateTypescript;
518
+ }
372
519
  return fallback;
373
520
  }
374
521
  async function loadWebpack() {
package/lib/index.d.cts CHANGED
@@ -1,8 +1,10 @@
1
- import { UnpluginFactory, UnpluginInstance } from 'unplugin';
1
+ import { UnpluginInstance, UnpluginFactory } from 'unplugin';
2
2
  import { PluginOptions } from './types.cjs';
3
3
  export { SFCLangFormat, VueI18nModule } from './types.cjs';
4
4
 
5
5
  declare const unpluginFactory: UnpluginFactory<PluginOptions | undefined>;
6
6
  declare const unplugin: UnpluginInstance<PluginOptions | undefined, boolean>;
7
7
 
8
- export { PluginOptions, unplugin as default, unplugin, unpluginFactory };
8
+ // @ts-ignore
9
+ export = unplugin;
10
+ export { PluginOptions, unplugin, unpluginFactory };
package/lib/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { UnpluginFactory, UnpluginInstance } from 'unplugin';
1
+ import { UnpluginInstance, UnpluginFactory } from 'unplugin';
2
2
  import { PluginOptions } from './types.mjs';
3
3
  export { SFCLangFormat, VueI18nModule } from './types.mjs';
4
4
 
package/lib/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
- import { UnpluginFactory, UnpluginInstance } from 'unplugin';
1
+ import { UnpluginInstance, UnpluginFactory } from 'unplugin';
2
2
  import { PluginOptions } from './types.js';
3
3
  export { SFCLangFormat, VueI18nModule } from './types.js';
4
4
 
5
5
  declare const unpluginFactory: UnpluginFactory<PluginOptions | undefined>;
6
6
  declare const unplugin: UnpluginInstance<PluginOptions | undefined, boolean>;
7
7
 
8
- export { PluginOptions, unplugin as default, unplugin, unpluginFactory };
8
+ // @ts-ignore
9
+ export = unplugin;
10
+ export { PluginOptions, unplugin, unpluginFactory };
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 { DynamicResourceError, generateJSON, generateYAML, generateJavaScript } 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
 
@@ -128,11 +129,53 @@ function getVueCompiler(vuePlugin) {
128
129
 
129
130
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
130
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/;
131
135
  const debug$1 = createDebug(resolveNamespace("resource"));
132
136
  function resourcePlugin(opts, meta) {
133
- const _filter = createFilter(opts.include, opts.exclude);
134
137
  const importedResources = /* @__PURE__ */ new Set();
135
- 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
+ }
136
179
  debug$1(`vue-i18n alias name: ${opts.module}`);
137
180
  const ctx = {
138
181
  prod: false,
@@ -142,7 +185,11 @@ function resourcePlugin(opts, meta) {
142
185
  const getSfcParser = () => vuePlugin ? getVueCompiler(vuePlugin).parse : parse$1;
143
186
  const resourcePaths = /* @__PURE__ */ new Set();
144
187
  for (const inc of opts.include || []) {
145
- 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
+ })) {
146
193
  resourcePaths.add(resourcePath);
147
194
  }
148
195
  }
@@ -156,6 +203,8 @@ function resourcePlugin(opts, meta) {
156
203
  ctx.prod = compiler.options.mode !== "development";
157
204
  ctx.sourceMap = !!compiler.options.devtool;
158
205
  debug$1(`${meta.framework}: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
206
+ const syncFilter = createFilter(...resolveIncludeExclude());
207
+ _filter = syncFilter;
159
208
  compiler.options.resolve.alias = {
160
209
  ...compiler.options.resolve.alias,
161
210
  [opts.module]: opts.vueI18nAliasPath
@@ -181,10 +230,9 @@ function resourcePlugin(opts, meta) {
181
230
  compiler.options.module.rules.push({
182
231
  test: /\.(json5?|ya?ml)$/,
183
232
  type: "javascript/auto",
184
- include: (resource) => filter(resource)
233
+ include: (resource) => syncFilter(resource) || importedResources.has(resource)
185
234
  });
186
235
  }
187
- const supportedFileExtensionsRE = /\.(json5?|ya?ml|[c|m]?[j|t]s)$/;
188
236
  return {
189
237
  name: resolveNamespace("resource"),
190
238
  /**
@@ -217,7 +265,7 @@ function resourcePlugin(opts, meta) {
217
265
  debug$1("alias Config:", aliasConfig);
218
266
  return assign(defineConfig, aliasConfig);
219
267
  },
220
- configResolved(config) {
268
+ async configResolved(config) {
221
269
  vuePlugin = getVitePlugin(config, "vite:vue");
222
270
  if (!checkVuePlugin(vuePlugin)) {
223
271
  return;
@@ -226,9 +274,13 @@ function resourcePlugin(opts, meta) {
226
274
  ctx.sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
227
275
  debug$1(`configResolved: isProduction = ${ctx.prod}, sourceMap = ${ctx.sourceMap}`);
228
276
  const jsonPlugin = getVitePlugin(config, "vite:json");
229
- if (jsonPlugin) {
230
- const orgTransform = jsonPlugin.transform;
231
- jsonPlugin.transform = async function(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();
232
284
  if (!/\.json$/.test(id) || filter(id)) {
233
285
  return;
234
286
  }
@@ -238,20 +290,46 @@ function resourcePlugin(opts, meta) {
238
290
  }
239
291
  debug$1("org json plugin");
240
292
  return orgTransform.apply(this, [code, id]);
241
- };
293
+ }
294
+ if (isObjectHook) {
295
+ transform.handler = overrideJson;
296
+ } else {
297
+ jsonPlugin.transform = overrideJson;
298
+ }
242
299
  }
243
300
  }
244
301
  },
245
- resolveId(id, importer) {
246
- debug$1("resolveId", id, importer);
302
+ async resolveId(id, importer) {
303
+ debug$1("resolveId", id, "from", importer);
247
304
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
248
305
  return asVirtualId(id, meta.framework);
249
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
+ }
250
327
  },
251
328
  loadInclude(id) {
252
- 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);
253
331
  },
254
- load(id) {
332
+ async load(id) {
255
333
  debug$1("load", id);
256
334
  if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && resourcePaths.size > 0) {
257
335
  const code = generateBundleResources(resourcePaths);
@@ -260,12 +338,78 @@ function resourcePlugin(opts, meta) {
260
338
  }
261
339
  return result(code);
262
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
+ }
263
402
  },
264
403
  transformInclude(id) {
265
404
  debug$1("transformInclude", id);
266
405
  if (meta.framework === "vite") {
267
406
  return true;
268
407
  }
408
+ const f = _filter ?? createFilter(...resolveIncludeExclude());
409
+ if (_filter == null) {
410
+ _filter = f;
411
+ }
412
+ const filterWithImported = (v) => f(v) || importedResources.has(v);
269
413
  const { filename, query } = parseVueRequest(id);
270
414
  if (filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID)) {
271
415
  return true;
@@ -274,12 +418,14 @@ function resourcePlugin(opts, meta) {
274
418
  if (!isResourcePath && "issuerPath" in query) {
275
419
  isResourcePath = resourcePaths.has(query.issuerPath);
276
420
  }
277
- return supportedFileExtensionsRE.test(filename) && filter(filename) && isResourcePath;
421
+ return supportedFileExtensionsRE.test(filename) && filterWithImported(filename) && isResourcePath;
278
422
  },
279
423
  async transform(code, id) {
424
+ if (isIntlifyVirtualId(id)) return;
280
425
  const { filename, query } = parseVueRequest(id);
281
426
  debug$1("transform", id, JSON.stringify(query), filename);
282
427
  let langInfo = opts.defaultSFCLang;
428
+ const filter = await getFilter();
283
429
  if (filter(id)) {
284
430
  const imports = findStaticImports(code);
285
431
  for (const p of imports) {
@@ -299,8 +445,7 @@ function resourcePlugin(opts, meta) {
299
445
  const { code: generatedCode, map } = generate(code, parseOptions);
300
446
  debug$1("generated code", generatedCode);
301
447
  debug$1("sourcemap", map, ctx.sourceMap);
302
- if (code === generatedCode)
303
- return;
448
+ if (code === generatedCode) return;
304
449
  return result(generatedCode);
305
450
  } catch (err) {
306
451
  if (err instanceof DynamicResourceError) {
@@ -354,9 +499,12 @@ function getGenerator(ext, fallback = generateJSON) {
354
499
  if (/\.ya?ml$/.test(ext)) {
355
500
  return generateYAML;
356
501
  }
357
- if (/\.[c|m]?[j|t]s$/.test(ext)) {
502
+ if (/\.[c|m]?js$/.test(ext)) {
358
503
  return generateJavaScript;
359
504
  }
505
+ if (/\.[c|m]?ts$/.test(ext)) {
506
+ return generateTypescript;
507
+ }
360
508
  return fallback;
361
509
  }
362
510
  async function loadWebpack() {
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.1",
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.4",
37
- "@intlify/bundle-utils": "12.0.0-alpha.1"
41
+ "vue": "~3.5.34",
42
+ "@intlify/bundle-utils": "12.0.0-alpha.3"
38
43
  },
39
44
  "devDependencies": {
40
- "@types/node": "^20.14.8",
41
- "@types/jsdom": "^16.2.5",
42
- "@types/memory-fs": "^0.3.2",
43
- "@types/debug": "^4.1.5",
44
- "@rspack/core": "^1.2.7",
45
45
  "@intlify/core-base": "next",
46
- "vite": "^6.2.2",
47
- "@vitejs/plugin-vue": "^5.2.3",
48
- "jsdom": "^25.0.1",
46
+ "@rspack/core": "^1.2.7",
47
+ "@types/debug": "^4.1.5",
48
+ "@types/jsdom": "^28.0.0",
49
+ "@types/memory-fs": "^0.3.2",
50
+ "@types/node": "^25.7.0",
51
+ "@vitejs/plugin-vue": "^6.0.6",
52
+ "jsdom": "^29.0.0",
49
53
  "memory-fs": "^0.5.0",
50
- "vue-loader": "^16.3.0",
51
- "ts-loader": "^9.5.2",
52
- "unbuild": "^2.0.0",
53
- "webpack": "^5.88.2",
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",