i18n+
pendingby dangehub
Manage translations for plugins with hot-reload support and crowdsourced dictionaries.
i18n+
A universal internationalization (i18n) framework for the Obsidian plugin ecosystem. Provides zero-dependency adapters, automated migration tools, and seamless multi-language support.
✨ Features
- Zero Runtime Dependency: Plugins work perfectly without I18n Plus installed
- Standalone + Mixed Mode: Built-in languages work independently; external dictionaries can override/extend them
- Automated Migration: Transform hardcoded strings to
t()calls with one command - Hot Reload: Switch languages instantly without restarting plugins
- Community Translations: Users can import third-party translations without code changes
🚀 Quick Start
For Plugin Developers: See the full Migration Guide for detailed integration instructions.
For Plugin Developers
-
Copy the adapter to your plugin:
cp templates/adapter.ts your-plugin/src/lang/i18n.ts -
Initialize in main.ts:
import { initI18n } from './lang/i18n'; export default class MyPlugin extends Plugin { i18n: I18nAdapter; t: (key: string, params?: any) => string; async onload() { this.i18n = initI18n(this); this.t = this.i18n.t.bind(this.i18n); } } -
Use translations:
new Notice(this.t("Hello, {name}!", { name: "World" }));
Automated Migration
Run the codemod to automatically replace hardcoded strings:
# Install jscodeshift
npm install -g jscodeshift
# Run codemod on your plugin
npx jscodeshift -t scripts/i18n-codemod.cjs your-plugin/src/ --parser=ts
# Extract keys to generate en.ts
node scripts/extract-keys.cjs your-plugin/src
📦 How It Works
Priority System
When t("key") is called, the adapter searches in this order:
- External Dictionary (loaded via I18n Plus)
- Built-in Language (current locale)
- Last Successful Locale (smart fallback to previous working language)
- Base Locale (configurable, defaults to English)
- Raw Key
This means:
- Users can override built-in translations with custom JSON files
- New languages can be added without modifying plugin code
- If a new language fails, it falls back to the last working language (not hardcoded English)
- Plugins work offline without I18n Plus installed
Architecture
┌─────────────────────────────────────────────────────────┐
│ Your Plugin │
│ ┌─────────────────────────────────────────────────┐ │
│ │ adapter.ts (self-contained, ~150 lines) │ │
│ │ ├── BUILTIN_LOCALES: { en, zh, ... } │ │
│ │ └── _externalDictionaries: { de, fr, ... } │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
▲
│ (optional)
▼
┌─────────────────────────────────────────────────────────┐
│ I18n Plus Plugin (optional) │
│ ├── Dictionary Manager UI │
│ ├── Global Locale Sync │
│ └── External .json Import/Export │
└─────────────────────────────────────────────────────────┘
🛠️ Scripts
| Script | Description |
|---|---|
i18n-codemod.cjs | Transform hardcoded strings to t() calls |
extract-keys.cjs | Extract all keys and generate en.ts |
inject-i18n.cjs | Auto-inject adapter into main.ts |
generate-report.cjs | Generate migration report |
🔧 Development
Available Commands
| Command | Description |
|---|---|
npm run dev | Start development mode with hot reload |
npm run build | Build the plugin (output to project root) |
npm run deploy | Build and copy to Obsidian test vault |
npm run lint | Run ESLint checks |
Deploy to Test Vault
The deploy command automatically copies build artifacts to your local Obsidian vault for testing.
Setup:
-
Create
deploy.config.local.jsonin project root:{ "targetDir": "C:\\path\\to\\your\\.obsidian\\plugins\\i18n-plus" } -
Run:
npm run deploy
Note:
deploy.config.local.jsonis gitignored to keep your local paths private.
📁 Project Structure
templates/
└── adapter.ts # Copy this to your plugin
scripts/
├── i18n-codemod.cjs # String replacement codemod
├── extract-keys.cjs # Key extraction script
└── inject-i18n.cjs # Auto-injection script
examples/
└── auto-migrate-workflow.yml # GitHub Action template
docs/
├── README.zh-CN.md # Chinese documentation
└── I18N_MIGRATION_GUIDE.zh-CN.md # Migration guide
🚨 Vibe Coding Warning
This project was built using Vibe Coding. While I have done my best to ensure the reliability of the code, please do not use this project if you are uncomfortable with this approach.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT License - see LICENSE for details.
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.