@intlify/unplugin-vue-i18n 5.0.0-beta.1 → 5.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
@@ -3,64 +3,128 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const unplugin$1 = require('unplugin');
6
- const pathe = require('pathe');
7
6
  const createDebug = require('debug');
8
- const fg = require('fast-glob');
7
+ const pc = require('picocolors');
8
+ const path = require('node:path');
9
+ const fs = require('node:fs');
10
+ const module$1 = require('node:module');
11
+ const pathe = require('pathe');
12
+ const mlly = require('mlly');
9
13
  const shared = require('@intlify/shared');
14
+ const fg = require('fast-glob');
10
15
  const pluginutils = require('@rollup/pluginutils');
11
16
  const bundleUtils = require('@intlify/bundle-utils');
12
- const compilerSfc = require('@vue/compiler-sfc');
13
- const fs = require('node:fs');
14
- const pc = require('picocolors');
15
- const module$1 = require('node:module');
16
- const path = require('node:path');
17
+ const compilerSfc = require('vue/compiler-sfc');
18
+ const vueI18nExtensions = require('@intlify/vue-i18n-extensions');
19
+ const scopeManager = require('@typescript-eslint/scope-manager');
20
+ const typescriptEstree = require('@typescript-eslint/typescript-estree');
21
+ const eslintUitls = require('@eslint-community/eslint-utils');
17
22
 
18
23
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
19
24
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
20
25
 
21
26
  const createDebug__default = /*#__PURE__*/_interopDefaultCompat(createDebug);
22
- const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
23
- const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
24
27
  const pc__default = /*#__PURE__*/_interopDefaultCompat(pc);
25
- const module__default = /*#__PURE__*/_interopDefaultCompat(module$1);
26
28
  const path__default = /*#__PURE__*/_interopDefaultCompat(path);
29
+ const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
30
+ const module__default = /*#__PURE__*/_interopDefaultCompat(module$1);
31
+ const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
32
+ const eslintUitls__default = /*#__PURE__*/_interopDefaultCompat(eslintUitls);
27
33
 
