@intlify/vue-i18n-extensions 6.0.3 → 6.0.4

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.
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createContentBuilder = void 0;
4
+ const shared_1 = require("@intlify/shared");
5
+ /**
6
+ * Create a Content Builder
7
+ *
8
+ * @param options - Content Builder options
9
+ *
10
+ * @returns A {@link ContentBuilder} instance
11
+ *
12
+ * @public
13
+ */
14
+ function createContentBuilder(options = {}) {
15
+ let _indentLevel = options.indentLevel != null && (0, shared_1.isNumber)(options.indentLevel) ? options.indentLevel : 0;
16
+ let _content = '';
17
+ function push(content) {
18
+ _content += content;
19
+ }
20
+ function _newline(n) {
21
+ push('\n' + ` `.repeat(n));
22
+ }
23
+ function newline() {
24
+ _newline(_indentLevel);
25
+ }
26
+ function pushline(content) {
27
+ push(content);
28
+ newline();
29
+ }
30
+ function indent(withoutNewLine) {
31
+ if (withoutNewLine) {
32
+ ++_indentLevel;
33
+ }
34
+ else {
35
+ _newline(++_indentLevel);
36
+ }
37
+ }
38
+ function deindent(withoutNewLine) {
39
+ if (withoutNewLine) {
40
+ --_indentLevel;
41
+ }
42
+ else {
43
+ _newline(--_indentLevel);
44
+ }
45
+ }
46
+ return {
47
+ get indentLevel() {
48
+ return _indentLevel;
49
+ },
50
+ get content() {
51
+ return String(_content);
52
+ },
53
+ push,
54
+ newline,
55
+ pushline,
56
+ indent,
57
+ deindent
58
+ };
59
+ }
60
+ exports.createContentBuilder = createContentBuilder;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformVTDirective = void 0;
4
+ var transform_1 = require("./transform");
5
+ Object.defineProperty(exports, "transformVTDirective", { enumerable: true, get: function () { return transform_1.transformVTDirective; } });
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.report = exports.getReportMessage = void 0;
4
+ const shared_1 = require("@intlify/shared");
5
+ // TODO: should be extracted as i18n resources (intlify project self hosting!)
6
+ const ReportMessages = {
7
+ [1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */]: `Unexpected directive expression: {0}`,
8
+ [2 /* ReportCodes.NOT_SUPPORTED */]: `Not supported transform: {0}`,
9
+ [3 /* ReportCodes.FAILED_VALUE_EVALUATION */]: `Failed value evaluation: {0}`,
10
+ [4 /* ReportCodes.REQUIRED_PARAMETER */]: `Required parameter: {0}`,
11
+ [5 /* ReportCodes.INVALID_PARAMETER_TYPE */]: `Required parameter: {0}`,
12
+ [6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */]: `v-t will override element children: {0}`,
13
+ [7 /* ReportCodes.NOT_RESOLVED_COMPOSER */]: `Not resolved vue-i18n composer: {0}`,
14
+ [8 /* ReportCodes.UNEXPECTED_ERROR */]: `Unexpected error: {0}`
15
+ };
16
+ function getReportMessage(code, ...args) {
17
+ return (0, shared_1.format)(ReportMessages[code], ...args);
18
+ }
19
+ exports.getReportMessage = getReportMessage;
20
+ function createExtensionsError(code, msg, loc) {
21
+ const error = new SyntaxError(msg);
22
+ error.code = code;
23
+ if (loc) {
24
+ error.loc = loc;
25
+ }
26
+ return error;
27
+ }
28
+ function report(code, options = {}) {
29
+ const mode = options.mode && (0, shared_1.isString)(options.mode) && ['warn', 'error'].includes(options.mode)
30
+ ? options.mode
31
+ : 'warn';
32
+ const msg = getReportMessage(code, options.args);
33
+ if (mode === 'warn') {
34
+ console.warn('[vue-i18n-extensions] ' + msg);
35
+ }
36
+ else {
37
+ // error
38
+ throw createExtensionsError(code, msg, options.loc);
39
+ }
40
+ }
41
+ exports.report = report;
@@ -0,0 +1,363 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformVTDirective = void 0;
4
+ const compiler_dom_1 = require("@vue/compiler-dom");
5
+ const shared_1 = require("@intlify/shared");
6
+ const transpiler_1 = require("./transpiler");
7
+ const report_1 = require("./report");
8
+ const builder_1 = require("./builder");
9
+ /**
10
+ * Transform `v-t` custom directive
11
+ *
12
+ * @remarks
13
+ * Transform that `v-t` custom directive is optimized vue-i18n code by Vue compiler.
14
+ * This transform can improve the performance by pre-translating, and it does support SSR.
15
+ *
16
+ * @param options - `v-t` custom directive transform options, see {@link TransformVTDirectiveOptions}
17
+ * @returns Directive transform
18
+ *
19
+ * @example
20
+ * ```js
21
+ * import { compile } from '@vue/compiler-dom'
22
+ * import { createI18n } from 'vue-i18n'
23
+ * import { transformVTDirective } from '@intlify/vue-i18n-extensions'
24
+ *
25
+ * // create i18n instance
26
+ * const i18n = createI18n({
27
+ * locale: 'ja',
28
+ * messages: {
29
+ * en: {
30
+ * hello: 'hello'
31
+ * },
32
+ * ja: {
33
+ * hello: 'こんにちは'
34
+ * }
35
+ * }
36
+ * })
37
+ *
38
+ * // get transform from `transformVTDirective` function, with `i18n` option
39
+ * const transformVT = transformVTDirective({ i18n })
40
+ *
41
+ * const { code } = compile(`<p v-t="'hello'"></p>`, {
42
+ * mode: 'function',
43
+ * hoistStatic: true,
44
+ * prefixIdentifiers: true,
45
+ * directiveTransforms: { t: transformVT } // <- you need to specify to `directiveTransforms` option!
46
+ * })
47
+ *
48
+ * console.log(code)
49
+ * // output ->
50
+ * // const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
51
+ * // return function render(_ctx, _cache) {
52
+ * // return (_openBlock(), _createBlock(\\"div\\", null, \\"こんにちは!\\"))
53
+ * // }
54
+ * ```
55
+ * @public
56
+ */
57
+ function transformVTDirective(options = {}) {
58
+ const i18nInstance = options.i18n;
59
+ const mode = (0, shared_1.isString)(options.mode) && ['composition', 'legacy'].includes(options.mode)
60
+ ? options.mode
61
+ : 'composition';
62
+ // prettier-ignore
63
+ const translationSignatures = (0, shared_1.isString)(options.translationSignatures)
64
+ ? [options.translationSignatures]
65
+ : (0, shared_1.isArray)(options.translationSignatures)
66
+ ? options.translationSignatures
67
+ : ['t'];
68
+ translationSignatures.push(`$t`); // fallback to global scope
69
+ return (dir, node, context) => {
70
+ const { exp, loc } = dir;
71
+ // console.log('v-t dir', dir)
72
+ // console.log('v-t node', node)
73
+ if (!exp) {
74
+ // TODO: throw error with context.OnError
75
+ // NOTE: We need to support from @vue/compiler-core
76
+ // https://github.com/vuejs/vue-next/issues/1147
77
+ (0, report_1.report)(1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */, {
78
+ mode: 'error',
79
+ args: [node.loc.source || ''],
80
+ loc: node.loc
81
+ });
82
+ }
83
+ if (node.children.length > 0) {
84
+ // TODO: throw error with context.OnError
85
+ // NOTE: We need to support from @vue/compiler-core
86
+ // https://github.com/vuejs/vue-next/issues/1147
87
+ (0, report_1.report)(6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */, {
88
+ mode: 'error',
89
+ args: [node.loc.source || ''],
90
+ loc: node.loc
91
+ });
92
+ node.children.length = 0;
93
+ }
94
+ if (isSimpleExpressionNode(exp)) {
95
+ if (isConstant(exp) && i18nInstance) {
96
+ const { status, value } = (0, transpiler_1.evaluateValue)(exp.content);
97
+ if (status === 'ng') {
98
+ (0, report_1.report)(3 /* ReportCodes.FAILED_VALUE_EVALUATION */, {
99
+ args: [node.loc.source || ''],
100
+ loc: node.loc
101
+ });
102
+ return { props: [] };
103
+ }
104
+ const [parsedValue, parseStatus] = parseValue(value);
105
+ if (parseStatus !== 0 /* ReportCodes.SUCCESS */) {
106
+ (0, report_1.report)(parseStatus, { args: [node.loc.source || ''], loc: node.loc });
107
+ return { props: [] };
108
+ }
109
+ if (parsedValue == null) {
110
+ (0, report_1.report)(8 /* ReportCodes.UNEXPECTED_ERROR */, {
111
+ args: [node.loc.source || ''],
112
+ loc: node.loc
113
+ });
114
+ return { props: [] };
115
+ }
116
+ const global = getComposer(i18nInstance);
117
+ if (global == null) {
118
+ (0, report_1.report)(7 /* ReportCodes.NOT_RESOLVED_COMPOSER */, {
119
+ args: [node.loc.source || ''],
120
+ loc: node.loc
121
+ });
122
+ return { props: [] };
123
+ }
124
+ const content = global.t(...makeParams(parsedValue));
125
+ node.children.push({
126
+ type: compiler_dom_1.NodeTypes.TEXT,
127
+ content
128
+ });
129
+ return { props: [] };
130
+ }
131
+ else {
132
+ const translationParams = (0, transpiler_1.parseVTExpression)(exp.content);
133
+ const code = generateTranslationCode(context, mode, translationParams, translationSignatures);
134
+ context.helper(compiler_dom_1.TO_DISPLAY_STRING);
135
+ node.children.push({
136
+ type: compiler_dom_1.NodeTypes.INTERPOLATION,
137
+ content: (0, compiler_dom_1.createCompoundExpression)([
138
+ (0, compiler_dom_1.createSimpleExpression)(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
139
+ ])
140
+ });
141
+ return { props: [] };
142
+ }
143
+ }
144
+ else if (isCompoundExpressionNode(exp)) {
145
+ const content = exp.children.map(mapNodeContentHandler).join('');
146
+ const code = generateTranslationCode(context, mode, (0, transpiler_1.parseVTExpression)(content), translationSignatures);
147
+ context.helper(compiler_dom_1.TO_DISPLAY_STRING);
148
+ node.children.push({
149
+ type: compiler_dom_1.NodeTypes.INTERPOLATION,
150
+ content: (0, compiler_dom_1.createCompoundExpression)([
151
+ (0, compiler_dom_1.createSimpleExpression)(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
152
+ ])
153
+ });
154
+ return { props: [] };
155
+ }
156
+ else {
157
+ (0, report_1.report)(2 /* ReportCodes.NOT_SUPPORTED */, {
158
+ args: [node.loc.source || ''],
159
+ loc: node.loc
160
+ });
161
+ return { props: [] };
162
+ }
163
+ };
164
+ }
165
+ exports.transformVTDirective = transformVTDirective;
166
+ function getComposer(i18n) {
167
+ return isI18nInstance(i18n) ? getComposerInternal(i18n) : null;
168
+ }
169
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
+ function isI18nInstance(i18n) {
171
+ return i18n != null && 'global' in i18n && 'mode' in i18n;
172
+ }
173
+ function getComposerInternal(i18n) {
174
+ if (i18n.mode === 'composition') {
175
+ return isComposer(i18n.global) ? i18n.global : null;
176
+ }
177
+ else {
178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
179
+ return isVueI18n(i18n.global) ? i18n.global.__composer : null;
180
+ }
181
+ }
182
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
+ function isComposer(target) {
184
+ return target != null && !('__composer' in target);
185
+ }
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ function isVueI18n(target) {
188
+ return target != null && '__composer' in target;
189
+ }
190
+ function isSimpleExpressionNode(node) {
191
+ return node != null && node.type === compiler_dom_1.NodeTypes.SIMPLE_EXPRESSION;
192
+ }
193
+ function isCompoundExpressionNode(node) {
194
+ return node != null && node.type === compiler_dom_1.NodeTypes.COMPOUND_EXPRESSION;
195
+ }
196
+ function isConstant(node) {
197
+ if ('isConstant' in node) {
198
+ // for v3.0.3 earlier
199
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
200
+ return node.isConstant;
201
+ }
202
+ else if ('constType' in node) {
203
+ // for v3.0.3 or later
204
+ return node.constType <= 3 /* ConstantTypes.CAN_STRINGIFY */;
205
+ }
206
+ else {
207
+ throw Error('unexpected error in Vue SimpleExpressionNode');
208
+ }
209
+ }
210
+ function mapNodeContentHandler(value) {
211
+ if ((0, shared_1.isString)(value)) {
212
+ return value;
213
+ }
214
+ else if ((0, shared_1.isSymbol)(value)) {
215
+ return value.description || '';
216
+ }
217
+ else if (isSimpleExpressionNode(value)) {
218
+ return value.content;
219
+ }
220
+ else if (isCompoundExpressionNode(value)) {
221
+ return value.children.map(mapNodeContentHandler).join('');
222
+ }
223
+ else if ((0, compiler_dom_1.isText)(value)) {
224
+ if ((0, shared_1.isString)(value.content)) {
225
+ return value.content;
226
+ }
227
+ else if (isSimpleExpressionNode(value.content)) {
228
+ return value.content.content;
229
+ }
230
+ else if (isCompoundExpressionNode(value.content)) {
231
+ return value.content.children.map(mapNodeContentHandler).join('');
232
+ }
233
+ else {
234
+ return '';
235
+ }
236
+ }
237
+ else {
238
+ return '';
239
+ }
240
+ }
241
+ function parseValue(value) {
242
+ if ((0, shared_1.isString)(value)) {
243
+ return [{ path: value }, 0 /* ReportCodes.SUCCESS */];
244
+ }
245
+ else if ((0, shared_1.isObject)(value)) {
246
+ if (!('path' in value)) {
247
+ return [null, 4 /* ReportCodes.REQUIRED_PARAMETER */];
248
+ }
249
+ return [value, 0 /* ReportCodes.SUCCESS */];
250
+ }
251
+ else {
252
+ return [null, 5 /* ReportCodes.INVALID_PARAMETER_TYPE */];
253
+ }
254
+ }
255
+ function makeParams(value) {
256
+ const { path, locale, args, choice, plural } = value;
257
+ const options = {};
258
+ const named = args || {};
259
+ if ((0, shared_1.isString)(locale)) {
260
+ options.locale = locale;
261
+ }
262
+ if ((0, shared_1.isNumber)(choice)) {
263
+ options.plural = choice;
264
+ }
265
+ if ((0, shared_1.isNumber)(plural)) {
266
+ options.plural = plural;
267
+ }
268
+ return [path, named, options];
269
+ }
270
+ function generateTranslationCode(context, mode, params, translationSignatures) {
271
+ return mode === 'composition'
272
+ ? generateComposableCode(context, params, translationSignatures)
273
+ : generateLegacyCode(context, params);
274
+ }
275
+ function generateTranslationCallableSignatures(context, translationSignatures) {
276
+ const { prefixIdentifiers, bindingMetadata } = context;
277
+ return translationSignatures
278
+ .map(signature => {
279
+ const type = (0, shared_1.hasOwn)(bindingMetadata, signature) && bindingMetadata[signature];
280
+ const bindingContext = prefixIdentifiers
281
+ ? (type && type.startsWith('setup')) || type === compiler_dom_1.BindingTypes.LITERAL_CONST
282
+ ? '$setup.'
283
+ : '_ctx.'
284
+ : '';
285
+ return `${bindingContext}${signature}`;
286
+ })
287
+ .join(' || ');
288
+ }
289
+ function generateComposableCode(context, params, translationSignatures) {
290
+ const baseCode = `(${generateTranslationCallableSignatures(context, translationSignatures)})`;
291
+ const builder = (0, builder_1.createContentBuilder)();
292
+ builder.push(`${baseCode}(`);
293
+ // generate path
294
+ builder.push(`${(0, shared_1.toDisplayString)(params.path)}`);
295
+ // generate named
296
+ builder.push(`, { `);
297
+ generateNamedCode(builder, params.named);
298
+ builder.push(` }`);
299
+ // generate options
300
+ builder.push(`, { `);
301
+ if (params.options.locale) {
302
+ builder.push(`locale: ${(0, shared_1.toDisplayString)(params.options.locale)}`);
303
+ }
304
+ if (params.options.plural) {
305
+ if (params.options.locale) {
306
+ builder.push(', ');
307
+ }
308
+ builder.push(`plural: ${(0, shared_1.toDisplayString)(params.options.plural)}`);
309
+ }
310
+ builder.push(` }`);
311
+ builder.push(`)`);
312
+ const content = builder.content;
313
+ return content;
314
+ }
315
+ function generateNamedCode(builder, named) {
316
+ const keys = Object.keys(named);
317
+ keys.forEach(k => {
318
+ const v = named[k];
319
+ if ((0, shared_1.isObject)(v)) {
320
+ builder.push(`${k}: { `);
321
+ generateNamedCode(builder, v);
322
+ builder.push(` }`);
323
+ }
324
+ else {
325
+ builder.push(`${k}: ${(0, shared_1.toDisplayString)(v)}`);
326
+ }
327
+ });
328
+ }
329
+ function generateLegacyCode(context, params) {
330
+ const mode = !params.options.plural ? 'basic' : 'plural';
331
+ const baseCode = `${context.prefixIdentifiers ? '_ctx.' : ''}${mode === 'basic' ? '$t' : '$tc'}`;
332
+ const builder = (0, builder_1.createContentBuilder)();
333
+ builder.push(`${baseCode}(`);
334
+ // generate path
335
+ builder.push(`${(0, shared_1.toDisplayString)(params.path)}`);
336
+ if (mode === 'basic') {
337
+ // generate locale
338
+ if ((0, shared_1.isString)(params.options.locale)) {
339
+ builder.push(`, ${(0, shared_1.toDisplayString)(params.options.locale)}`);
340
+ }
341
+ // generate named
342
+ builder.push(`, { `);
343
+ generateNamedCode(builder, params.named);
344
+ builder.push(` }`);
345
+ }
346
+ else {
347
+ // generate plural
348
+ builder.push(`, ${(0, shared_1.toDisplayString)(params.options.plural)}`);
349
+ if ((0, shared_1.isString)(params.options.locale)) {
350
+ // generate locale
351
+ builder.push(`, ${(0, shared_1.toDisplayString)(params.options.locale)}`);
352
+ }
353
+ else {
354
+ // generate named
355
+ builder.push(`, { `);
356
+ generateNamedCode(builder, params.named);
357
+ builder.push(` }`);
358
+ }
359
+ }
360
+ builder.push(`)`);
361
+ const content = builder.content;
362
+ return content;
363
+ }
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseVTExpression = exports.evaluateValue = void 0;
4
+ const parser_1 = require("@babel/parser");
5
+ function evaluateValue(expression) {
6
+ const ret = { status: 'ng', value: undefined };
7
+ try {
8
+ const ast = (0, parser_1.parse)(`const a = ${expression.trim()}`);
9
+ if (ast.program.body.length >= 1 &&
10
+ ast.program.body[0].type === 'VariableDeclaration' &&
11
+ ast.program.body[0].declarations.length >= 1) {
12
+ const node = ast.program.body[0].declarations[0].init;
13
+ if (node != null && (node.type === 'StringLiteral' || node.type === 'ObjectExpression')) {
14
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
15
+ const val = new Function(`return ${expression.trim()} `)();
16
+ ret.status = 'ok';
17
+ ret.value = val;
18
+ }
19
+ }
20
+ // eslint-disable-next-line no-empty
21
+ }
22
+ catch (_e) { }
23
+ return ret;
24
+ }
25
+ exports.evaluateValue = evaluateValue;
26
+ function parseVTExpression(expression) {
27
+ const ret = {
28
+ path: '',
29
+ named: {},
30
+ options: {}
31
+ };
32
+ try {
33
+ const ast = (0, parser_1.parse)(`const a = ${expression.trim()}`);
34
+ if (ast.program.body.length >= 1 &&
35
+ ast.program.body[0].type === 'VariableDeclaration' &&
36
+ ast.program.body[0].declarations.length >= 1) {
37
+ const node = ast.program.body[0].declarations[0].init;
38
+ if (node != null) {
39
+ if (node.type === 'StringLiteral' && node.extra) {
40
+ ret.path = node.extra.raw;
41
+ }
42
+ else if (node.type === 'Identifier') {
43
+ ret.path = node.name;
44
+ }
45
+ else if (node.type === 'MemberExpression') {
46
+ ret.path = getObjectMemberValue(node);
47
+ }
48
+ else if (node.type === 'ObjectExpression') {
49
+ node.properties.forEach(propNode => {
50
+ if (propNode.type === 'ObjectProperty') {
51
+ const propKeyNode = propNode.key;
52
+ if (propKeyNode.type !== 'Identifier') {
53
+ return;
54
+ }
55
+ const propValueNode = propNode.value;
56
+ switch (propKeyNode.name) {
57
+ case 'path':
58
+ ret.path = getObjectMemberValue(propValueNode);
59
+ break;
60
+ case 'locale':
61
+ ret.options.locale = getObjectMemberValue(propValueNode);
62
+ break;
63
+ case 'choice':
64
+ case 'plural':
65
+ ret.options.plural = getObjectMemberValue(propValueNode);
66
+ break;
67
+ case 'args':
68
+ // console.log('args', propValueNode)
69
+ if (propValueNode.type === 'ObjectExpression') {
70
+ traverseObjectMember(propValueNode, ret.named);
71
+ }
72
+ break;
73
+ default:
74
+ break;
75
+ }
76
+ }
77
+ });
78
+ }
79
+ }
80
+ }
81
+ // eslint-disable-next-line no-empty
82
+ }
83
+ catch (_e) { }
84
+ return ret;
85
+ }
86
+ exports.parseVTExpression = parseVTExpression;
87
+ function getObjectMemberValue(node) {
88
+ if ((node.type === 'StringLiteral' || node.type === 'NumericLiteral') && node.extra) {
89
+ return node.extra.raw;
90
+ }
91
+ else if (node.type === 'Identifier') {
92
+ return node.name;
93
+ }
94
+ else if (node.type === 'MemberExpression') {
95
+ const paths = [];
96
+ collectMemberPath(node, paths);
97
+ paths.reverse();
98
+ return paths.join('.');
99
+ }
100
+ else {
101
+ return '';
102
+ }
103
+ }
104
+ function traverseObjectMember(node, target) {
105
+ node.properties.forEach(propNode => {
106
+ if (propNode.type === 'ObjectProperty') {
107
+ const propKeyNode = propNode.key;
108
+ if (propKeyNode.type !== 'Identifier') {
109
+ return;
110
+ }
111
+ if (!(propKeyNode.name in target)) {
112
+ target[propKeyNode.name] = {};
113
+ }
114
+ // console.log('propNode', propNode)
115
+ const propValueNode = propNode.value;
116
+ if (propValueNode.type === 'ObjectExpression') {
117
+ traverseObjectMember(propValueNode, target[propKeyNode.name]);
118
+ }
119
+ else {
120
+ target[propKeyNode.name] = getObjectMemberValue(propValueNode);
121
+ }
122
+ }
123
+ });
124
+ }
125
+ function collectMemberPath(node, paths) {
126
+ if (node.type === 'Identifier') {
127
+ paths.push(node.name);
128
+ return;
129
+ }
130
+ else if (node.type === 'MemberExpression' && node.property.type === 'Identifier') {
131
+ paths.push(node.property.name);
132
+ return collectMemberPath(node.object, paths);
133
+ }
134
+ }
@@ -0,0 +1,56 @@
1
+ import { isNumber } from '@intlify/shared';
2
+ /**
3
+ * Create a Content Builder
4
+ *
5
+ * @param options - Content Builder options
6
+ *
7
+ * @returns A {@link ContentBuilder} instance
8
+ *
9
+ * @public
10
+ */
11
+ export function createContentBuilder(options = {}) {
12
+ let _indentLevel = options.indentLevel != null && isNumber(options.indentLevel) ? options.indentLevel : 0;
13
+ let _content = '';
14
+ function push(content) {
15
+ _content += content;
16
+ }
17
+ function _newline(n) {
18
+ push('\n' + ` `.repeat(n));
19
+ }
20
+ function newline() {
21
+ _newline(_indentLevel);
22
+ }
23
+ function pushline(content) {
24
+ push(content);
25
+ newline();
26
+ }
27
+ function indent(withoutNewLine) {
28
+ if (withoutNewLine) {
29
+ ++_indentLevel;
30
+ }
31
+ else {
32
+ _newline(++_indentLevel);
33
+ }
34
+ }
35
+ function deindent(withoutNewLine) {
36
+ if (withoutNewLine) {
37
+ --_indentLevel;
38
+ }
39
+ else {
40
+ _newline(--_indentLevel);
41
+ }
42
+ }
43
+ return {
44
+ get indentLevel() {
45
+ return _indentLevel;
46
+ },
47
+ get content() {
48
+ return String(_content);
49
+ },
50
+ push,
51
+ newline,
52
+ pushline,
53
+ indent,
54
+ deindent
55
+ };
56
+ }
@@ -0,0 +1 @@
1
+ export { transformVTDirective } from './transform';
@@ -0,0 +1,36 @@
1
+ import { format, isString } from '@intlify/shared';
2
+ // TODO: should be extracted as i18n resources (intlify project self hosting!)
3
+ const ReportMessages = {
4
+ [1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */]: `Unexpected directive expression: {0}`,
5
+ [2 /* ReportCodes.NOT_SUPPORTED */]: `Not supported transform: {0}`,
6
+ [3 /* ReportCodes.FAILED_VALUE_EVALUATION */]: `Failed value evaluation: {0}`,
7
+ [4 /* ReportCodes.REQUIRED_PARAMETER */]: `Required parameter: {0}`,
8
+ [5 /* ReportCodes.INVALID_PARAMETER_TYPE */]: `Required parameter: {0}`,
9
+ [6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */]: `v-t will override element children: {0}`,
10
+ [7 /* ReportCodes.NOT_RESOLVED_COMPOSER */]: `Not resolved vue-i18n composer: {0}`,
11
+ [8 /* ReportCodes.UNEXPECTED_ERROR */]: `Unexpected error: {0}`
12
+ };
13
+ export function getReportMessage(code, ...args) {
14
+ return format(ReportMessages[code], ...args);
15
+ }
16
+ function createExtensionsError(code, msg, loc) {
17
+ const error = new SyntaxError(msg);
18
+ error.code = code;
19
+ if (loc) {
20
+ error.loc = loc;
21
+ }
22
+ return error;
23
+ }
24
+ export function report(code, options = {}) {
25
+ const mode = options.mode && isString(options.mode) && ['warn', 'error'].includes(options.mode)
26
+ ? options.mode
27
+ : 'warn';
28
+ const msg = getReportMessage(code, options.args);
29
+ if (mode === 'warn') {
30
+ console.warn('[vue-i18n-extensions] ' + msg);
31
+ }
32
+ else {
33
+ // error
34
+ throw createExtensionsError(code, msg, options.loc);
35
+ }
36
+ }
@@ -0,0 +1,359 @@
1
+ import { createSimpleExpression, NodeTypes, isText, BindingTypes, createCompoundExpression, TO_DISPLAY_STRING } from '@vue/compiler-dom';
2
+ import { isNumber, isObject, isString, isSymbol, toDisplayString, hasOwn, isArray } from '@intlify/shared';
3
+ import { evaluateValue, parseVTExpression } from './transpiler';
4
+ import { report } from './report';
5
+ import { createContentBuilder } from './builder';
6
+ /**
7
+ * Transform `v-t` custom directive
8
+ *
9
+ * @remarks
10
+ * Transform that `v-t` custom directive is optimized vue-i18n code by Vue compiler.
11
+ * This transform can improve the performance by pre-translating, and it does support SSR.
12
+ *
13
+ * @param options - `v-t` custom directive transform options, see {@link TransformVTDirectiveOptions}
14
+ * @returns Directive transform
15
+ *
16
+ * @example
17
+ * ```js
18
+ * import { compile } from '@vue/compiler-dom'
19
+ * import { createI18n } from 'vue-i18n'
20
+ * import { transformVTDirective } from '@intlify/vue-i18n-extensions'
21
+ *
22
+ * // create i18n instance
23
+ * const i18n = createI18n({
24
+ * locale: 'ja',
25
+ * messages: {
26
+ * en: {
27
+ * hello: 'hello'
28
+ * },
29
+ * ja: {
30
+ * hello: 'こんにちは'
31
+ * }
32
+ * }
33
+ * })
34
+ *
35
+ * // get transform from `transformVTDirective` function, with `i18n` option
36
+ * const transformVT = transformVTDirective({ i18n })
37
+ *
38
+ * const { code } = compile(`<p v-t="'hello'"></p>`, {
39
+ * mode: 'function',
40
+ * hoistStatic: true,
41
+ * prefixIdentifiers: true,
42
+ * directiveTransforms: { t: transformVT } // <- you need to specify to `directiveTransforms` option!
43
+ * })
44
+ *
45
+ * console.log(code)
46
+ * // output ->
47
+ * // const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
48
+ * // return function render(_ctx, _cache) {
49
+ * // return (_openBlock(), _createBlock(\\"div\\", null, \\"こんにちは!\\"))
50
+ * // }
51
+ * ```
52
+ * @public
53
+ */
54
+ export function transformVTDirective(options = {}) {
55
+ const i18nInstance = options.i18n;
56
+ const mode = isString(options.mode) && ['composition', 'legacy'].includes(options.mode)
57
+ ? options.mode
58
+ : 'composition';
59
+ // prettier-ignore
60
+ const translationSignatures = isString(options.translationSignatures)
61
+ ? [options.translationSignatures]
62
+ : isArray(options.translationSignatures)
63
+ ? options.translationSignatures
64
+ : ['t'];
65
+ translationSignatures.push(`$t`); // fallback to global scope
66
+ return (dir, node, context) => {
67
+ const { exp, loc } = dir;
68
+ // console.log('v-t dir', dir)
69
+ // console.log('v-t node', node)
70
+ if (!exp) {
71
+ // TODO: throw error with context.OnError
72
+ // NOTE: We need to support from @vue/compiler-core
73
+ // https://github.com/vuejs/vue-next/issues/1147
74
+ report(1 /* ReportCodes.UNEXPECTED_DIRECTIVE_EXPRESSION */, {
75
+ mode: 'error',
76
+ args: [node.loc.source || ''],
77
+ loc: node.loc
78
+ });
79
+ }
80
+ if (node.children.length > 0) {
81
+ // TODO: throw error with context.OnError
82
+ // NOTE: We need to support from @vue/compiler-core
83
+ // https://github.com/vuejs/vue-next/issues/1147
84
+ report(6 /* ReportCodes.OVERRIDE_ELEMENT_CHILDREN */, {
85
+ mode: 'error',
86
+ args: [node.loc.source || ''],
87
+ loc: node.loc
88
+ });
89
+ node.children.length = 0;
90
+ }
91
+ if (isSimpleExpressionNode(exp)) {
92
+ if (isConstant(exp) && i18nInstance) {
93
+ const { status, value } = evaluateValue(exp.content);
94
+ if (status === 'ng') {
95
+ report(3 /* ReportCodes.FAILED_VALUE_EVALUATION */, {
96
+ args: [node.loc.source || ''],
97
+ loc: node.loc
98
+ });
99
+ return { props: [] };
100
+ }
101
+ const [parsedValue, parseStatus] = parseValue(value);
102
+ if (parseStatus !== 0 /* ReportCodes.SUCCESS */) {
103
+ report(parseStatus, { args: [node.loc.source || ''], loc: node.loc });
104
+ return { props: [] };
105
+ }
106
+ if (parsedValue == null) {
107
+ report(8 /* ReportCodes.UNEXPECTED_ERROR */, {
108
+ args: [node.loc.source || ''],
109
+ loc: node.loc
110
+ });
111
+ return { props: [] };
112
+ }
113
+ const global = getComposer(i18nInstance);
114
+ if (global == null) {
115
+ report(7 /* ReportCodes.NOT_RESOLVED_COMPOSER */, {
116
+ args: [node.loc.source || ''],
117
+ loc: node.loc
118
+ });
119
+ return { props: [] };
120
+ }
121
+ const content = global.t(...makeParams(parsedValue));
122
+ node.children.push({
123
+ type: NodeTypes.TEXT,
124
+ content
125
+ });
126
+ return { props: [] };
127
+ }
128
+ else {
129
+ const translationParams = parseVTExpression(exp.content);
130
+ const code = generateTranslationCode(context, mode, translationParams, translationSignatures);
131
+ context.helper(TO_DISPLAY_STRING);
132
+ node.children.push({
133
+ type: NodeTypes.INTERPOLATION,
134
+ content: createCompoundExpression([
135
+ createSimpleExpression(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
136
+ ])
137
+ });
138
+ return { props: [] };
139
+ }
140
+ }
141
+ else if (isCompoundExpressionNode(exp)) {
142
+ const content = exp.children.map(mapNodeContentHandler).join('');
143
+ const code = generateTranslationCode(context, mode, parseVTExpression(content), translationSignatures);
144
+ context.helper(TO_DISPLAY_STRING);
145
+ node.children.push({
146
+ type: NodeTypes.INTERPOLATION,
147
+ content: createCompoundExpression([
148
+ createSimpleExpression(code, false, loc, 0 /* ConstantTypes.NOT_CONSTANT */)
149
+ ])
150
+ });
151
+ return { props: [] };
152
+ }
153
+ else {
154
+ report(2 /* ReportCodes.NOT_SUPPORTED */, {
155
+ args: [node.loc.source || ''],
156
+ loc: node.loc
157
+ });
158
+ return { props: [] };
159
+ }
160
+ };
161
+ }
162
+ function getComposer(i18n) {
163
+ return isI18nInstance(i18n) ? getComposerInternal(i18n) : null;
164
+ }
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ function isI18nInstance(i18n) {
167
+ return i18n != null && 'global' in i18n && 'mode' in i18n;
168
+ }
169
+ function getComposerInternal(i18n) {
170
+ if (i18n.mode === 'composition') {
171
+ return isComposer(i18n.global) ? i18n.global : null;
172
+ }
173
+ else {
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
175
+ return isVueI18n(i18n.global) ? i18n.global.__composer : null;
176
+ }
177
+ }
178
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
+ function isComposer(target) {
180
+ return target != null && !('__composer' in target);
181
+ }
182
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
+ function isVueI18n(target) {
184
+ return target != null && '__composer' in target;
185
+ }
186
+ function isSimpleExpressionNode(node) {
187
+ return node != null && node.type === NodeTypes.SIMPLE_EXPRESSION;
188
+ }
189
+ function isCompoundExpressionNode(node) {
190
+ return node != null && node.type === NodeTypes.COMPOUND_EXPRESSION;
191
+ }
192
+ function isConstant(node) {
193
+ if ('isConstant' in node) {
194
+ // for v3.0.3 earlier
195
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
196
+ return node.isConstant;
197
+ }
198
+ else if ('constType' in node) {
199
+ // for v3.0.3 or later
200
+ return node.constType <= 3 /* ConstantTypes.CAN_STRINGIFY */;
201
+ }
202
+ else {
203
+ throw Error('unexpected error in Vue SimpleExpressionNode');
204
+ }
205
+ }
206
+ function mapNodeContentHandler(value) {
207
+ if (isString(value)) {
208
+ return value;
209
+ }
210
+ else if (isSymbol(value)) {
211
+ return value.description || '';
212
+ }
213
+ else if (isSimpleExpressionNode(value)) {
214
+ return value.content;
215
+ }
216
+ else if (isCompoundExpressionNode(value)) {
217
+ return value.children.map(mapNodeContentHandler).join('');
218
+ }
219
+ else if (isText(value)) {
220
+ if (isString(value.content)) {
221
+ return value.content;
222
+ }
223
+ else if (isSimpleExpressionNode(value.content)) {
224
+ return value.content.content;
225
+ }
226
+ else if (isCompoundExpressionNode(value.content)) {
227
+ return value.content.children.map(mapNodeContentHandler).join('');
228
+ }
229
+ else {
230
+ return '';
231
+ }
232
+ }
233
+ else {
234
+ return '';
235
+ }
236
+ }
237
+ function parseValue(value) {
238
+ if (isString(value)) {
239
+ return [{ path: value }, 0 /* ReportCodes.SUCCESS */];
240
+ }
241
+ else if (isObject(value)) {
242
+ if (!('path' in value)) {
243
+ return [null, 4 /* ReportCodes.REQUIRED_PARAMETER */];
244
+ }
245
+ return [value, 0 /* ReportCodes.SUCCESS */];
246
+ }
247
+ else {
248
+ return [null, 5 /* ReportCodes.INVALID_PARAMETER_TYPE */];
249
+ }
250
+ }
251
+ function makeParams(value) {
252
+ const { path, locale, args, choice, plural } = value;
253
+ const options = {};
254
+ const named = args || {};
255
+ if (isString(locale)) {
256
+ options.locale = locale;
257
+ }
258
+ if (isNumber(choice)) {
259
+ options.plural = choice;
260
+ }
261
+ if (isNumber(plural)) {
262
+ options.plural = plural;
263
+ }
264
+ return [path, named, options];
265
+ }
266
+ function generateTranslationCode(context, mode, params, translationSignatures) {
267
+ return mode === 'composition'
268
+ ? generateComposableCode(context, params, translationSignatures)
269
+ : generateLegacyCode(context, params);
270
+ }
271
+ function generateTranslationCallableSignatures(context, translationSignatures) {
272
+ const { prefixIdentifiers, bindingMetadata } = context;
273
+ return translationSignatures
274
+ .map(signature => {
275
+ const type = hasOwn(bindingMetadata, signature) && bindingMetadata[signature];
276
+ const bindingContext = prefixIdentifiers
277
+ ? (type && type.startsWith('setup')) || type === BindingTypes.LITERAL_CONST
278
+ ? '$setup.'
279
+ : '_ctx.'
280
+ : '';
281
+ return `${bindingContext}${signature}`;
282
+ })
283
+ .join(' || ');
284
+ }
285
+ function generateComposableCode(context, params, translationSignatures) {
286
+ const baseCode = `(${generateTranslationCallableSignatures(context, translationSignatures)})`;
287
+ const builder = createContentBuilder();
288
+ builder.push(`${baseCode}(`);
289
+ // generate path
290
+ builder.push(`${toDisplayString(params.path)}`);
291
+ // generate named
292
+ builder.push(`, { `);
293
+ generateNamedCode(builder, params.named);
294
+ builder.push(` }`);
295
+ // generate options
296
+ builder.push(`, { `);
297
+ if (params.options.locale) {
298
+ builder.push(`locale: ${toDisplayString(params.options.locale)}`);
299
+ }
300
+ if (params.options.plural) {
301
+ if (params.options.locale) {
302
+ builder.push(', ');
303
+ }
304
+ builder.push(`plural: ${toDisplayString(params.options.plural)}`);
305
+ }
306
+ builder.push(` }`);
307
+ builder.push(`)`);
308
+ const content = builder.content;
309
+ return content;
310
+ }
311
+ function generateNamedCode(builder, named) {
312
+ const keys = Object.keys(named);
313
+ keys.forEach(k => {
314
+ const v = named[k];
315
+ if (isObject(v)) {
316
+ builder.push(`${k}: { `);
317
+ generateNamedCode(builder, v);
318
+ builder.push(` }`);
319
+ }
320
+ else {
321
+ builder.push(`${k}: ${toDisplayString(v)}`);
322
+ }
323
+ });
324
+ }
325
+ function generateLegacyCode(context, params) {
326
+ const mode = !params.options.plural ? 'basic' : 'plural';
327
+ const baseCode = `${context.prefixIdentifiers ? '_ctx.' : ''}${mode === 'basic' ? '$t' : '$tc'}`;
328
+ const builder = createContentBuilder();
329
+ builder.push(`${baseCode}(`);
330
+ // generate path
331
+ builder.push(`${toDisplayString(params.path)}`);
332
+ if (mode === 'basic') {
333
+ // generate locale
334
+ if (isString(params.options.locale)) {
335
+ builder.push(`, ${toDisplayString(params.options.locale)}`);
336
+ }
337
+ // generate named
338
+ builder.push(`, { `);
339
+ generateNamedCode(builder, params.named);
340
+ builder.push(` }`);
341
+ }
342
+ else {
343
+ // generate plural
344
+ builder.push(`, ${toDisplayString(params.options.plural)}`);
345
+ if (isString(params.options.locale)) {
346
+ // generate locale
347
+ builder.push(`, ${toDisplayString(params.options.locale)}`);
348
+ }
349
+ else {
350
+ // generate named
351
+ builder.push(`, { `);
352
+ generateNamedCode(builder, params.named);
353
+ builder.push(` }`);
354
+ }
355
+ }
356
+ builder.push(`)`);
357
+ const content = builder.content;
358
+ return content;
359
+ }
@@ -0,0 +1,129 @@
1
+ import { parse } from '@babel/parser';
2
+ export function evaluateValue(expression) {
3
+ const ret = { status: 'ng', value: undefined };
4
+ try {
5
+ const ast = parse(`const a = ${expression.trim()}`);
6
+ if (ast.program.body.length >= 1 &&
7
+ ast.program.body[0].type === 'VariableDeclaration' &&
8
+ ast.program.body[0].declarations.length >= 1) {
9
+ const node = ast.program.body[0].declarations[0].init;
10
+ if (node != null && (node.type === 'StringLiteral' || node.type === 'ObjectExpression')) {
11
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
12
+ const val = new Function(`return ${expression.trim()} `)();
13
+ ret.status = 'ok';
14
+ ret.value = val;
15
+ }
16
+ }
17
+ // eslint-disable-next-line no-empty
18
+ }
19
+ catch (_e) { }
20
+ return ret;
21
+ }
22
+ export function parseVTExpression(expression) {
23
+ const ret = {
24
+ path: '',
25
+ named: {},
26
+ options: {}
27
+ };
28
+ try {
29
+ const ast = parse(`const a = ${expression.trim()}`);
30
+ if (ast.program.body.length >= 1 &&
31
+ ast.program.body[0].type === 'VariableDeclaration' &&
32
+ ast.program.body[0].declarations.length >= 1) {
33
+ const node = ast.program.body[0].declarations[0].init;
34
+ if (node != null) {
35
+ if (node.type === 'StringLiteral' && node.extra) {
36
+ ret.path = node.extra.raw;
37
+ }
38
+ else if (node.type === 'Identifier') {
39
+ ret.path = node.name;
40
+ }
41
+ else if (node.type === 'MemberExpression') {
42
+ ret.path = getObjectMemberValue(node);
43
+ }
44
+ else if (node.type === 'ObjectExpression') {
45
+ node.properties.forEach(propNode => {
46
+ if (propNode.type === 'ObjectProperty') {
47
+ const propKeyNode = propNode.key;
48
+ if (propKeyNode.type !== 'Identifier') {
49
+ return;
50
+ }
51
+ const propValueNode = propNode.value;
52
+ switch (propKeyNode.name) {
53
+ case 'path':
54
+ ret.path = getObjectMemberValue(propValueNode);
55
+ break;
56
+ case 'locale':
57
+ ret.options.locale = getObjectMemberValue(propValueNode);
58
+ break;
59
+ case 'choice':
60
+ case 'plural':
61
+ ret.options.plural = getObjectMemberValue(propValueNode);
62
+ break;
63
+ case 'args':
64
+ // console.log('args', propValueNode)
65
+ if (propValueNode.type === 'ObjectExpression') {
66
+ traverseObjectMember(propValueNode, ret.named);
67
+ }
68
+ break;
69
+ default:
70
+ break;
71
+ }
72
+ }
73
+ });
74
+ }
75
+ }
76
+ }
77
+ // eslint-disable-next-line no-empty
78
+ }
79
+ catch (_e) { }
80
+ return ret;
81
+ }
82
+ function getObjectMemberValue(node) {
83
+ if ((node.type === 'StringLiteral' || node.type === 'NumericLiteral') && node.extra) {
84
+ return node.extra.raw;
85
+ }
86
+ else if (node.type === 'Identifier') {
87
+ return node.name;
88
+ }
89
+ else if (node.type === 'MemberExpression') {
90
+ const paths = [];
91
+ collectMemberPath(node, paths);
92
+ paths.reverse();
93
+ return paths.join('.');
94
+ }
95
+ else {
96
+ return '';
97
+ }
98
+ }
99
+ function traverseObjectMember(node, target) {
100
+ node.properties.forEach(propNode => {
101
+ if (propNode.type === 'ObjectProperty') {
102
+ const propKeyNode = propNode.key;
103
+ if (propKeyNode.type !== 'Identifier') {
104
+ return;
105
+ }
106
+ if (!(propKeyNode.name in target)) {
107
+ target[propKeyNode.name] = {};
108
+ }
109
+ // console.log('propNode', propNode)
110
+ const propValueNode = propNode.value;
111
+ if (propValueNode.type === 'ObjectExpression') {
112
+ traverseObjectMember(propValueNode, target[propKeyNode.name]);
113
+ }
114
+ else {
115
+ target[propKeyNode.name] = getObjectMemberValue(propValueNode);
116
+ }
117
+ }
118
+ });
119
+ }
120
+ function collectMemberPath(node, paths) {
121
+ if (node.type === 'Identifier') {
122
+ paths.push(node.name);
123
+ return;
124
+ }
125
+ else if (node.type === 'MemberExpression' && node.property.type === 'Identifier') {
126
+ paths.push(node.property.name);
127
+ return collectMemberPath(node.object, paths);
128
+ }
129
+ }
@@ -0,0 +1,97 @@
1
+ import type { DirectiveTransform } from '@vue/compiler-dom';
2
+ import type { I18n } from 'vue-i18n';
3
+ import type { I18nMode } from 'vue-i18n';
4
+
5
+ /**
6
+ * Transform `v-t` custom directive
7
+ *
8
+ * @remarks
9
+ * Transform that `v-t` custom directive is optimized vue-i18n code by Vue compiler.
10
+ * This transform can improve the performance by pre-translating, and it does support SSR.
11
+ *
12
+ * @param options - `v-t` custom directive transform options, see {@link TransformVTDirectiveOptions}
13
+ * @returns Directive transform
14
+ *
15
+ * @example
16
+ * ```js
17
+ * import { compile } from '@vue/compiler-dom'
18
+ * import { createI18n } from 'vue-i18n'
19
+ * import { transformVTDirective } from '@intlify/vue-i18n-extensions'
20
+ *
21
+ * // create i18n instance
22
+ * const i18n = createI18n({
23
+ * locale: 'ja',
24
+ * messages: {
25
+ * en: {
26
+ * hello: 'hello'
27
+ * },
28
+ * ja: {
29
+ * hello: 'こんにちは'
30
+ * }
31
+ * }
32
+ * })
33
+ *
34
+ * // get transform from `transformVTDirective` function, with `i18n` option
35
+ * const transformVT = transformVTDirective({ i18n })
36
+ *
37
+ * const { code } = compile(`<p v-t="'hello'"></p>`, {
38
+ * mode: 'function',
39
+ * hoistStatic: true,
40
+ * prefixIdentifiers: true,
41
+ * directiveTransforms: { t: transformVT } // <- you need to specify to `directiveTransforms` option!
42
+ * })
43
+ *
44
+ * console.log(code)
45
+ * // output ->
46
+ * // const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue
47
+ * // return function render(_ctx, _cache) {
48
+ * // return (_openBlock(), _createBlock(\\"div\\", null, \\"こんにちは!\\"))
49
+ * // }
50
+ * ```
51
+ * @public
52
+ */
53
+ export declare function transformVTDirective<Messages extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
54
+ DateTimeFormats extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
55
+ NumberFormats extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
56
+ Legacy extends boolean = true>(options?: TransformVTDirectiveOptions<Messages, DateTimeFormats, NumberFormats, Legacy>): DirectiveTransform;
57
+
58
+ /**
59
+ * Transform options for `v-t` custom directive
60
+ *
61
+ * @public
62
+ */
63
+ export declare interface TransformVTDirectiveOptions<Messages extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
64
+ DateTimeFormats extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
65
+ NumberFormats extends Record<string, unknown> = {}, // eslint-disable-line @typescript-eslint/ban-types -- TODO: fix this
66
+ Legacy extends boolean = true> {
67
+ /**
68
+ * I18n instance
69
+ *
70
+ * @remarks
71
+ * If this option is specified, `v-t` custom directive transform uses an I18n instance to pre-translate.
72
+ * The translation will use the global resources registered in the I18n instance,
73
+ * that is, `v-t` directive transform is also a limitation that the resources of each component cannot be used.
74
+ */
75
+ i18n?: I18n<Messages, DateTimeFormats, NumberFormats, Legacy>;
76
+ /**
77
+ * I18n Mode
78
+ *
79
+ * @remarks
80
+ * Specify the API style of vue-i18n. If you use legacy API style (e.g. `$t`) at vue-i18n, you need to specify `legacy`.
81
+ *
82
+ * @default 'composition'
83
+ */
84
+ mode?: I18nMode;
85
+ /**
86
+ * Translation function signatures
87
+ *
88
+ * @remarks
89
+ * You can specify the signature of the translation function attached to the binding context when it is codegen in the Vue Compiler.
90
+ * If you have changed the signature to a non `t` signature in the `setup` hook or `<script setup>`, you can safely SSR it.
91
+ * If each Vue component has a different signature for the translation function, you can specify several in an array for safe SSR.
92
+ * This option value is `undefined` and the signature attached to the binding context is `t`.
93
+ */
94
+ translationSignatures?: string | string[];
95
+ }
96
+
97
+ export { }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@intlify/vue-i18n-extensions",
3
3
  "description": "vue-i18n extensions",
4
- "version": "6.0.3",
4
+ "version": "6.0.4",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"