ngx-multi-lingual
v1.0.2
Published
Zero-pipe auto-translation for Angular — built-in dictionary, IndexedDB cache, shared hosted backend, and AI fallback. No JSON files. No pipes. Just HTML.
Maintainers
Readme
ngx-multi-lingual
Zero-pipe auto-translation for Angular.
Drop it in, add one config line, and every text node in your app translates automatically — no | t pipe, no directive, no per-language JSON files.
npm install ngx-multi-lingualWhy this library exists
Every i18n solution for Angular requires developers to:
- Wrap every string in a pipe:
{{ 'Save' | translate }} - Maintain JSON files for each language
- Remember to mark every new string
ngx-multi-lingual eliminates all three. It scans the live DOM after render, translates everything it finds using a five-tier chain, and reacts to language changes automatically — including full RTL layout switching for Arabic, Urdu, Hebrew, and others.
Quick start
// app.config.ts
import { provideSmartI18n } from 'ngx-multi-lingual';
export const appConfig: ApplicationConfig = {
providers: [
provideSmartI18n({
projectId: 'my-app',
defaultLang: 'en',
autoTranslate: true,
}),
],
};<!-- app.html — plain HTML, no pipes needed -->
<button>Save</button>
<button>Cancel</button>
<h1>Welcome to the ERP System</h1>
<label>Customer Name</label>Switch language anywhere:
import { LanguageService } from 'ngx-multi-lingual';
@Component({ ... })
export class AppComponent {
lang = inject(LanguageService);
}<button (click)="lang.setLanguage('ar')">عربي</button>
<button (click)="lang.setLanguage('fr')">Français</button>The DOM updates instantly. RTL (dir="rtl") is applied automatically for Arabic and Urdu.
Five-tier translation chain
Every text node passes through these tiers in order — fastest first:
Tier 1 — Static config overrides (sync, ~0 ms)
Exact phrase → translation from your provideSmartI18n() config.
Use for domain-critical wording (e.g. "Invoice" → "Facture client").
Tier 2 — Built-in dictionary (sync, ~0 ms, offline)
160+ common ERP / UI terms across 7 languages.
Save, Cancel, Delete, Customer, Invoice, Total Revenue …
Tier 3 — IndexedDB word cache (async, ~1 ms)
Results from previous backend / AI calls stored locally.
Survives page refresh — no repeat network calls.
Tier 4 — Shared hosted backend (async, ~50 ms)
Millions of pre-translated phrases shared across all projects.
Activated by adding apiKey: 'si18n-...' to your config.
Tier 5 — AI fallback (async, ~800 ms, once-ever)
Unknown phrases go to Anthropic or OpenAI exactly once.
Result stored in IndexedDB + backend — never charged again.Supported languages
| Code | Language | RTL |
|------|-------------|-----|
| ar | Arabic | ✓ |
| ur | Urdu | ✓ |
| fr | French | |
| es | Spanish | |
| pt | Portuguese | |
| hi | Hindi | |
| de | German | |
RTL layout (document.documentElement.dir = 'rtl') is applied automatically when switching to ar or ur.
Hosted backend (Tier 4)
Register at https://smart-i18n.io, create a project, and get an API key.
Add one field — that's all:
provideSmartI18n({
projectId: 'my-app',
defaultLang: 'en',
autoTranslate: true,
apiKey: 'si18n-xxxxxxxxxxxx', // ← the only change
})- Every phrase your AI translates is contributed back to the shared database instantly
- Every future project that looks up the same phrase gets it free from the database — zero AI cost after the first occurrence globally
- No
apiUrl, no bundle server, no extra config needed
Self-hosted backend
Run the open-source Express.js + MySQL backend on your own infrastructure:
provideSmartI18n({
backendUrl: 'https://your-server.com/v1',
apiKey: 'your-key',
...
})AI fallback (Tier 5)
provideSmartI18n({
projectId: 'my-app',
defaultLang: 'en',
autoTranslate: true,
ai: {
provider: 'anthropic',
apiKey: 'sk-ant-YOUR_KEY',
model: 'claude-haiku-4-5-20251001', // fast & cheap
},
})OpenAI alternative:
ai: {
provider: 'openai',
apiKey: 'sk-YOUR_KEY',
model: 'gpt-4o-mini',
}Skip auto-translation
Use data-i18n-skip or translate="no" on any element to exclude its subtree:
<!-- Language switcher labels must not be translated -->
<div class="lang-switcher" data-i18n-skip>
<button (click)="lang.setLanguage('ar')">عربي</button>
<button (click)="lang.setLanguage('fr')">Français</button>
</div>
<!-- Code samples, terminal output, etc. -->
<code translate="no">npm install ngx-multi-lingual</code>Or configure selectors globally:
provideSmartI18n({
skipSelectors: ['.lang-switcher', '[data-i18n-skip]', 'code', 'pre'],
})Static overrides
Override specific phrases — useful for domain-specific terminology where exact wording matters:
provideSmartI18n({
staticTranslations: {
ar: {
default: {
'Save': 'حفظ',
'Welcome to the ERP System': 'مرحباً بك في نظام ERP',
},
crm: {
'Invoice': 'فاتورة مبيعات', // sales invoice
'Balance': 'الرصيد المحاسبي',
},
finance: {
'Invoice': 'فاتورة مالية', // financial invoice — different term
},
},
},
})The namespace (default, crm, finance) lets you use different translations for the same source word in different contexts.
Translation loading state
@Component({ ... })
export class AppComponent {
domTranslator = inject(DomTranslatorService);
}@if (domTranslator.isTranslating()) {
<div class="loading-bar">Translating…</div>
}Explicit pipe (optional)
For cases where you need translation in component logic rather than the DOM:
import { TranslatePipe } from 'ngx-multi-lingual';
@Component({
imports: [TranslatePipe],
template: `<title>{{ 'Dashboard' | t }}</title>`,
})With interpolation:
{{ 'Hello {{name}}, you have {{count}} messages' | t:{ params: { name: user.name, count: 5 } } }}Inline edit mode
Enable live translation editing with Ctrl+Alt+Click:
provideSmartI18n({
editMode: true, // enable in dev / staging only
})Clicking any translated text opens an inline editor for translators to fix strings without a code deploy.
Full config reference
provideSmartI18n({
// Required
projectId: 'my-app', // identifies your project in the backend
defaultLang: 'en', // source language of your HTML
// Auto-translation (zero-pipe mode)
autoTranslate: true,
skipSelectors: ['.lang-switcher', 'code', 'pre'],
minTextLength: 2, // ignore nodes shorter than this
// Hosted backend (Tier 4)
apiKey: 'si18n-...', // from https://smart-i18n.io
backendUrl: 'https://...', // only for self-hosted deployments
// AI fallback (Tier 5)
ai: {
provider: 'anthropic', // 'anthropic' | 'openai' | 'custom'
apiKey: 'sk-ant-...',
model: 'claude-haiku-4-5-20251001',
batchSize: 50, // texts per AI request
endpoint: '...', // custom endpoint / proxy
},
// Static overrides (Tier 1)
staticTranslations: {
ar: { default: { 'Save': 'حفظ' } }
},
eagerNamespaces: ['default', 'crm', 'finance'],
// Misc
editMode: true, // Ctrl+Alt+Click inline editor
cacheTtlMs: 604800000, // IndexedDB TTL — 7 days default
fallbackLang: 'en',
})How DOM auto-translation works
APP_BOOTSTRAP_LISTENERfires after the root component rendersDomTranslatorService.start()walks the DOM withTreeWalker, collecting all text nodes and translatable attributes (placeholder,title,aria-label,alt)- The five-tier chain resolves each phrase; DOM nodes are updated via
requestAnimationFrameto avoid layout thrashing - A
MutationObserverwatches for new nodes (routing, dynamic content) and translates them automatically with a 16 ms debounce
Built-in dictionary — 160+ terms, offline, zero config
Covers:
| Category | Examples | |----------|---------| | Actions | Save, Cancel, Delete, Edit, Add, Search, Export, Import, Reset … | | Navigation | Dashboard, Settings, Profile, Reports, Notifications … | | Auth | Login, Logout, Register, Password, Username, Email … | | Status | Active, Pending, Approved, Rejected, Completed, Paid, Overdue … | | Form fields | Name, Phone, Address, Date, Amount, Price, Quantity, Required … | | ERP core | Customer, Invoice, Order, Payment, Product, Vendor, Employee … | | Finance | Total Revenue, Profit & Loss, Tax, Discount, Fiscal Year, Due Date … |
Requirements
- Angular 17+
- Modern browser with IndexedDB support
License
MIT © Bilal Raza