28
- function parseVueRequest(id) {
29
- const [filename, rawQuery] = id.split(`?`, 2);
30
- const params = new URLSearchParams(rawQuery);
31
- const ret = {};
32
- const langPart = Object.keys(Object.fromEntries(params)).find(
33
- (key) => /lang\./i.test(key)
34
- );
35
- ret.vue = params.has("vue");
36
- ret.global = params.has("global");
37
- ret.src = params.has("src");
38
- ret.raw = params.has("raw");
39
- if (params.has("type")) {
40
- ret.type = params.get("type");
41
- }
42
- if (params.has("blockType")) {
43
- ret.blockType = params.get("blockType");
34
+ const PKG_NAME = "unplugin-vue-i18n";
35
+
36
+ function warn(...args) {
37
+ console.warn(pc__default.yellow(pc__default.bold(`[${PKG_NAME}] `)), ...args);
38
+ }
39
+ function error(...args) {
40
+ console.error(pc__default.red(pc__default.bold(`[${PKG_NAME}] `)), ...args);
41
+ }
42
+ function raiseError(message) {
43
+ throw new Error(`[${PKG_NAME}] ${message}`);
44
+ }
45
+
46
+ function resolveNamespace(name) {
47
+ return `${PKG_NAME}:${name}`;
48
+ }
49
+ function getVitePlugin(config, name) {
50
+ return config.plugins.find((p) => p.name === name);
51
+ }
52
+ function checkVuePlugin(vuePlugin) {
53
+ if (vuePlugin == null || !vuePlugin.api) {
54
+ error(
55
+ "`@vitejs/plugin-vue` plugin is not found or invalid version. Please install `@vitejs/plugin-vue` v4.3.4 or later version."
56
+ );
57
+ return false;
44
58
  }
45
- if (params.has("index")) {
46
- ret.index = Number(params.get("index"));
59
+ return true;
60
+ }
61
+ const isWindows = typeof process !== "undefined" && process.platform === "win32";
62
+ const windowsSlashRE = /\\/g;
63
+ function slash(p) {
64
+ return p.replace(windowsSlashRE, "/");
65
+ }
66
+ function normalizePath(id) {
67
+ return path__default.posix.normalize(isWindows ? slash(id) : id);
68
+ }
69
+
70
+ const defaultFindOptions = {
71
+ startingFrom: ".",
72
+ rootPattern: /^node_modules$/,
73
+ reverse: false,
74
+ test: (filePath) => {
75
+ try {
76
+ if (fs.statSync(filePath).isFile()) {
77
+ return true;
78
+ }
79
+ } catch {
80
+ }
47
81
  }
48
- if (params.has("locale")) {
49
- ret.locale = params.get("locale");
82
+ };
83
+ function findFile(filename, _options = {}) {
84
+ const filenames = Array.isArray(filename) ? filename : [filename];
85
+ const options = { ...defaultFindOptions, ..._options };
86
+ const basePath = pathe.resolve(options.startingFrom);
87
+ const leadingSlash = basePath[0] === "/";
88
+ const segments = basePath.split("/").filter(Boolean);
89
+ if (leadingSlash) {
90
+ segments[0] = "/" + segments[0];
50
91
  }
51
- if (langPart) {
52
- const [, lang] = langPart.split(".");
53
- ret.lang = lang;
54
- } else if (params.has("lang")) {
55
- ret.lang = params.get("lang");
92
+ let root = segments.findIndex((r) => r.match(options.rootPattern));
93
+ if (root === -1) {
94
+ root = 0;
56
95
  }
57
- if (params.has("issuerPath")) {
58
- ret.issuerPath = params.get("issuerPath");
96
+ if (options.reverse) {
97
+ for (let index = root + 1; index <= segments.length; index++) {
98
+ for (const filename2 of filenames) {
99
+ const filePath = pathe.join(...segments.slice(0, index), filename2);
100
+ if (options.test(filePath)) {
101
+ return filePath;
102
+ }
103
+ }
104
+ }
105
+ } else {
106
+ for (let index = segments.length; index > root; index--) {
107
+ for (const filename2 of filenames) {
108
+ const filePath = pathe.join(...segments.slice(0, index), filename2);
109
+ if (options.test(filePath)) {
110
+ return filePath;
111
+ }
112
+ }
113
+ }
59
114
  }
60
- return {
61
- filename,
62
- query: ret
63
- };
115
+ throw new Error(
116
+ `Cannot find matching ${filename} in ${options.startingFrom} or parent directories`
117
+ );
118
+ }
119
+ function findNearestFile(filename, _options = {}) {
120
+ return findFile(filename, _options);
121
+ }
122
+ function resolvePackageJSON(id = process.cwd(), options = {}) {
123
+ const resolvedPath = pathe.isAbsolute(id) ? id : mlly.resolvePathSync(id, options);
124
+ return findNearestFile("package.json", {
125
+ startingFrom: resolvedPath,
126
+ ...options
127
+ });
64
128
  }
65
129
 
66
130
  const _require = module__default.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
@@ -76,11 +140,11 @@ function checkInstallPackage(debug) {
76
140
  }
77
141
  function resolvePkgPath(id, debug) {
78
142
  try {
79
- const resolvedPath = _require.resolve(id);
80
- const pkgPath = path__default.dirname(resolvedPath);
81
- const pkgJson = JSON.parse(
82
- fs__default.readFileSync(path__default.join(pkgPath, "package.json"), "utf-8")
83
- );
143
+ const modPath = _require.resolve(id);
144
+ debug("modPath:", modPath, id);
145
+ const pkgJsonPath = resolvePackageJSON(modPath);
146
+ debug("pkgJsonPath:", pkgJsonPath);
147
+ const pkgJson = JSON.parse(fs__default.readFileSync(pkgJsonPath, "utf-8"));
84
148
  const pkgName = pkgJson.name.startsWith("vue-i18n") ? "vue-i18n" : pkgJson.name.startsWith("petite-vue-i18n") ? "petite-vue-i18n" : "";
85
149
  return pkgJson ? { alias: id, pkg: pkgName } : null;
86
150
  } catch (e) {
@@ -88,34 +152,14 @@ function resolvePkgPath(id, debug) {
88
152
  return null;
89
153
  }
90
154
  }
91
- function warn(...args) {
92
- console.warn(pc__default.yellow(pc__default.bold(`[unplugin-vue-i18n] `)), ...args);
93
- }
94
- function error(...args) {
95
- console.error(pc__default.red(pc__default.bold(`[unplugin-vue-i18n] `)), ...args);
96
- }
97
- async function getRaw(path2) {
98
- return fs.promises.readFile(path2, { encoding: "utf-8" });
99
- }
100
- function raiseError(message) {
101
- throw new Error(`[unplugin-vue-i18n] ${message}`);
102
- }
103
155
 
104
- const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
105
- const VIRTUAL_PREFIX = "\0";
106
- const debug = createDebug__default("unplugin-vue-i18n");
107
- const installedPkgInfo = checkInstallPackage(debug);
108
- const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
109
- debug("plugin options:", options, meta.framework);
110
- if (!["vite", "webpack"].includes(meta.framework)) {
111
- raiseError(`This plugin is supported 'vite' and 'webpack' only`);
112
- }
156
+ function resolveOptions(options, installedPkgInfo) {
113
157
  let onlyLocales = [];
114
158
  if (options.onlyLocales) {
115
- onlyLocales = Array.isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
159
+ onlyLocales = shared.isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
116
160
  }
117
161
  let include = options.include;
118
- let exclude = null;
162
+ let exclude = void 0;
119
163
  if (include) {
120
164
  if (shared.isArray(include)) {
121
165
  include = include.map((item) => pathe.normalize(item));
@@ -125,35 +169,137 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
125
169
  } else {
126
170
  exclude = "**/**";
127
171
  }
128
- const filter = pluginutils.createFilter(include, exclude);
129
172
  const forceStringify = !!options.forceStringify;
130
173
  const defaultSFCLang = shared.isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
131
174
  const globalSFCScope = !!options.globalSFCScope;
132
175
  const runtimeOnly = shared.isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
133
- debug("runtimeOnly", runtimeOnly);
134
176
  const dropMessageCompiler = !!options.dropMessageCompiler;
135
- debug("dropMessageCompiler", dropMessageCompiler);
136
177
  const compositionOnly = installedPkgInfo.pkg === "vue-i18n" ? shared.isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
137
- debug("compositionOnly", compositionOnly);
138
178
  const fullInstall = installedPkgInfo.pkg === "vue-i18n" ? shared.isBoolean(options.fullInstall) ? options.fullInstall : true : false;
139
- debug("fullInstall", fullInstall);
140
179
  const ssrBuild = !!options.ssr;
141
- debug("ssr", ssrBuild);
142
- const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
143
- return `${installedPkgInfo.alias}/dist/${installedPkgInfo.pkg}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
144
- };
145
180
  const allowDynamic = !!options.allowDynamic;
146
- debug("allowDynamic", allowDynamic);
147
181
  const strictMessage = shared.isBoolean(options.strictMessage) ? options.strictMessage : true;
148
- debug("strictMessage", strictMessage);
149
182
  const escapeHtml = !!options.escapeHtml;
150
- debug("escapeHtml", escapeHtml);
183
+ const optimizeTranslationDirective = shared.isString(options.optimizeTranslationDirective) || shared.isArray(options.optimizeTranslationDirective) ? options.optimizeTranslationDirective : !!options.optimizeTranslationDirective;
184
+ const translationIdentifiers = /* @__PURE__ */ new Map();
185
+ return {
186
+ include,
187
+ exclude,
188
+ onlyLocales,
189
+ forceStringify,
190
+ defaultSFCLang,
191
+ globalSFCScope,
192
+ runtimeOnly,
193
+ dropMessageCompiler,
194
+ compositionOnly,
195
+ fullInstall,
196
+ ssrBuild,
197
+ allowDynamic,
198
+ strictMessage,
199
+ escapeHtml,
200
+ optimizeTranslationDirective,
201
+ translationIdentifiers
202
+ };
203
+ }
204
+
205
+ function parseVueRequest(id) {
206
+ const [filename, rawQuery] = id.split(`?`, 2);
207
+ const params = new URLSearchParams(rawQuery);
208
+ const ret = {};
209
+ const langPart = Object.keys(Object.fromEntries(params)).find(
210
+ (key) => /lang\./i.test(key)
211
+ );
212
+ ret.vue = params.has("vue");
213
+ ret.global = params.has("global");
214
+ ret.src = params.has("src");
215
+ ret.raw = params.has("raw");
216
+ if (params.has("type")) {
217
+ ret.type = params.get("type");
218
+ }
219
+ if (params.has("blockType")) {
220
+ ret.blockType = params.get("blockType");
221
+ }
222
+ if (params.has("index")) {
223
+ ret.index = Number(params.get("index"));
224
+ }
225
+ if (params.has("locale")) {
226
+ ret.locale = params.get("locale");
227
+ }
228
+ if (langPart) {
229
+ const [, lang] = langPart.split(".");
230
+ ret.lang = lang;
231
+ } else if (params.has("lang")) {
232
+ ret.lang = params.get("lang");
233
+ }
234
+ if (params.has("issuerPath")) {
235
+ ret.issuerPath = params.get("issuerPath");
236
+ }
237
+ return {
238
+ filename,
239
+ query: ret
240
+ };
241
+ }
242
+
243
+ function getVueCompiler(vuePlugin) {
244
+ return vuePlugin?.api?.options.compiler;
245
+ }
246
+ function getVuePluginOptions(vuePlugin) {
247
+ return {
248
+ isProduction: vuePlugin?.api?.options.isProduction,
249
+ root: vuePlugin?.api?.options.root,
250
+ template: vuePlugin?.api?.options.template,
251
+ compiler: vuePlugin?.api?.options.compiler
252
+ };
253
+ }
254
+
255
+ function createDescriptor(filename, source, { template, compiler }) {
256
+ const { descriptor, errors } = compiler.parse(source, {
257
+ filename,
258
+ templateParseOptions: template?.compilerOptions
259
+ });
260
+ return { descriptor, errors };
261
+ }
262
+ function getDescriptor(filename, code, options) {
263
+ const { descriptor, errors } = createDescriptor(filename, code, options);
264
+ if (errors.length) {
265
+ throw errors[0];
266
+ }
267
+ return descriptor;
268
+ }
269
+
270
+ const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
271
+ const VIRTUAL_PREFIX = "\0";
272
+ const debug$2 = createDebug__default(resolveNamespace("resource"));
273
+ function resourcePlugin({
274
+ onlyLocales,
275
+ include,
276
+ exclude,
277
+ forceStringify,
278
+ defaultSFCLang,
279
+ globalSFCScope,
280
+ runtimeOnly,
281
+ dropMessageCompiler,
282
+ compositionOnly,
283
+ fullInstall,
284
+ ssrBuild,
285
+ strictMessage,
286
+ allowDynamic,
287
+ escapeHtml
288
+ }, meta, installedPkgInfo) {
289
+ const filter = pluginutils.createFilter(include, exclude);
290
+ const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
291
+ return `${installedPkgInfo.alias}/dist/${installedPkgInfo.pkg}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
292
+ };
151
293
  let isProduction = false;
152
294
  let sourceMap = false;
153
295
  const vueI18nAliasName = installedPkgInfo.alias;
154
- debug(`vue-i18n alias name: ${vueI18nAliasName}`);
296
+ debug$2(`vue-i18n alias name: ${vueI18nAliasName}`);
297
+ let vuePlugin = null;
298
+ const getSfcParser = () => {
299
+ return vuePlugin ? getVueCompiler(vuePlugin).parse : compilerSfc.parse;
300
+ };
155
301
  return {
156
- name: "unplugin-vue-i18n",
302
+ name: resolveNamespace("resource"),
157
303
  /**
158
304
  * NOTE:
159
305
  *
@@ -173,7 +319,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
173
319
  __VUE_I18N_PROD_DEVTOOLS__: false
174
320
  }
175
321
  };
176
- debug("define Config:", defineConfig);
322
+ debug$2("define Config:", defineConfig);
177
323
  const aliasConfig = {
178
324
  resolve: {
179
325
  alias: {
@@ -184,16 +330,20 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
184
330
  }
185
331
  }
186
332
  };
187
- debug("alias Config:", aliasConfig);
333
+ debug$2("alias Config:", aliasConfig);
188
334
  return shared.assign(defineConfig, aliasConfig);
189
335
  },
190
336
  configResolved(config) {
337
+ vuePlugin = getVitePlugin(config, "vite:vue");
338
+ if (!checkVuePlugin(vuePlugin)) {
339
+ return;
340
+ }
191
341
  isProduction = config.isProduction;
192
342
  sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
193
- debug(
343
+ debug$2(
194
344
  `configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
195
345
  );
196
- const jsonPlugin = config.plugins.find((p) => p.name === "vite:json");
346
+ const jsonPlugin = getVitePlugin(config, "vite:json");
197
347
  if (jsonPlugin) {
198
348
  const orgTransform = jsonPlugin.transform;
199
349
  jsonPlugin.transform = async function(code, id) {
@@ -204,13 +354,11 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
204
354
  if (query.vue) {
205
355
  return;
206
356
  }
207
- debug("org json plugin");
357
+ debug$2("org json plugin");
208
358
  return orgTransform.apply(this, [code, id]);
209
359
  };
210
360
  }
211
- const esbuildPlugin = config.plugins.find(
212
- (p) => p.name === "vite:esbuild"
213
- );
361
+ const esbuildPlugin = getVitePlugin(config, "vite:esbuild");
214
362
  if (esbuildPlugin) {
215
363
  const orgTransform = esbuildPlugin.transform;
216
364
  esbuildPlugin.transform = async function(code, id) {
@@ -243,10 +391,10 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
243
391
  forceStringify
244
392
  }
245
393
  );
246
- debug("parseOptions", parseOptions);
394
+ debug$2("parseOptions", parseOptions);
247
395
  const { code: generatedCode, map } = generate(_code, parseOptions);
248
- debug("generated code", generatedCode);
249
- debug("sourcemap", map, sourceMap);
396
+ debug$2("generated code", generatedCode);
397
+ debug$2("sourcemap", map, sourceMap);
250
398
  if (_code === generatedCode)
251
399
  return;
252
400
  return {
@@ -274,7 +422,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
274
422
  webpack(compiler) {
275
423
  isProduction = compiler.options.mode !== "development";
276
424
  sourceMap = !!compiler.options.devtool;
277
- debug(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
425
+ debug$2(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
278
426
  compiler.options.resolve = normalizeConfigResolveAlias(
279
427
  compiler.options.resolve,
280
428
  meta.framework
@@ -283,7 +431,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
283
431
  ssr: ssrBuild,
284
432
  runtimeOnly
285
433
  });
286
- debug(
434
+ debug$2(
287
435
  `set ${vueI18nAliasName}: ${getVueI18nAliasPath({
288
436
  ssr: ssrBuild,
289
437
  runtimeOnly
@@ -298,10 +446,10 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
298
446
  __INTLIFY_PROD_DEVTOOLS__: "false"
299
447
  })
300
448
  );
301
- debug(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
302
- debug(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
449
+ debug$2(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
450
+ debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
303
451
  } else {
304
- debug("ignore vue-i18n feature flags with webpack.DefinePlugin");
452
+ debug$2("ignore vue-i18n feature flags with webpack.DefinePlugin");
305
453
  }
306
454
  });
307
455
  if (compiler.options.module) {
@@ -315,15 +463,14 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
315
463
  }
316
464
  },
317
465
  resolveId(id, importer) {
318
- debug("resolveId", id, importer);
466
+ debug$2("resolveId", id, importer);
319
467
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
320
468
  return asVirtualId(id, meta.framework);
321
469
  }
322
470
  },
323
471
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
324
472
  async load(id) {
325
- debug("load", id);
326
- const { query } = parseVueRequest(id);
473
+ debug$2("load", id);
327
474
  if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
328
475
  let resourcePaths = [];
329
476
  const includePaths = shared.isArray(include) ? include : [include];
@@ -335,7 +482,6 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
335
482
  );
336
483
  const code = await generateBundleResources(
337
484
  resourcePaths,
338
- query,
339
485
  isProduction,
340
486
  {
341
487
  forceStringify,
@@ -350,7 +496,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
350
496
  }
351
497
  },
352
498
  transformInclude(id) {
353
- debug("transformInclude", id);
499
+ debug$2("transformInclude", id);
354
500
  if (meta.framework === "vite") {
355
501
  return true;
356
502
  } else {
@@ -360,7 +506,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
360
506
  },
361
507
  async transform(code, id) {
362
508
  const { filename, query } = parseVueRequest(id);
363
- debug("transform", id, JSON.stringify(query), filename);
509
+ debug$2("transform", id, JSON.stringify(query), filename);
364
510
  let langInfo = defaultSFCLang;
365
511
  let inSourceMap;
366
512
  if (!query.vue) {
@@ -383,10 +529,10 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
383
529
  forceStringify
384
530
  }
385
531
  );
386
- debug("parseOptions", parseOptions);
532
+ debug$2("parseOptions", parseOptions);
387
533
  const { code: generatedCode, map } = generate(code, parseOptions);
388
- debug("generated code", generatedCode);
389
- debug("sourcemap", map, sourceMap);
534
+ debug$2("generated code", generatedCode);
535
+ debug$2("sourcemap", map, sourceMap);
390
536
  if (code === generatedCode)
391
537
  return;
392
538
  return {
@@ -402,7 +548,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
402
548
  } else if (defaultSFCLang) {
403
549
  langInfo = defaultSFCLang;
404
550
  }
405
- debug("langInfo", langInfo);
551
+ debug$2("langInfo", langInfo);
406
552
  const generate = /\.?json5?/.test(langInfo) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
407
553
  const parseOptions = getOptions(
408
554
  filename,
@@ -419,17 +565,18 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
419
565
  forceStringify
420
566
  }
421
567
  );
422
- debug("parseOptions", parseOptions);
568
+ debug$2("parseOptions", parseOptions);
423
569
  const source = await getCode(
424
570
  code,
425
571
  filename,
426
572
  sourceMap,
427
573
  query,
574
+ getSfcParser(),
428
575
  meta.framework
429
576
  );
430
577
  const { code: generatedCode, map } = generate(source, parseOptions);
431
- debug("generated code", generatedCode);
432
- debug("sourcemap", map, sourceMap);
578
+ debug$2("generated code", generatedCode);
579
+ debug$2("sourcemap", map, sourceMap);
433
580
  if (code === generatedCode)
434
581
  return;
435
582
  return {
@@ -441,7 +588,7 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
441
588
  }
442
589
  }
443
590
  };
444
- });
591
+ }
445
592
  function getGenerator(ext, defaultGen = bundleUtils.generateJSON) {
446
593
  return /\.?json5?$/.test(ext) ? bundleUtils.generateJSON : /\.ya?ml$/.test(ext) ? bundleUtils.generateYAML : /\.([c|m]?js|[c|m]?ts)$/.test(ext) ? bundleUtils.generateJavaScript : defaultGen;
447
594
  }
@@ -474,7 +621,7 @@ async function loadWebpack() {
474
621
  }
475
622
  return webpack;
476
623
  }
477
- async function generateBundleResources(resources, query, isProduction, {
624
+ async function generateBundleResources(resources, isProduction, {
478
625
  forceStringify = false,
479
626
  isGlobal = false,
480
627
  onlyLocales = [],
@@ -484,7 +631,7 @@ async function generateBundleResources(resources, query, isProduction, {
484
631
  }) {
485
632
  const codes = [];
486
633
  for (const res of resources) {
487
- debug(`${res} bundle loading ...`);
634
+ debug$2(`${res} bundle loading ...`);
488
635
  if (/\.(json5?|ya?ml)$/.test(res)) {
489
636
  const { ext, name } = pathe.parse(res);
490
637
  const source = await getRaw(res);
@@ -499,7 +646,7 @@ async function generateBundleResources(resources, query, isProduction, {
499
646
  });
500
647
  parseOptions.type = "bare";
501
648
  const { code } = generate(source, parseOptions);
502
- debug("generated code", code);
649
+ debug$2("generated code", code);
503
650
  codes.push(`${JSON.stringify(name)}: ${code}`);
504
651
  }
505
652
  }
@@ -527,24 +674,24 @@ export default mergeDeep({},
527
674
  ${codes.map((code) => `{${code}}`).join(",\n")}
528
675
  );`;
529
676
  }
530
- async function getCode(source, filename, sourceMap, query, framework = "vite") {
677
+ async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
531
678
  const { index, issuerPath } = query;
532
679
  if (!shared.isNumber(index)) {
533
680
  raiseError(`unexpected index: ${index}`);
534
681
  }
535
682
  if (framework === "webpack") {
536
683
  if (issuerPath) {
537
- debug(`getCode (webpack) ${index} via issuerPath`, issuerPath);
684
+ debug$2(`getCode (webpack) ${index} via issuerPath`, issuerPath);
538
685
  return await getRaw(filename);
539
686
  } else {
540
- const result = compilerSfc.parse(await getRaw(filename), {
687
+ const result = parser(await getRaw(filename), {
541
688
  sourceMap,
542
689
  filename
543
690
  });
544
691
  const block = result.descriptor.customBlocks[index];
545
692
  if (block) {
546
693
  const code = block.src ? await getRaw(block.src) : block.content;
547
- debug(`getCode (webpack) ${index} from SFC`, code);
694
+ debug$2(`getCode (webpack) ${index} from SFC`, code);
548
695
  return code;
549
696
  } else {
550
697
  return source;
@@ -619,6 +766,299 @@ function getVirtualId(id, framework = "vite") {
619
766
  function asVirtualId(id, framework = "vite") {
620
767
  return framework === "vite" ? VIRTUAL_PREFIX + id : id;
621
768
  }
769
+ async function getRaw(path) {
770
+ return fs.promises.readFile(path, { encoding: "utf-8" });
771
+ }
772
+
773
+ const debug$1 = createDebug__default(resolveNamespace("directive"));
774
+ function directivePlugin({
775
+ optimizeTranslationDirective,
776
+ translationIdentifiers
777
+ }) {
778
+ let vuePlugin = null;
779
+ let vuePluginOptions = null;
780
+ return {
781
+ name: resolveNamespace("directive"),
782
+ enforce: "pre",
783
+ vite: {
784
+ config(config) {
785
+ vuePlugin = getVitePlugin(config, "vite:vue");
786
+ if (!checkVuePlugin(vuePlugin)) {
787
+ return;
788
+ }
789
+ if (optimizeTranslationDirective) {
790
+ vuePlugin.api.options = resolveVueOptions(
791
+ vuePlugin,
792
+ optimizeTranslationDirective,
793
+ translationIdentifiers
794
+ );
795
+ debug$1(`vite:vue options['template']:`, vuePlugin.api.options);
796
+ }
797
+ },
798
+ configResolved(config) {
799
+ vuePlugin = getVitePlugin(config, "vite:vue");
800
+ if (!checkVuePlugin(vuePlugin)) {
801
+ return;
802
+ }
803
+ }
804
+ },
805
+ async transform(code, id) {
806
+ const { filename } = parseVueRequest(id);
807
+ if (vuePluginOptions == null) {
808
+ vuePluginOptions = getVuePluginOptions(vuePlugin);
809
+ }
810
+ if (id.endsWith(".vue")) {
811
+ analyzeIdentifiers(
812
+ getDescriptor(filename, code, vuePluginOptions),
813
+ vuePluginOptions,
814
+ translationIdentifiers
815
+ );
816
+ }
817
+ return code;
818
+ }
819
+ };
820
+ }
821
+ function resolveVueOptions(vuePlugin, optimizeTranslationDirective, translationIdentifiers) {
822
+ var _a, _b;
823
+ const vueOptions = vuePlugin.api.options;
824
+ vueOptions.template || (vueOptions.template = {});
825
+ (_a = vueOptions.template).compilerOptions || (_a.compilerOptions = {});
826
+ (_b = vueOptions.template.compilerOptions).directiveTransforms || (_b.directiveTransforms = {});
827
+ const translationSignatureResolver = (context, baseResolver) => {
828
+ const { filename } = context;
829
+ const vuePluginOptions = getVuePluginOptions(vuePlugin);
830
+ const normalizedFilename = normalizePath(
831
+ path__default.relative(vuePluginOptions.root, filename)
832
+ );
833
+ const resolveIdentifier2 = translationIdentifiers.get(normalizedFilename);
834
+ debug$1("resolved vue-i18n Identifier", resolveIdentifier2);
835
+ if (resolveIdentifier2 == null) {
836
+ return void 0;
837
+ }
838
+ if (resolveIdentifier2.type === "identifier") {
839
+ return baseResolver(context, resolveIdentifier2.key);
840
+ } else {
841
+ const resolvedSignature = baseResolver(context, resolveIdentifier2.key);
842
+ return resolveIdentifier2?.style === "script-setup" ? `${resolvedSignature}.t` : resolvedSignature;
843
+ }
844
+ };
845
+ vueOptions.template.compilerOptions.directiveTransforms.t = vueI18nExtensions.transformVTDirective({
846
+ translationSignatures: shared.isBoolean(optimizeTranslationDirective) ? translationSignatureResolver : optimizeTranslationDirective
847
+ });
848
+ return vueOptions;
849
+ }
850
+ function analyzeIdentifiers(descriptor, { root }, translationIdentifiers) {
851
+ const source = descriptor.scriptSetup?.content || descriptor.script?.content;
852
+ debug$1("getDescriptor content", source);
853
+ if (!source) {
854
+ return;
855
+ }
856
+ const ast = typescriptEstree.parse(source, { range: true });
857
+ typescriptEstree.simpleTraverse(ast, {
858
+ enter(node, parent) {
859
+ if (parent) {
860
+ node.parent = parent;
861
+ }
862
+ }
863
+ });
864
+ const scopeManager$1 = scopeManager.analyze(ast, { sourceType: "module" });
865
+ const scope = getScope(scopeManager$1, ast);
866
+ const importLocalName = getImportLocalName(scope, "vue-i18n", "useI18n");
867
+ if (importLocalName == null) {
868
+ return;
869
+ }
870
+ debug$1("importLocalName", importLocalName);
871
+ const resolvedIdentifier = getVueI18nIdentifier(scope, importLocalName);
872
+ if (resolvedIdentifier) {
873
+ const normalizedFilename = normalizePath(
874
+ path__default.relative(root, descriptor.filename)
875
+ );
876
+ debug$1("set vue-i18n resolved identifier: ", resolvedIdentifier);
877
+ translationIdentifiers.set(normalizedFilename, resolvedIdentifier);
878
+ }
879
+ }
880
+ function getScope(manager, node) {
881
+ const scope = manager.acquire(node, true);
882
+ if (scope) {
883
+ if (scope.type === "function-expression-name") {
884
+ return scope.childScopes[0];
885
+ }
886
+ return scope;
887
+ }
888
+ return manager.scopes[0];
889
+ }
890
+ function getImportLocalName(scope, source, imported) {
891
+ const importDecl = getImportDeclaration(scope, source);
892
+ if (importDecl) {
893
+ const specifierNode = importDecl.specifiers.find(
894
+ (specifierNode2) => isImportedIdentifierInImportClause(specifierNode2) && specifierNode2.imported.name === imported
895
+ );
896
+ return specifierNode ? specifierNode.local.name : null;
897
+ }
898
+ return null;
899
+ }
900
+ function getImportDeclaration(scope, source) {
901
+ const tracker = new eslintUitls__default.ReferenceTracker(scope);
902
+ const traceMap = {
903
+ [source]: {
904
+ [eslintUitls__default.ReferenceTracker.ESM]: true,
905
+ [eslintUitls__default.ReferenceTracker.READ]: true
906
+ }
907
+ };
908
+ const refs = Array.from(tracker.iterateEsmReferences(traceMap));
909
+ return refs.length ? refs[0].node : null;
910
+ }
911
+ function isImportedIdentifierInImportClause(node) {
912
+ return "imported" in node;
913
+ }
914
+ function getVueI18nIdentifier(scope, local) {
915
+ const { callExpression, returnStatement } = getCallExpressionAndReturnStatement(scope, local);
916
+ if (callExpression == null) {
917
+ return null;
918
+ }
919
+ const id = getVariableDeclarationIdFrom(callExpression);
920
+ if (id == null) {
921
+ return null;
922
+ }
923
+ const variableIdPairs = parseVariableId(id);
924
+ debug$1("variableIdPairs:", variableIdPairs);
925
+ const returnVariableIdPairs = parseReturnStatement(returnStatement);
926
+ debug$1("returnVariableIdPairs:", returnVariableIdPairs);
927
+ return resolveIdentifier(variableIdPairs, returnVariableIdPairs);
928
+ }
929
+ const EMPTY_NODE_RETURN = {
930
+ callExpression: null,
931
+ returnStatement: null
932
+ };
933
+ function getCallExpressionAndReturnStatement(scope, local) {
934
+ const variable = eslintUitls__default.findVariable(scope, local);
935
+ if (variable == null) {
936
+ return EMPTY_NODE_RETURN;
937
+ }
938
+ const callExpressionRef = variable.references.find((ref) => {
939
+ return ref.identifier.parent?.type === typescriptEstree.AST_NODE_TYPES.CallExpression;
940
+ });
941
+ if (callExpressionRef == null) {
942
+ return EMPTY_NODE_RETURN;
943
+ }
944
+ let returnStatement = null;
945
+ 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") {
946
+ returnStatement = callExpressionRef.from.block.body.body.find(
947
+ (statement) => {
948
+ return statement.type === typescriptEstree.AST_NODE_TYPES.ReturnStatement;
949
+ }
950
+ );
951
+ }
952
+ return {
953
+ callExpression: callExpressionRef.identifier.parent,
954
+ returnStatement
955
+ };
956
+ }
957
+ function getVariableDeclarationIdFrom(node) {
958
+ if (node.parent?.type !== typescriptEstree.AST_NODE_TYPES.VariableDeclarator) {
959
+ return null;
960
+ }
961
+ return node.parent.id;
962
+ }
963
+ function parseVariableId(node) {
964
+ if (node.type === typescriptEstree.AST_NODE_TYPES.Identifier) {
965
+ return [{ key: node.name, value: null }];
966
+ } else {
967
+ const props = node.properties.filter(
968
+ // ignore RestElement
969
+ (prop) => prop.type === typescriptEstree.AST_NODE_TYPES.Property
970
+ );
971
+ const pairs = [];
972
+ for (const prop of props) {
973
+ if (prop?.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && prop?.value.type === typescriptEstree.AST_NODE_TYPES.Identifier) {
974
+ pairs.push({ key: prop.key.name, value: prop.value.name });
975
+ }
976
+ }
977
+ return pairs;
978
+ }
979
+ }
980
+ function parseReturnStatement(node) {
981
+ const pairs = [];
982
+ if (node == null || node.argument == null) {
983
+ return pairs;
984
+ }
985
+ if (node.argument.type === typescriptEstree.AST_NODE_TYPES.ObjectExpression) {
986
+ for (const prop of node.argument.properties) {
987
+ if (prop.type === typescriptEstree.AST_NODE_TYPES.Property) {
988
+ if (prop.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && prop.value.type === typescriptEstree.AST_NODE_TYPES.Identifier) {
989
+ pairs.push({ key: prop.key.name, value: prop.value.name });
990
+ } else if (prop.key.type === typescriptEstree.AST_NODE_TYPES.Identifier && prop.value.type === typescriptEstree.AST_NODE_TYPES.MemberExpression && prop.value.object.type === typescriptEstree.AST_NODE_TYPES.Identifier && prop.value.property.type === typescriptEstree.AST_NODE_TYPES.Identifier) {
991
+ pairs.push({
992
+ key: prop.key.name,
993
+ value: `${prop.value.object.name}.${prop.value.property.name}`
994
+ });
995
+ }
996
+ }
997
+ }
998
+ return pairs;
999
+ } else if (node.argument.type === typescriptEstree.AST_NODE_TYPES.Identifier) {
1000
+ return pairs;
1001
+ } else {
1002
+ return pairs;
1003
+ }
1004
+ }
1005
+ function resolveIdentifier(localVariables, returnVariable) {
1006
+ if (returnVariable.length === 0) {
1007
+ const variable = localVariables.find((pair) => pair.key === "t");
1008
+ if (variable && variable.value) {
1009
+ return { type: "identifier", key: variable.value };
1010
+ }
1011
+ const identifierOnly = localVariables.find((pair) => pair.value === null);
1012
+ if (identifierOnly && identifierOnly.key) {
1013
+ return { type: "object", key: identifierOnly.key, style: "script-setup" };
1014
+ }
1015
+ return null;
1016
+ } else {
1017
+ const variable = localVariables.find((pair) => pair.key === "t");
1018
+ if (variable && variable.value) {
1019
+ const returnVar = returnVariable.find(
1020
+ (pair) => pair.value === variable.value
1021
+ );
1022
+ if (returnVar && returnVar.key) {
1023
+ return { type: "identifier", key: returnVar.key };
1024
+ }
1025
+ }
1026
+ const identifierOnly = localVariables.find((pair) => pair.value === null);
1027
+ if (identifierOnly && identifierOnly.key) {
1028
+ const targetKey = identifierOnly.key;
1029
+ const returnVar = returnVariable.find(
1030
+ (pair) => pair.value?.startsWith(targetKey)
1031
+ );
1032
+ if (returnVar && returnVar.key) {
1033
+ return { type: "object", key: returnVar.key, style: "setup-hook" };
1034
+ }
1035
+ }
1036
+ return null;
1037
+ }
1038
+ }
1039
+
1040
+ const debug = createDebug__default(resolveNamespace("root"));
1041
+ const installedPkgInfo = checkInstallPackage(debug);
1042
+ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
1043
+ debug("meta framework", meta.framework);
1044
+ if (!["vite", "webpack"].includes(meta.framework)) {
1045
+ raiseError(`This plugin is supported 'vite' and 'webpack' only`);
1046
+ }
1047
+ debug("plugin options (resolving):", options);
1048
+ const resolvedOptions = resolveOptions(options, installedPkgInfo);
1049
+ debug("plugin options (resolved):", resolvedOptions);
1050
+ const plugins = [resourcePlugin(resolvedOptions, meta, installedPkgInfo)];
1051
+ if (resolvedOptions.optimizeTranslationDirective) {
1052
+ if (meta.framework === "webpack") {
1053
+ raiseError(
1054
+ `The 'optimizeTranslationDirective' option still is not supported for webpack.
1055
+ We are waiting for your Pull Request \u{1F642}.`
1056
+ );
1057
+ }
1058
+ plugins.push(directivePlugin(resolvedOptions));
1059
+ }
1060
+ return plugins;
1061
+ });
622
1062
 
623
1063
  exports.default = unplugin;
624
1064
  exports.unplugin = unplugin;