WeblateOrg / WeblateOrg/weblate

Add native support for Vue i18n Single File Component (SFC) <i18n> custom blocks

Open
#17,241 1 comment 0 reactions 0 assignees View on GitHub
Area: File format support Waiting for: Demand
Dominant language
Python
Stars
6.1k
Forks
1.4k
Avg merge
9h 53m
Merged PRs (30d)
395

Description

### Describe the problem

### **Problem Description**

Currently, Weblate supports Vue i18n through standard JSON files (as documented in the [[JSON files format documentation](https://docs.weblate.org/en/latest/formats/json.html)](https://docs.weblate.org/en/latest/formats/json.html)). However, Vue.js developers commonly use **Single File Components (SFC)** with embedded `` custom blocks to manage component-scoped translations directly within `.vue` files.

This pattern is officially supported and recommended by Vue i18n, but Weblate currently lacks native support for parsing and managing these embedded translation blocks.

**Current Workflow (Problematic):**
1. Developers maintain translations in `` blocks within `.vue` files
2. To use Weblate, they must extract these translations to separate JSON files
3. After translation in Weblate, they must manually sync changes back to SFC files
4. This creates maintenance overhead, synchronization issues, and duplicated translation sources

---

### **Proposed Solution**

Add a new file format to Weblate: **"Vue i18n SFC"** or **"Vue SFC i18n blocks"**

This format would:

1. **Parse `.vue` files** and extract `` custom blocks
2. **Support both JSON and YAML formats** within `` blocks (as Vue i18n supports both)
3. **Maintain the original file structure** when writing translations back
4. **Handle multiple `` blocks** per file (Vue i18n supports this pattern)
5. **Preserve file integrity** - only modify content within `` tags, leaving ``, ``, and `<style>` sections untouched

---

### **Technical Details**

#### **Vue i18n SFC Structure Example:**

```vue
<template>
<div>
<h1>{{ $t('hello') }}</h1>
<p>{{ $t('welcome') }}</p>
</div>
</template>

<script>
export default {
name: 'MyComponent'
}

{
"en": {
"hello": "Hello World",
"welcome": "Welcome to our application"
},
"tr": {
"hello": "Merhaba Dünya",
"welcome": "Uygulamamıza hoş geldiniz"
}
}

h1 { color: blue; }

```

#### **Alternative YAML Format:**

```vue

en:
hello: Hello World
welcome: Welcome to our application
tr:
hello: Merhaba Dünya
welcome: Uygulamamıza hoş geldiniz

```

#### **External File Reference (also supported):**

```vue

```
---

### **Implementation Considerations**

#### **Parsing Strategy:**
- Use regex or XML parser to extract `` blocks from `.vue` files
- Detect format based on `lang` attribute (default: JSON)
- Parse the content according to detected format (JSON/YAML)
- Extract translation keys similar to existing JSON/YAML parsers

#### **Writing Strategy:**
- Preserve original file structure
- Only update content within `` tags
- Maintain formatting and indentation
- Support atomic updates to prevent file corruption

#### **File Format Properties:**
- **Monolingual**: Yes (each language is separate within the block)
- **Supports plurals**: Yes (inherited from JSON/YAML format capabilities)
- **Supports context**: Via keys (inherited from format)
- **Location**: File path + component name
- **Read-only support**: Can be implemented via flags

---

### **Integration with Existing Tools**

The Vue i18n ecosystem has several tools that work with SFC i18n blocks:

1. **[[@intlify/unplugin-vue-i18n](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n)](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n)** - Vite/Webpack plugin
---

### **Use Cases & Benefits**

#### **For Developers:**
- ✅ **Single source of truth** - translations live next to the components that use them
- ✅ **Better context** - translators see which component uses each string
- ✅ **Component-scoped translations** - avoid namespace collisions
- ✅ **Reduced maintenance** - no manual synchronization needed
- ✅ **Git-friendly** - translations and code changes in same commits

#### **For Translators:**
- ✅ **Better context** - can see component structure and usage
- ✅ **Component location** - know which UI element uses each string
- ✅ **Familiar Weblate interface** - no workflow changes needed

#### **For Project Managers:**
- ✅ **Simplified workflow** - no custom extraction/injection scripts
- ✅ **Reduced errors** - automated process prevents sync issues
- ✅ **Better tracking** - translations tied directly to components

---

### **Real-World Usage**

Many projects in the Vue.js ecosystem use this pattern:

- **[[Mainsail](https://github.com/mainsail-crew/mainsail)](https://github.com/mainsail-crew/mainsail)** - Uses Vue i18n with SFC, currently extracts to JSON for Weblate
- **Nuxt.js projects** - Commonly use i18n blocks with Nuxt i18n module
- **Vue 3 applications** - Increasingly adopt SFC i18n blocks with Composition API
- **Component libraries** - Use component-scoped translations for reusability

According to npm statistics, `vue-i18n` has **~2.5 million weekly downloads**, and a significant portion of users adopt the SFC pattern.

---

### **Alternative Workarounds (Current State)**

Users currently employ these workarounds:

1. **Manual extraction/injection scripts**
- Error-prone and maintenance-heavy

2. **Separate JSON files**
- Loses component-scoping benefits
- Requires manual synchronization
- Against Vue i18n best practices

3. **Pre/post-commit hooks**
- Complex setup
- Fragile and difficult to debug
- Vendor lock-in to specific workflows

4. **Not using Weblate**
- Weblate loses potential users from Vue.js ecosystem

---

### **Specification References**

- **Vue i18n SFC Documentation**: https://vue-i18n.intlify.dev/guide/advanced/sfc
- **@intlify/unplugin-vue-i18n**: https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
- **Vue Loader Custom Blocks**: https://vue-loader.vuejs.org/guide/custom-blocks.html

---

### **Implementation Priority Justification**

This feature would:
- 🎯 **Expand Weblate's market** to the large Vue.js ecosystem (2.5M+ weekly npm downloads)
- 🎯 **Reduce friction** for Vue.js developers adopting Weblate
- 🎯 **Align with best practices** recommended by Vue i18n documentation
- 🎯 **Complement existing JSON support** rather than replacing it
- 🎯 **Relatively low implementation cost** compared to potential user base growth

---

### **Similar Existing Implementations**

For reference, Weblate already supports several specialized formats:
- **Android string resources** - XML-embedded translations
- **iOS strings** - Specialized format for Apple ecosystem
- **WebExtension JSON** - Browser extension specific format
- **XLIFF** - XML-based translation interchange format

The Vue i18n SFC format would follow similar patterns but for Vue.js ecosystem.

---

### **Questions for Discussion**

1. Should this be implemented as a built-in format or as a plugin/extension?
2. Should external `src` references be followed, or should users be required to inline translations?
3. How should multiple `` blocks in a single file be handled in the Weblate UI?
4. Should this support both Vue 2 and Vue 3 SFC formats, or focus on Vue 3?

---

### **I'm Happy to Help**

I would be willing to:
- [ ] Provide more detailed technical specifications
- [ ] Create sample `.vue` files for testing
- [ ] Test the implementation with real-world projects
- [ ] Contribute to documentation
- [ ] Potentially contribute to implementation (depending on complexity)

### Solution brainstorm

Native Built-in Format (Recommended)
Implement Vue i18n SFC support as a native file format in Weblate, similar to existing specialized formats like Android XML or iOS strings.
Implementation Steps:

Create a new format class VueI18nSFCFormat inheriting from MonolingualFormat
Implement parsing logic:

Use regex or XML parser to locate blocks within .vue files
Detect format (JSON/YAML) from lang attribute or content analysis
Extract translations while preserving file structure

Implement serialization:

Update only block content
Preserve formatting, indentation, and other Vue SFC sections

Add format detection to auto-recognize .vue files with blocks

Pros:

✅ First-class support with full Weblate feature integration
✅ No external dependencies required
✅ Better performance (native implementation)
✅ Consistent with other Weblate formats

Cons:

❌ More initial development effort
❌ Maintenance burden on Weblate team

### Describe alternatives you have considered

_No response_

### Screenshots

_No response_

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.