@intlify/unplugin-vue-i18n 0.4.0 → 0.6.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,94 @@
1
+
2
+ ## @intlify/unplugin-vue-i18n@0.6.0 (2022-09-19)
3
+
4
+ #### :bug: Bug Fixes
5
+ * [#180](https://github.com/intlify/bundle-tools/pull/180) fix(unplugin-vue-i18n): improve compilation error handling ([@kazupon](https://github.com/kazupon))
6
+
7
+ #### Committers: 1
8
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
9
+
10
+
11
+ ## @intlify/unplugin-vue-i18n@0.5.0 (2022-07-26)
12
+
13
+ #### :star: Features
14
+ * [#156](https://github.com/intlify/bundle-tools/pull/156) feat(unplugin-vue-i18n): support petite-vue-i18n and useVueI18nImportName option ([@kazupon](https://github.com/kazupon))
15
+
16
+ #### :zap: Improvement Features
17
+ * [#155](https://github.com/intlify/bundle-tools/pull/155) fix(unplugin-vue-i18n): improve wrong virtual module implementation ([@kazupon](https://github.com/kazupon))
18
+ * [#154](https://github.com/intlify/bundle-tools/pull/154) fix(unplugin-vue-i18n): support unplugin v0.8 ([@kazupon](https://github.com/kazupon))
19
+
20
+ #### Committers: 1
21
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
22
+
23
+
24
+ ## @intlify/unplugin-vue-i18n@0.4.0 (2022-07-07)
25
+
26
+ #### :star: Features
27
+ * [#138](https://github.com/intlify/bundle-tools/pull/138) feat(unplugin-vue-i18n): support esm options for bridge ([@kazupon](https://github.com/kazupon))
28
+
29
+ #### Committers: 1
30
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
31
+
32
+
33
+ ## @intlify/unplugin-vue-i18n@0.3.0 (2022-07-07)
34
+
35
+ #### :star: Features
36
+ * [#136](https://github.com/intlify/bundle-tools/pull/136) feat(unplugin-vue-i18n): support fullinstall option ([@kazupon](https://github.com/kazupon))
37
+ * [#135](https://github.com/intlify/bundle-tools/pull/135) feat(unplugin-vue-i18n): support composition only option ([@kazupon](https://github.com/kazupon))
38
+ * [#134](https://github.com/intlify/bundle-tools/pull/134) feat(unplugin-vue-i18n): support runtimeOnly option ([@kazupon](https://github.com/kazupon))
39
+
40
+ #### :pencil: Documentation
41
+ * [#133](https://github.com/intlify/bundle-tools/pull/133) docs: consistent plugin name and add Nuxt ([@Atinux](https://github.com/Atinux))
42
+
43
+ #### Committers: 2
44
+ - Sébastien Chopin ([@Atinux](https://github.com/Atinux))
45
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
46
+
47
+
48
+ ## @intlify/unplugin-vue-i18n@0.2.1 (2022-05-07)
49
+
50
+ #### :bug: Bug Fixes
51
+ * [#118](https://github.com/intlify/bundle-tools/pull/118) fix(unplugin-vue-i18n): code transforming strictly ([@kazupon](https://github.com/kazupon))
52
+
53
+ #### Committers: 1
54
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
55
+
56
+
57
+ ## @intlify/unplugin-vue-i18n@0.2.0 (2022-05-06)
58
+
59
+ #### :star: Features
60
+ * [#117](https://github.com/intlify/bundle-tools/pull/117) feat: support virtual resource importing ([@kazupon](https://github.com/kazupon))
61
+
62
+ #### Committers: 1
63
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
64
+
65
+
66
+ ## @intlify/unplugin-vue-i18n@0.1.2 (2022-05-06)
67
+
68
+ #### :bug: Bug Fixes
69
+ * [#115](https://github.com/intlify/bundle-tools/pull/115) fix(unplugin-vue-i18n): export d.ts files ([@kazupon](https://github.com/kazupon))
70
+
71
+ #### Committers: 1
72
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
73
+
74
+
75
+ ## @intlify/unplugin-vue-i18n@0.1.1 (2022-05-06)
76
+
77
+ #### :bug: Bug Fixes
78
+ * [#114](https://github.com/intlify/bundle-tools/pull/114) fix(unplugin-vue-i18n): export types ([@kazupon](https://github.com/kazupon))
79
+
80
+ #### Committers: 1
81
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
82
+
83
+
84
+ ## @intlify/unplugin-vue-i18n@0.1.0 (2022-05-06)
85
+
86
+ #### :star: Features
87
+ * [#113](https://github.com/intlify/bundle-tools/pull/113) feat: unplugin basic implementation for vue-i18n ([@kazupon](https://github.com/kazupon))
88
+
89
+ #### Committers: 1
90
+ - kazuya kawaguchi ([@kazupon](https://github.com/kazupon))
91
+
92
+ ## @intlify/unplugin-vue-i18n@0.0.0 (2022-05-02)
93
+
94
+ :tada: Initial release.
package/README.md CHANGED
@@ -237,6 +237,13 @@ This plugin will automatically select and bundle Vue I18n build according to the
237
237
 
238
238
  About details, See the [here](https://vue-i18n.intlify.dev/guide/advanced/optimization.html#improve-performance-and-reduce-bundle-size-with-runtime-build-only)
239
239
 
240
+ ### For `petite-vue-i18n`
241
+
242
+ This plugin will automatically select and bundle `petite-vue-i18n` build according to the following vite behavior:
243
+
244
+ - vite dev: `petite-vue-i18n.esm-bundler.js`
245
+ - vite build: `petite-vue-i18n.runtime.esm-bundler.js`
246
+
240
247
 
241
248
  ## 🔧 Options
242
249
 
@@ -428,9 +435,15 @@ About details, See the [here](https://vue-i18n.intlify.dev/guide/advanced/optimi
428
435
 
429
436
  This option that to use i18n custom blocks in `vue-class-component`.
430
437
 
438
+ ### `useVueI18nImportName` (Experimental)
439
+
440
+ - **Type:** `boolean`
441
+ - **Default:** `false`
442
+
443
+ Whether to use the import name of `petite-vue-i18n` with the same import name as vue-i18n (`import { xxx } from 'vue-i18n'`).
444
+
445
+ This option allows a smooth migration from `petite-vue-i18n` to `vue-i18n` and allows progressive enhacement.
431
446
 
432
- ## ✅ TODO
433
- - [ ] Bundling optimizations
434
447
 
435
448
  ## 📜 Changelog
436
449
 
package/lib/index.cjs CHANGED
@@ -13,6 +13,7 @@ const compilerSfc = require('@vue/compiler-sfc');
13
13
  const JSON5 = require('json5');
14
14
  const yaml = require('js-yaml');
15
15
  const fs = require('fs');
16
+ const pc = require('picocolors');
16
17
 
17
18
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
18
19
 
@@ -20,12 +21,15 @@ const createDebug__default = /*#__PURE__*/_interopDefaultLegacy(createDebug);
20
21
  const fg__default = /*#__PURE__*/_interopDefaultLegacy(fg);
21
22
  const JSON5__default = /*#__PURE__*/_interopDefaultLegacy(JSON5);
22
23
  const yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
24
+ const pc__default = /*#__PURE__*/_interopDefaultLegacy(pc);
23
25
 
24
26
  function parseVueRequest(id) {
25
27
  const [filename, rawQuery] = id.split(`?`, 2);
26
28
  const params = new URLSearchParams(rawQuery);
27
29
  const ret = {};
28
- const langPart = Object.keys(Object.fromEntries(params)).find((key) => /lang\./i.test(key));
30
+ const langPart = Object.keys(Object.fromEntries(params)).find(
31
+ (key) => /lang\./i.test(key)
32
+ );
29
33
  ret.vue = params.has("vue");
30
34
  ret.global = params.has("global");
31
35
  ret.src = params.has("src");
@@ -81,10 +85,10 @@ function convert(source, lang) {
81
85
  }
82
86
 
83
87
  function warn(...args) {
84
- console.warn(`[unplugin-vue-i18n] `, ...args);
88
+ console.warn(pc__default.yellow(pc__default.bold(`[unplugin-vue-i18n] `)), ...args);
85
89
  }
86
90
  function error(...args) {
87
- console.error(`[unplugin-vue-i18n] `, ...args);
91
+ console.error(pc__default.red(pc__default.bold(`[unplugin-vue-i18n] `)), ...args);
88
92
  }
89
93
  async function getRaw(path) {
90
94
  return fs.promises.readFile(path, { encoding: "utf-8" });
@@ -95,7 +99,9 @@ function raiseError(message) {
95
99
 
96
100
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
97
101
  const INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID = "@intlify/vite-plugin-vue-i18n/messages";
102
+ const VIRTUAL_PREFIX = "\0";
98
103
  const debug = createDebug__default("unplugin-vue-i18n");
104
+ const installedPkg = bundleUtils.checkInstallPackage("@intlify/unplugin-vue-i18n", debug);
99
105
  const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
100
106
  debug("plugin options:", options, meta.framework);
101
107
  if (!["vite", "webpack"].includes(meta.framework)) {
@@ -118,10 +124,16 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
118
124
  debug("bridge", bridge);
119
125
  const runtimeOnly = shared.isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
120
126
  debug("runtimeOnly", runtimeOnly);
121
- const compositionOnly = shared.isBoolean(options.compositionOnly) ? options.compositionOnly : true;
127
+ const compositionOnly = installedPkg === "vue-i18n" ? shared.isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
122
128
  debug("compositionOnly", compositionOnly);
123
- const fullInstall = shared.isBoolean(options.fullInstall) ? options.fullInstall : true;
129
+ const fullInstall = installedPkg === "vue-i18n" ? shared.isBoolean(options.fullInstall) ? options.fullInstall : true : false;
124
130
  debug("fullInstall", fullInstall);
131
+ const useVueI18nImportName = options.useVueI18nImportName;
132
+ if (useVueI18nImportName != null) {
133
+ warn(`'useVueI18nImportName' option is experimental`);
134
+ }
135
+ debug("useVueI18nImportName", useVueI18nImportName);
136
+ const getAliasName = () => installedPkg === "petite-vue-i18n" && shared.isBoolean(useVueI18nImportName) && useVueI18nImportName ? "vue-i18n" : `${installedPkg}`;
125
137
  const esm = shared.isBoolean(options.esm) ? options.esm : true;
126
138
  debug("esm", esm);
127
139
  let isProduction = false;
@@ -129,39 +141,51 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
129
141
  return {
130
142
  name: "unplugin-vue-i18n",
131
143
  enforce: meta.framework === "vite" ? "pre" : "post",
132
- transformInclude(id) {
133
- debug("transformInclude", id);
134
- if (meta.framework === "vite") {
135
- return true;
136
- } else {
137
- const { filename } = parseVueRequest(id);
138
- return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || filename.endsWith(INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) ? true : /\.(json5?|ya?ml)$/.test(id) && filter(id);
139
- }
140
- },
141
144
  vite: {
142
145
  config(config, { command }) {
143
146
  normalizeConfigResolveAlias(config.resolve, meta.framework);
144
147
  if (command === "build" && runtimeOnly) {
145
148
  if (shared.isArray(config.resolve.alias)) {
146
149
  config.resolve.alias.push({
147
- find: "vue-i18n",
148
- replacement: `vue-i18n/dist/vue-i18n.runtime.esm-bundler.js`
150
+ find: getAliasName(),
151
+ replacement: `${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`
149
152
  });
150
153
  } else if (shared.isObject(config.resolve.alias)) {
151
- config.resolve.alias["vue-i18n"] = `vue-i18n/dist/vue-i18n.runtime.esm-bundler.js`;
154
+ config.resolve.alias[getAliasName()] = `${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`;
152
155
  }
156
+ debug(`alias name: ${getAliasName()}`);
157
+ debug(
158
+ `set ${installedPkg} runtime only: ${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`
159
+ );
160
+ } else if (command === "serve" && installedPkg === "petite-vue-i18n" && useVueI18nImportName) {
161
+ normalizeConfigResolveAlias(config.resolve, meta.framework);
162
+ if (shared.isArray(config.resolve.alias)) {
163
+ config.resolve.alias.push({
164
+ find: "vue-i18n",
165
+ replacement: `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`
166
+ });
167
+ } else {
168
+ config.resolve.alias["vue-i18n"] = `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`;
169
+ }
170
+ debug(`alias name: ${getAliasName()}`);
153
171
  }
154
172
  config.define = config.define || {};
155
173
  config.define["__VUE_I18N_LEGACY_API__"] = !compositionOnly;
156
- debug(`set __VUE_I18N_LEGACY_API__ is '${config.define["__VUE_I18N_LEGACY_API__"]}'`);
174
+ debug(
175
+ `set __VUE_I18N_LEGACY_API__ is '${config.define["__VUE_I18N_LEGACY_API__"]}'`
176
+ );
157
177
  config.define["__VUE_I18N_FULL_INSTALL__"] = fullInstall;
158
- debug(`set __VUE_I18N_FULL_INSTALL__ is '${config.define["__VUE_I18N_FULL_INSTALL__"]}'`);
178
+ debug(
179
+ `set __VUE_I18N_FULL_INSTALL__ is '${config.define["__VUE_I18N_FULL_INSTALL__"]}'`
180
+ );
159
181
  config.define["__VUE_I18N_PROD_DEVTOOLS__"] = false;
160
182
  },
161
183
  configResolved(config) {
162
184
  isProduction = config.isProduction;
163
185
  sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
164
- debug(`configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
186
+ debug(
187
+ `configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
188
+ );
165
189
  const jsonPlugin = config.plugins.find((p) => p.name === "vite:json");
166
190
  if (jsonPlugin) {
167
191
  const orgTransform = jsonPlugin.transform;
@@ -189,11 +213,13 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
189
213
  }
190
214
  loadWebpack().then((webpack) => {
191
215
  if (webpack) {
192
- compiler.options.plugins.push(new webpack.DefinePlugin({
193
- __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
194
- __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
195
- __INTLIFY_PROD_DEVTOOLS__: "false"
196
- }));
216
+ compiler.options.plugins.push(
217
+ new webpack.DefinePlugin({
218
+ __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
219
+ __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
220
+ __INTLIFY_PROD_DEVTOOLS__: "false"
221
+ })
222
+ );
197
223
  debug(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
198
224
  debug(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
199
225
  } else {
@@ -211,35 +237,55 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
211
237
  resolveId(id, importer) {
212
238
  debug("resolveId", id, importer);
213
239
  if (id === INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) {
214
- warn(`deprected '${INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID}', you should switch to '${INTLIFY_BUNDLE_IMPORT_ID}'`);
215
- return id;
240
+ warn(
241
+ `deprected '${INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID}', you should switch to '${INTLIFY_BUNDLE_IMPORT_ID}'`
242
+ );
243
+ return asVirtualId(id, meta.framework);
216
244
  }
217
245
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
218
- return id;
246
+ return asVirtualId(id, meta.framework);
219
247
  }
220
248
  },
221
249
  async load(id) {
222
250
  debug("load", id);
223
251
  const { query } = parseVueRequest(id);
224
- if ([INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID, INTLIFY_BUNDLE_IMPORT_ID].includes(id) && include) {
252
+ if ([INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID, INTLIFY_BUNDLE_IMPORT_ID].includes(
253
+ getVirtualId(id, meta.framework)
254
+ ) && include) {
225
255
  let resourcePaths = [];
226
256
  const includePaths = shared.isArray(include) ? include : [include];
227
257
  for (const inc of includePaths) {
228
258
  resourcePaths = [...resourcePaths, ...await fg__default(inc)];
229
259
  }
230
- resourcePaths = resourcePaths.filter((el, pos) => resourcePaths.indexOf(el) === pos);
231
- const code = await generateBundleResources(resourcePaths, query, isProduction, {
232
- forceStringify,
233
- bridge,
234
- exportESM: esm,
235
- useClassComponent
236
- });
260
+ resourcePaths = resourcePaths.filter(
261
+ (el, pos) => resourcePaths.indexOf(el) === pos
262
+ );
263
+ const code = await generateBundleResources(
264
+ resourcePaths,
265
+ query,
266
+ isProduction,
267
+ {
268
+ forceStringify,
269
+ bridge,
270
+ exportESM: esm,
271
+ useClassComponent
272
+ }
273
+ );
237
274
  return {
238
275
  code,
239
276
  map: { mappings: "" }
240
277
  };
241
278
  }
242
279
  },
280
+ transformInclude(id) {
281
+ debug("transformInclude", id);
282
+ if (meta.framework === "vite") {
283
+ return true;
284
+ } else {
285
+ const { filename } = parseVueRequest(id);
286
+ return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || filename.endsWith(INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) || /\.(json5?|ya?ml)$/.test(filename) && filter(filename);
287
+ }
288
+ },
243
289
  async transform(code, id) {
244
290
  const { filename, query } = parseVueRequest(id);
245
291
  debug("transform", id, JSON.stringify(query), filename);
@@ -249,16 +295,26 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
249
295
  if (/\.(json5?|ya?ml)$/.test(id) && filter(id)) {
250
296
  langInfo = pathe.parse(filename).ext;
251
297
  const generate = /\.?json5?/.test(langInfo) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
252
- const parseOptions = getOptions(filename, isProduction, query, sourceMap, {
253
- inSourceMap,
254
- isGlobal: globalSFCScope,
255
- useClassComponent,
256
- bridge,
257
- exportESM: esm,
258
- forceStringify
259
- });
298
+ const parseOptions = getOptions(
299
+ filename,
300
+ isProduction,
301
+ query,
302
+ sourceMap,
303
+ {
304
+ inSourceMap,
305
+ isGlobal: globalSFCScope,
306
+ useClassComponent,
307
+ bridge,
308
+ exportESM: esm,
309
+ forceStringify
310
+ }
311
+ );
260
312
  debug("parseOptions", parseOptions);
261
- const { code: generatedCode, map } = generate(code, parseOptions, bridge ? createBridgeCodeGenerator(code, query) : void 0);
313
+ const { code: generatedCode, map } = generate(
314
+ code,
315
+ parseOptions,
316
+ bridge ? createBridgeCodeGenerator(code, query) : void 0
317
+ );
262
318
  debug("generated code", generatedCode);
263
319
  debug("sourcemap", map, sourceMap);
264
320
  if (code === generatedCode)
@@ -282,17 +338,33 @@ const unplugin = unplugin$1.createUnplugin((options = {}, meta) => {
282
338
  }
283
339
  debug("langInfo", langInfo);
284
340
  const generate = /\.?json5?/.test(langInfo) ? bundleUtils.generateJSON : bundleUtils.generateYAML;
285
- const parseOptions = getOptions(filename, isProduction, query, sourceMap, {
286
- inSourceMap,
287
- isGlobal: globalSFCScope,
288
- useClassComponent,
289
- bridge,
290
- exportESM: esm,
291
- forceStringify
292
- });
341
+ const parseOptions = getOptions(
342
+ filename,
343
+ isProduction,
344
+ query,
345
+ sourceMap,
346
+ {
347
+ inSourceMap,
348
+ isGlobal: globalSFCScope,
349
+ useClassComponent,
350
+ bridge,
351
+ exportESM: esm,
352
+ forceStringify
353
+ }
354
+ );
293
355
  debug("parseOptions", parseOptions);
294
- const source = await getCode(code, filename, sourceMap, query, meta.framework);
295
- const { code: generatedCode, map } = generate(source, parseOptions, bridge ? createBridgeCodeGenerator(source, query) : void 0);
356
+ const source = await getCode(
357
+ code,
358
+ filename,
359
+ sourceMap,
360
+ query,
361
+ meta.framework
362
+ );
363
+ const { code: generatedCode, map } = generate(
364
+ source,
365
+ parseOptions,
366
+ bridge ? createBridgeCodeGenerator(source, query) : void 0
367
+ );
296
368
  debug("generated code", generatedCode);
297
369
  debug("sourcemap", map, sourceMap);
298
370
  if (code === generatedCode)
@@ -329,7 +401,7 @@ async function loadWebpack() {
329
401
  try {
330
402
  webpack = await import('webpack').then((m) => m.default || m);
331
403
  } catch (e) {
332
- console.warn(`[@intlify/unplugin-vue-i18n] webpack not found, please install webpack.`);
404
+ warn(`webpack not found, please install webpack.`);
333
405
  }
334
406
  return webpack;
335
407
  }
@@ -355,7 +427,11 @@ async function generateBundleResources(resources, query, isProduction, {
355
427
  forceStringify
356
428
  });
357
429
  parseOptions.type = "bare";
358
- const { code } = generate(source, parseOptions, bridge ? createBridgeCodeGenerator(source, query) : void 0);
430
+ const { code } = generate(
431
+ source,
432
+ parseOptions,
433
+ bridge ? createBridgeCodeGenerator(source, query) : void 0
434
+ );
359
435
  debug("generated code", code);
360
436
  codes.push(`${JSON.stringify(name)}: ${code}`);
361
437
  }
@@ -416,8 +492,20 @@ function getOptions(filename, isProduction, query, sourceMap, {
416
492
  onWarn: (msg) => {
417
493
  warn(`${filename} ${msg}`);
418
494
  },
419
- onError: (msg) => {
420
- error(`${filename} ${msg}`);
495
+ onError: (msg, extra) => {
496
+ const codeFrame = shared.generateCodeFrame(
497
+ extra?.source || extra?.location?.source || "",
498
+ extra?.location?.start.column,
499
+ extra?.location?.end.column
500
+ );
501
+ const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
502
+ target message: ${extra?.source}
503
+ target message path: ${extra?.path}
504
+
505
+ ${codeFrame}
506
+ `;
507
+ error(errMssage);
508
+ throw new Error(errMssage);
421
509
  }
422
510
  };
423
511
  if (isCustomBlock(query)) {
@@ -433,6 +521,12 @@ function getOptions(filename, isProduction, query, sourceMap, {
433
521
  });
434
522
  }
435
523
  }
524
+ function getVirtualId(id, framework = "vite") {
525
+ return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
526
+ }
527
+ function asVirtualId(id, framework = "vite") {
528
+ return framework === "vite" ? VIRTUAL_PREFIX + id : id;
529
+ }
436
530
 
437
531
  exports["default"] = unplugin;
438
532
  exports.unplugin = unplugin;
package/lib/index.mjs CHANGED
@@ -2,19 +2,22 @@ import { createUnplugin } from 'unplugin';
2
2
  import { normalize, parse } from 'pathe';
3
3
  import createDebug from 'debug';
4
4
  import fg from 'fast-glob';
5
- import { isString, isArray, isBoolean, isObject, isEmptyObject, isNumber, assign } from '@intlify/shared';
5
+ import { isString, isArray, isBoolean, isObject, isNumber, isEmptyObject, assign, generateCodeFrame } from '@intlify/shared';
6
6
  import { createFilter } from '@rollup/pluginutils';
7
- import { generateJSON, generateYAML } from '@intlify/bundle-utils';
7
+ import { checkInstallPackage, generateJSON, generateYAML } from '@intlify/bundle-utils';
8
8
  import { parse as parse$1 } from '@vue/compiler-sfc';
9
9
  import JSON5 from 'json5';
10
10
  import yaml from 'js-yaml';
11
11
  import { promises } from 'fs';
12
+ import pc from 'picocolors';
12
13
 
13
14
  function parseVueRequest(id) {
14
15
  const [filename, rawQuery] = id.split(`?`, 2);
15
16
  const params = new URLSearchParams(rawQuery);
16
17
  const ret = {};
17
- const langPart = Object.keys(Object.fromEntries(params)).find((key) => /lang\./i.test(key));
18
+ const langPart = Object.keys(Object.fromEntries(params)).find(
19
+ (key) => /lang\./i.test(key)
20
+ );
18
21
  ret.vue = params.has("vue");
19
22
  ret.global = params.has("global");
20
23
  ret.src = params.has("src");
@@ -70,10 +73,10 @@ function convert(source, lang) {
70
73
  }
71
74
 
72
75
  function warn(...args) {
73
- console.warn(`[unplugin-vue-i18n] `, ...args);
76
+ console.warn(pc.yellow(pc.bold(`[unplugin-vue-i18n] `)), ...args);
74
77
  }
75
78
  function error(...args) {
76
- console.error(`[unplugin-vue-i18n] `, ...args);
79
+ console.error(pc.red(pc.bold(`[unplugin-vue-i18n] `)), ...args);
77
80
  }
78
81
  async function getRaw(path) {
79
82
  return promises.readFile(path, { encoding: "utf-8" });
@@ -84,7 +87,9 @@ function raiseError(message) {
84
87
 
85
88
  const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
86
89
  const INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID = "@intlify/vite-plugin-vue-i18n/messages";
90
+ const VIRTUAL_PREFIX = "\0";
87
91
  const debug = createDebug("unplugin-vue-i18n");
92
+ const installedPkg = checkInstallPackage("@intlify/unplugin-vue-i18n", debug);
88
93
  const unplugin = createUnplugin((options = {}, meta) => {
89
94
  debug("plugin options:", options, meta.framework);
90
95
  if (!["vite", "webpack"].includes(meta.framework)) {
@@ -107,10 +112,16 @@ const unplugin = createUnplugin((options = {}, meta) => {
107
112
  debug("bridge", bridge);
108
113
  const runtimeOnly = isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
109
114
  debug("runtimeOnly", runtimeOnly);
110
- const compositionOnly = isBoolean(options.compositionOnly) ? options.compositionOnly : true;
115
+ const compositionOnly = installedPkg === "vue-i18n" ? isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
111
116
  debug("compositionOnly", compositionOnly);
112
- const fullInstall = isBoolean(options.fullInstall) ? options.fullInstall : true;
117
+ const fullInstall = installedPkg === "vue-i18n" ? isBoolean(options.fullInstall) ? options.fullInstall : true : false;
113
118
  debug("fullInstall", fullInstall);
119
+ const useVueI18nImportName = options.useVueI18nImportName;
120
+ if (useVueI18nImportName != null) {
121
+ warn(`'useVueI18nImportName' option is experimental`);
122
+ }
123
+ debug("useVueI18nImportName", useVueI18nImportName);
124
+ const getAliasName = () => installedPkg === "petite-vue-i18n" && isBoolean(useVueI18nImportName) && useVueI18nImportName ? "vue-i18n" : `${installedPkg}`;
114
125
  const esm = isBoolean(options.esm) ? options.esm : true;
115
126
  debug("esm", esm);
116
127
  let isProduction = false;
@@ -118,39 +129,51 @@ const unplugin = createUnplugin((options = {}, meta) => {
118
129
  return {
119
130
  name: "unplugin-vue-i18n",
120
131
  enforce: meta.framework === "vite" ? "pre" : "post",
121
- transformInclude(id) {
122
- debug("transformInclude", id);
123
- if (meta.framework === "vite") {
124
- return true;
125
- } else {
126
- const { filename } = parseVueRequest(id);
127
- return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || filename.endsWith(INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) ? true : /\.(json5?|ya?ml)$/.test(id) && filter(id);
128
- }
129
- },
130
132
  vite: {
131
133
  config(config, { command }) {
132
134
  normalizeConfigResolveAlias(config.resolve, meta.framework);
133
135
  if (command === "build" && runtimeOnly) {
134
136
  if (isArray(config.resolve.alias)) {
135
137
  config.resolve.alias.push({
136
- find: "vue-i18n",
137
- replacement: `vue-i18n/dist/vue-i18n.runtime.esm-bundler.js`
138
+ find: getAliasName(),
139
+ replacement: `${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`
138
140
  });
139
141
  } else if (isObject(config.resolve.alias)) {
140
- config.resolve.alias["vue-i18n"] = `vue-i18n/dist/vue-i18n.runtime.esm-bundler.js`;
142
+ config.resolve.alias[getAliasName()] = `${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`;
141
143
  }
144
+ debug(`alias name: ${getAliasName()}`);
145
+ debug(
146
+ `set ${installedPkg} runtime only: ${installedPkg}/dist/${installedPkg}.runtime.esm-bundler.js`
147
+ );
148
+ } else if (command === "serve" && installedPkg === "petite-vue-i18n" && useVueI18nImportName) {
149
+ normalizeConfigResolveAlias(config.resolve, meta.framework);
150
+ if (isArray(config.resolve.alias)) {
151
+ config.resolve.alias.push({
152
+ find: "vue-i18n",
153
+ replacement: `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`
154
+ });
155
+ } else {
156
+ config.resolve.alias["vue-i18n"] = `petite-vue-i18n/dist/petite-vue-i18n.esm-bundler.js`;
157
+ }
158
+ debug(`alias name: ${getAliasName()}`);
142
159
  }
143
160
  config.define = config.define || {};
144
161
  config.define["__VUE_I18N_LEGACY_API__"] = !compositionOnly;
145
- debug(`set __VUE_I18N_LEGACY_API__ is '${config.define["__VUE_I18N_LEGACY_API__"]}'`);
162
+ debug(
163
+ `set __VUE_I18N_LEGACY_API__ is '${config.define["__VUE_I18N_LEGACY_API__"]}'`
164
+ );
146
165
  config.define["__VUE_I18N_FULL_INSTALL__"] = fullInstall;
147
- debug(`set __VUE_I18N_FULL_INSTALL__ is '${config.define["__VUE_I18N_FULL_INSTALL__"]}'`);
166
+ debug(
167
+ `set __VUE_I18N_FULL_INSTALL__ is '${config.define["__VUE_I18N_FULL_INSTALL__"]}'`
168
+ );
148
169
  config.define["__VUE_I18N_PROD_DEVTOOLS__"] = false;
149
170
  },
150
171
  configResolved(config) {
151
172
  isProduction = config.isProduction;
152
173
  sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
153
- debug(`configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
174
+ debug(
175
+ `configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
176
+ );
154
177
  const jsonPlugin = config.plugins.find((p) => p.name === "vite:json");
155
178
  if (jsonPlugin) {
156
179
  const orgTransform = jsonPlugin.transform;
@@ -178,11 +201,13 @@ const unplugin = createUnplugin((options = {}, meta) => {
178
201
  }
179
202
  loadWebpack().then((webpack) => {
180
203
  if (webpack) {
181
- compiler.options.plugins.push(new webpack.DefinePlugin({
182
- __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
183
- __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
184
- __INTLIFY_PROD_DEVTOOLS__: "false"
185
- }));
204
+ compiler.options.plugins.push(
205
+ new webpack.DefinePlugin({
206
+ __VUE_I18N_LEGACY_API__: JSON.stringify(compositionOnly),
207
+ __VUE_I18N_FULL_INSTALL__: JSON.stringify(fullInstall),
208
+ __INTLIFY_PROD_DEVTOOLS__: "false"
209
+ })
210
+ );
186
211
  debug(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
187
212
  debug(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
188
213
  } else {
@@ -200,35 +225,55 @@ const unplugin = createUnplugin((options = {}, meta) => {
200
225
  resolveId(id, importer) {
201
226
  debug("resolveId", id, importer);
202
227
  if (id === INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) {
203
- warn(`deprected '${INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID}', you should switch to '${INTLIFY_BUNDLE_IMPORT_ID}'`);
204
- return id;
228
+ warn(
229
+ `deprected '${INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID}', you should switch to '${INTLIFY_BUNDLE_IMPORT_ID}'`
230
+ );
231
+ return asVirtualId(id, meta.framework);
205
232
  }
206
233
  if (id === INTLIFY_BUNDLE_IMPORT_ID) {
207
- return id;
234
+ return asVirtualId(id, meta.framework);
208
235
  }
209
236
  },
210
237
  async load(id) {
211
238
  debug("load", id);
212
239
  const { query } = parseVueRequest(id);
213
- if ([INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID, INTLIFY_BUNDLE_IMPORT_ID].includes(id) && include) {
240
+ if ([INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID, INTLIFY_BUNDLE_IMPORT_ID].includes(
241
+ getVirtualId(id, meta.framework)
242
+ ) && include) {
214
243
  let resourcePaths = [];
215
244
  const includePaths = isArray(include) ? include : [include];
216
245
  for (const inc of includePaths) {
217
246
  resourcePaths = [...resourcePaths, ...await fg(inc)];
218
247
  }
219
- resourcePaths = resourcePaths.filter((el, pos) => resourcePaths.indexOf(el) === pos);
220
- const code = await generateBundleResources(resourcePaths, query, isProduction, {
221
- forceStringify,
222
- bridge,
223
- exportESM: esm,
224
- useClassComponent
225
- });
248
+ resourcePaths = resourcePaths.filter(
249
+ (el, pos) => resourcePaths.indexOf(el) === pos
250
+ );
251
+ const code = await generateBundleResources(
252
+ resourcePaths,
253
+ query,
254
+ isProduction,
255
+ {
256
+ forceStringify,
257
+ bridge,
258
+ exportESM: esm,
259
+ useClassComponent
260
+ }
261
+ );
226
262
  return {
227
263
  code,
228
264
  map: { mappings: "" }
229
265
  };
230
266
  }
231
267
  },
268
+ transformInclude(id) {
269
+ debug("transformInclude", id);
270
+ if (meta.framework === "vite") {
271
+ return true;
272
+ } else {
273
+ const { filename } = parseVueRequest(id);
274
+ return filename.endsWith("vue") || filename.endsWith(INTLIFY_BUNDLE_IMPORT_ID) || filename.endsWith(INTLIFY_BUNDLE_IMPORT_DEPRECTED_ID) || /\.(json5?|ya?ml)$/.test(filename) && filter(filename);
275
+ }
276
+ },
232
277
  async transform(code, id) {
233
278
  const { filename, query } = parseVueRequest(id);
234
279
  debug("transform", id, JSON.stringify(query), filename);
@@ -238,16 +283,26 @@ const unplugin = createUnplugin((options = {}, meta) => {
238
283
  if (/\.(json5?|ya?ml)$/.test(id) && filter(id)) {
239
284
  langInfo = parse(filename).ext;
240
285
  const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
241
- const parseOptions = getOptions(filename, isProduction, query, sourceMap, {
242
- inSourceMap,
243
- isGlobal: globalSFCScope,
244
- useClassComponent,
245
- bridge,
246
- exportESM: esm,
247
- forceStringify
248
- });
286
+ const parseOptions = getOptions(
287
+ filename,
288
+ isProduction,
289
+ query,
290
+ sourceMap,
291
+ {
292
+ inSourceMap,
293
+ isGlobal: globalSFCScope,
294
+ useClassComponent,
295
+ bridge,
296
+ exportESM: esm,
297
+ forceStringify
298
+ }
299
+ );
249
300
  debug("parseOptions", parseOptions);
250
- const { code: generatedCode, map } = generate(code, parseOptions, bridge ? createBridgeCodeGenerator(code, query) : void 0);
301
+ const { code: generatedCode, map } = generate(
302
+ code,
303
+ parseOptions,
304
+ bridge ? createBridgeCodeGenerator(code, query) : void 0
305
+ );
251
306
  debug("generated code", generatedCode);
252
307
  debug("sourcemap", map, sourceMap);
253
308
  if (code === generatedCode)
@@ -271,17 +326,33 @@ const unplugin = createUnplugin((options = {}, meta) => {
271
326
  }
272
327
  debug("langInfo", langInfo);
273
328
  const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
274
- const parseOptions = getOptions(filename, isProduction, query, sourceMap, {
275
- inSourceMap,
276
- isGlobal: globalSFCScope,
277
- useClassComponent,
278
- bridge,
279
- exportESM: esm,
280
- forceStringify
281
- });
329
+ const parseOptions = getOptions(
330
+ filename,
331
+ isProduction,
332
+ query,
333
+ sourceMap,
334
+ {
335
+ inSourceMap,
336
+ isGlobal: globalSFCScope,
337
+ useClassComponent,
338
+ bridge,
339
+ exportESM: esm,
340
+ forceStringify
341
+ }
342
+ );
282
343
  debug("parseOptions", parseOptions);
283
- const source = await getCode(code, filename, sourceMap, query, meta.framework);
284
- const { code: generatedCode, map } = generate(source, parseOptions, bridge ? createBridgeCodeGenerator(source, query) : void 0);
344
+ const source = await getCode(
345
+ code,
346
+ filename,
347
+ sourceMap,
348
+ query,
349
+ meta.framework
350
+ );
351
+ const { code: generatedCode, map } = generate(
352
+ source,
353
+ parseOptions,
354
+ bridge ? createBridgeCodeGenerator(source, query) : void 0
355
+ );
285
356
  debug("generated code", generatedCode);
286
357
  debug("sourcemap", map, sourceMap);
287
358
  if (code === generatedCode)
@@ -318,7 +389,7 @@ async function loadWebpack() {
318
389
  try {
319
390
  webpack = await import('webpack').then((m) => m.default || m);
320
391
  } catch (e) {
321
- console.warn(`[@intlify/unplugin-vue-i18n] webpack not found, please install webpack.`);
392
+ warn(`webpack not found, please install webpack.`);
322
393
  }
323
394
  return webpack;
324
395
  }
@@ -344,7 +415,11 @@ async function generateBundleResources(resources, query, isProduction, {
344
415
  forceStringify
345
416
  });
346
417
  parseOptions.type = "bare";
347
- const { code } = generate(source, parseOptions, bridge ? createBridgeCodeGenerator(source, query) : void 0);
418
+ const { code } = generate(
419
+ source,
420
+ parseOptions,
421
+ bridge ? createBridgeCodeGenerator(source, query) : void 0
422
+ );
348
423
  debug("generated code", code);
349
424
  codes.push(`${JSON.stringify(name)}: ${code}`);
350
425
  }
@@ -405,8 +480,20 @@ function getOptions(filename, isProduction, query, sourceMap, {
405
480
  onWarn: (msg) => {
406
481
  warn(`${filename} ${msg}`);
407
482
  },
408
- onError: (msg) => {
409
- error(`${filename} ${msg}`);
483
+ onError: (msg, extra) => {
484
+ const codeFrame = generateCodeFrame(
485
+ extra?.source || extra?.location?.source || "",
486
+ extra?.location?.start.column,
487
+ extra?.location?.end.column
488
+ );
489
+ const errMssage = `${msg} (error code: ${extra?.code}) in ${filename}
490
+ target message: ${extra?.source}
491
+ target message path: ${extra?.path}
492
+
493
+ ${codeFrame}
494
+ `;
495
+ error(errMssage);
496
+ throw new Error(errMssage);
410
497
  }
411
498
  };
412
499
  if (isCustomBlock(query)) {
@@ -422,5 +509,11 @@ function getOptions(filename, isProduction, query, sourceMap, {
422
509
  });
423
510
  }
424
511
  }
512
+ function getVirtualId(id, framework = "vite") {
513
+ return framework === "vite" ? id.startsWith(VIRTUAL_PREFIX) ? id.slice(VIRTUAL_PREFIX.length) : "" : id;
514
+ }
515
+ function asVirtualId(id, framework = "vite") {
516
+ return framework === "vite" ? VIRTUAL_PREFIX + id : id;
517
+ }
425
518
 
426
519
  export { unplugin as default, unplugin };
package/lib/types.d.ts CHANGED
@@ -10,6 +10,7 @@ interface PluginOptions {
10
10
  globalSFCScope?: boolean;
11
11
  bridge?: boolean;
12
12
  useClassComponent?: boolean;
13
+ useVueI18nImportName?: boolean;
13
14
  }
14
15
 
15
16
  export { PluginOptions, SFCLangFormat };
package/lib/vite.cjs CHANGED
@@ -12,6 +12,7 @@ require('@vue/compiler-sfc');
12
12
  require('json5');
13
13
  require('js-yaml');
14
14
  require('fs');
15
+ require('picocolors');
15
16
 
16
17
  const vite = index.unplugin.vite;
17
18
 
package/lib/vite.mjs CHANGED
@@ -10,6 +10,7 @@ import '@vue/compiler-sfc';
10
10
  import 'json5';
11
11
  import 'js-yaml';
12
12
  import 'fs';
13
+ import 'picocolors';
13
14
 
14
15
  const vite = unplugin.vite;
15
16
 
package/lib/webpack.cjs CHANGED
@@ -12,6 +12,7 @@ require('@vue/compiler-sfc');
12
12
  require('json5');
13
13
  require('js-yaml');
14
14
  require('fs');
15
+ require('picocolors');
15
16
 
16
17
  const webpack = index.unplugin.webpack;
17
18
 
package/lib/webpack.mjs CHANGED
@@ -10,6 +10,7 @@ import '@vue/compiler-sfc';
10
10
  import 'json5';
11
11
  import 'js-yaml';
12
12
  import 'fs';
13
+ import 'picocolors';
13
14
 
14
15
  const webpack = unplugin.webpack;
15
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlify/unplugin-vue-i18n",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "unplugin for Vue I18n",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
@@ -22,7 +22,7 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
- "@intlify/bundle-utils": "next",
25
+ "@intlify/bundle-utils": "^3.1.2",
26
26
  "@intlify/shared": "next",
27
27
  "@rollup/pluginutils": "^4.2.0",
28
28
  "@vue/compiler-sfc": "^3.2.23",
@@ -31,15 +31,16 @@
31
31
  "js-yaml": "^4.1.0",
32
32
  "json5": "^2.2.0",
33
33
  "pathe": "^0.2.0",
34
+ "picocolors": "^1.0.0",
34
35
  "source-map": "0.6.1",
35
- "unplugin": "^0.6.2"
36
+ "unplugin": "^0.8.0"
36
37
  },
37
38
  "devDependencies": {
38
39
  "mlly": "^0.5.2",
39
- "unbuild": "^0.7.4"
40
+ "unbuild": "^0.8.11"
40
41
  },
41
42
  "engines": {
42
- "node": ">= 12"
43
+ "node": ">= 14.16"
43
44
  },
44
45
  "files": [
45
46
  "lib",