README file from
Githubi18n+
I18n Plus is a powerful Obsidian internationalization (i18n) management plugin, and also a universal development framework for the plugin ecosystem.
For Users, it is an intuitive translation management tool that lets you easily translate/correct plugin translations. For Developers, it provides zero-dependency i18n adapters and automated migration tools.
Read the Whitepaper: For a deep dive into the philosophy, architecture, and future roadmap of Obsidian's third-party internationalization, please read the Whitepaper.
✨ Features
For Users
- Visual Management: View and manage translation status of all plugins in a unified panel
- Hot Reload: Switch plugin languages without restarting Obsidian, effective immediately
- Incremental Localization: Modify only unsatisfactory translations via "Overlay" mode without affecting the original plugin
- Community Sharing: Import/Export
.jsontranslation files for easy sharing - Cloud Sync: Download the latest community translation packages directly from the cloud
For Developers
- 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 - Type Safety: TypeScript-based intelligent code completion
🚀 Quick Start
For Users
- Install Plugin: Search for and install
i18n-plusin Obsidian Community Plugins. - Open Manager: Click the
🌐icon in the left sidebar, or use the commandOpen Dictionary Manager. - Switch Language:
- Find the target plugin in the list
- Select
zhor another language from the dropdown - The interface will update immediately (for plugins supporting hot reload)
- Correct Translation:
- Click the
👁️(View Content) button next to the plugin - Modify the translation in the editor
- Click
Saveto apply changes immediately
- Click the
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.