or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-optimizations.mdindex.mdplugin-configuration.mdresource-processing.mdsfc-integration.md
tile.json

sfc-integration.mddocs/

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

```