0
# SFC Integration
1
2
Processing of Vue Single File Component `<i18n>` custom blocks with support for multiple formats, scoping, and import functionality.
3
4
## Capabilities
5
6
### i18n Custom Blocks
7
8
Process `<i18n>` custom blocks within Vue Single File Components.
9
10
```typescript { .api }
11
/**
12
* i18n custom block processing in Vue SFCs
13
* Supports inline locale definitions and external imports
14
*/
15
interface I18nCustomBlock {
16
/**
17
* Inline locale messages in various formats
18
*/
19
inline: boolean;
20
21
/**
22
* Block language format
23
*/
24
lang?: SFCLangFormat;
25
26
/**
27
* Scope for the i18n block
28
*/
29
global?: boolean;
30
31
/**
32
* Locale identifier for the block
33
*/
34
locale?: string;
35
36
/**
37
* External resource import
38
*/
39
src?: string;
40
}
41
42
type SFCLangFormat = 'json' | 'json5' | 'yml' | 'yaml';
43
```
44
45
### Vue Request Query Parsing
46
47
Parse Vue SFC requests with i18n-specific query parameters.
48
49
```typescript { .api }
50
/**
51
* Parse Vue SFC request with query parameters
52
* @param id - Request identifier with query string
53
* @returns Parsed filename and query object
54
*/
55
function parseVueRequest(id: string): {
56
filename: string;
57
query: VueQuery;
58
};
59
60
interface VueQuery {
61
/** Whether this is a Vue file request */
62
vue?: boolean;
63
64
/** Whether this is a source file request */
65
src?: boolean;
66
67
/** Whether this block has global scope */
68
global?: boolean;
69
70
/** Type of SFC block */
71
type?: 'script' | 'template' | 'style' | 'custom' | 'i18n';
72
73
/** Custom block type name */
74
blockType?: string;
75
76
/** Block index within the SFC */
77
index?: number;
78
79
/** Locale identifier for the block */
80
locale?: string;
81
82
/** Language format of the block */
83
lang?: string;
84
85
/** Whether to return raw content */
86
raw?: boolean;
87
88
/** Path of the file that imported this resource */
89
issuerPath?: string;
90
}
91
```
92
93
### SFC Descriptor Processing
94
95
Create and process Vue SFC descriptors for i18n block extraction.
96
97
```typescript { .api }
98
/**
99
* Create SFC descriptor from source code
100
* @param filename - Source file name
101
* @param source - Vue SFC source code
102
* @param options - Vue plugin options
103
* @returns Parsed SFC descriptor and any errors
104
*/
105
function createDescriptor(
106
filename: string,
107
source: string,
108
options: VuePluginResolvedOptions
109
): SFCParseResult;
110
111
/**
112
* Get SFC descriptor, throwing on parse errors
113
* @param filename - Source file name
114
* @param code - Vue SFC source code
115
* @param options - Vue plugin options
116
* @returns Parsed SFC descriptor
117
* @throws {Error} If parsing fails
118
*/
119
function getDescriptor(
120
filename: string,
121
code: string,
122
options: VuePluginResolvedOptions
123
): SFCDescriptor;
124
125
interface SFCParseResult {
126
descriptor: SFCDescriptor;
127
errors: (CompilerError | SyntaxError)[];
128
}
129
```
130
131
### Vue Plugin Integration
132
133
Integration with Vue SFC compiler and plugin system.
134
135
```typescript { .api }
136
/**
137
* Extract Vue compiler from Vue plugin instance
138
* @param vuePlugin - Vue plugin instance
139
* @returns Vue SFC compiler
140
*/
141
function getVueCompiler(vuePlugin: RollupPlugin): typeof import('vue/compiler-sfc');
142
143
/**
144
* Extract Vue plugin options
145
* @param vuePlugin - Vue plugin instance
146
* @returns Resolved Vue plugin options
147
*/
148
function getVuePluginOptions(vuePlugin: RollupPlugin): VuePluginResolvedOptions;
149
150
/**
151
* Get SFC descriptor with error handling
152
* @param filename - Source file name
153
* @param code - Vue SFC source code
154
* @param options - Vue plugin options
155
* @returns Parsed SFC descriptor
156
* @throws {Error} If parsing fails
157
*/
158
function getDescriptor(
159
filename: string,
160
code: string,
161
options: VuePluginResolvedOptions
162
): SFCDescriptor;
163
164
interface VuePluginResolvedOptions {
165
isProduction: boolean;
166
root: string;
167
compiler: typeof import('vue/compiler-sfc');
168
template?: Partial<SFCTemplateCompileOptions>;
169
}
170
```
171
172
## SFC Configuration Options
173
174
### Block Language Configuration
175
176
```typescript { .api }
177
/**
178
* Configuration for SFC i18n block language handling
179
*/
180
interface SFCLanguageOptions {
181
/**
182
* Default language format for i18n blocks without lang attribute
183
* @default 'json'
184
*/
185
defaultSFCLang?: SFCLangFormat;
186
}
187
```
188
189
### Block Scoping Configuration
190
191
```typescript { .api }
192
/**
193
* Configuration for SFC i18n block scoping
194
*/
195
interface SFCScopingOptions {
196
/**
197
* Make all i18n blocks global scope by default
198
* Overrides individual block scope attributes
199
* @default false
200
*/
201
globalSFCScope?: boolean;
202
}
203
```
204
205
### Block Transformation
206
207
```typescript { .api }
208
/**
209
* Custom transformation for i18n block content
210
*/
211
interface SFCTransformOptions {
212
/**
213
* Transform function for i18n block source
214
* Called before block processing
215
* @param src - Original i18n block source
216
* @returns Transformed source string
217
*/
218
transformI18nBlock?: (src: string | Buffer) => string;
219
}
220
```
221
222
## Usage Examples
223
224
### Basic i18n Custom Block
225
226
```vue
227
<template>
228
<div>
229
<h1>{{ t('title') }}</h1>
230
<p>{{ t('description') }}</p>
231
</div>
232
</template>
233
234
<script setup>
235
import { useI18n } from 'vue-i18n';
236
237
const { t } = useI18n({
238
useScope: 'local'
239
});
240
</script>
241
242
<i18n>
243
{
244
"en": {
245
"title": "Welcome",
246
"description": "This is a local component message"
247
},
248
"fr": {
249
"title": "Bienvenue",
250
"description": "Ceci est un message de composant local"
251
}
252
}
253
</i18n>
254
```
255
256
### YAML Format i18n Block
257
258
```vue
259
<template>
260
<div>{{ t('message') }}</div>
261
</template>
262
263
<script setup>
264
import { useI18n } from 'vue-i18n';
265
const { t } = useI18n({ useScope: 'local' });
266
</script>
267
268
<i18n lang="yaml">
269
en:
270
message: Hello from YAML
271
nested:
272
key: Nested value
273
fr:
274
message: Bonjour depuis YAML
275
nested:
276
key: Valeur imbriquée
277
</i18n>
278
```
279
280
### Global Scope i18n Block
281
282
```vue
283
<template>
284
<div>{{ $t('global.message') }}</div>
285
</template>
286
287
<i18n global>
288
{
289
"en": {
290
"global": {
291
"message": "This message is available globally"
292
}
293
},
294
"fr": {
295
"global": {
296
"message": "Ce message est disponible globalement"
297
}
298
}
299
}
300
</i18n>
301
```
302
303
### External Resource Import
304
305
```vue
306
<template>
307
<div>{{ t('imported.message') }}</div>
308
</template>
309
310
<script setup>
311
import { useI18n } from 'vue-i18n';
312
const { t } = useI18n({ useScope: 'local' });
313
</script>
314
315
<!-- Import external i18n resource -->
316
<i18n src="./component-messages.json"></i18n>
317
```
318
319
### Multiple i18n Blocks
320
321
```vue
322
<template>
323
<div>
324
<h1>{{ t('title') }}</h1>
325
<nav>
326
<a href="/">{{ $t('nav.home') }}</a>
327
<a href="/about">{{ $t('nav.about') }}</a>
328
</nav>
329
</div>
330
</template>
331
332
<script setup>
333
import { useI18n } from 'vue-i18n';
334
const { t } = useI18n({ useScope: 'local' });
335
</script>
336
337
<!-- Local messages for this component -->
338
<i18n>
339
{
340
"en": { "title": "Component Title" },
341
"fr": { "title": "Titre du Composant" }
342
}
343
</i18n>
344
345
<!-- Global navigation messages -->
346
<i18n global>
347
{
348
"en": {
349
"nav": {
350
"home": "Home",
351
"about": "About"
352
}
353
},
354
"fr": {
355
"nav": {
356
"home": "Accueil",
357
"about": "À propos"
358
}
359
}
360
}
361
</i18n>
362
```
363
364
### Locale-specific Blocks
365
366
```vue
367
<template>
368
<div>{{ t('message') }}</div>
369
</template>
370
371
<script setup>
372
import { useI18n } from 'vue-i18n';
373
const { t } = useI18n({ useScope: 'local' });
374
</script>
375
376
<!-- English-only block -->
377
<i18n locale="en">
378
{
379
"message": "English-specific message",
380
"feature": "This feature is English-only"
381
}
382
</i18n>
383
384
<!-- French-only block -->
385
<i18n locale="fr" lang="yaml">
386
message: Message spécifique au français
387
feature: Cette fonctionnalité est réservée au français
388
</i18n>
389
```
390
391
### Custom Block Transformation
392
393
```typescript
394
// Plugin configuration with custom transformation
395
VueI18nPlugin({
396
transformI18nBlock: (source) => {
397
// Transform array of message keys to full message objects
398
if (source.trim().startsWith('[')) {
399
const keys = JSON.parse(source);
400
const messages = {};
401
402
keys.forEach(key => {
403
messages.en = messages.en || {};
404
messages.fr = messages.fr || {};
405
messages.en[key] = `English: ${key}`;
406
messages.fr[key] = `Français: ${key}`;
407
});
408
409
return JSON.stringify(messages);
410
}
411
return source;
412
}
413
});
414
```
415
416
```vue
417
<!-- Before transformation -->
418
<i18n>
419
[
420
"welcome",
421
"goodbye",
422
"thank-you"
423
]
424
</i18n>
425
426
<!-- After transformation (automatic) -->
427
<i18n>
428
{
429
"en": {
430
"welcome": "English: welcome",
431
"goodbye": "English: goodbye",
432
"thank-you": "English: thank-you"
433
},
434
"fr": {
435
"welcome": "Français: welcome",
436
"goodbye": "Français: goodbye",
437
"thank-you": "Français: thank-you"
438
}
439
}
440
</i18n>
441
```
442
443
## Configuration Examples
444
445
### Basic SFC Configuration
446
447
```typescript
448
VueI18nPlugin({
449
defaultSFCLang: 'yaml',
450
globalSFCScope: false
451
});
452
```
453
454
### Advanced SFC Configuration
455
456
```typescript
457
VueI18nPlugin({
458
defaultSFCLang: 'json5',
459
globalSFCScope: true,
460
transformI18nBlock: (src) => {
461
// Custom preprocessing logic
462
return preprocessI18nBlock(src);
463
}
464
});
465
```
466
467
### Development vs Production
468
469
```typescript
470
const isDev = process.env.NODE_ENV === 'development';
471
472
VueI18nPlugin({
473
defaultSFCLang: isDev ? 'yaml' : 'json',
474
globalSFCScope: false,
475
strictMessage: !isDev,
476
escapeHtml: !isDev
477
});
478
```