Internationalization > ngx-directo
Angular 18+ Signals-based library for RTL/LTR directionality, Arabic localization, and Google Font orchestration.
ngx-directo
The ultimate Angular 18+ Signals-based library for RTL/LTR directionality, Arabic localization, and Google Font orchestration. Zoneless-ready and high-performance.
⭐ Star this on GitHub to support RTL development!
ngx-directo is a high-performance, lightweight Angular library for managing bi-directional (RTL/LTR) layouts, dynamic font orchestration, and localized UI state. Built for the modern web, it is fully zoneless-ready and powered by fine-grained Signals.
Key Advantages
- Zoneless Optimized: Zero dependence on NgZone. Perfectly compatible with provideZonelessChangeDetection().
- Reactive Design: Built entirely on Angular Signals for high-performance state updates.
- Smart Detection: MutationObserver-driven script detection for mixed-content isolation.
- Automatic Font Orchestration: Dynamic injection of Google Fonts based on active language state.
- Intelligent Mapping: Built-in support for all major RTL languages (
ar,he,fa,ur, etc.) out of the box. - CSS-Native Animations: Direct injection of --dir-sign and --dir-align variables for zero-JS animations.
Installation
npm install ngx-directo
Configuration & Hydration
Initialize the library in your app.config.ts. Directo is designed to be Zero-Config by default, providing sensible fallbacks for English (LTR) and Arabic (RTL) out of the box.
Production Setup (Recommended)
Directo is designed to be Zero-Config by default, providing sensible fallbacks for English (LTR) and Arabic (RTL) out of the box. For production-grade applications, you can use the built-in DirectoLoader to automate translation loading.
import { ApplicationConfig } from '@angular/core';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { provideDirecto, DIRECTO_LOADER, DirectoHttpLoader, DirectoFetchLoader } from 'ngx-directo';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideDirecto({
languages: {
ar: {
direction: 'rtl',
fontFamily: 'Cairo, sans-serif',
googleFontName: 'Cairo', // Auto-injected from Google Fonts
localizeDigits: true, // Enables 0-9 to ٠-٩ conversion
},
en: {
direction: 'ltr',
fontFamily: 'Inter, sans-serif',
googleFontName: 'Inter'
}
},
defaultLang: 'en',
// Option A: Automatic translation loading (using HttpClient)
// Default: ./assets/i18n/{{lang}}.json
loader: {
provide: DIRECTO_LOADER,
useFactory: (http: HttpClient) => new DirectoHttpLoader(http, './assets/i18n/', '.json'),
deps: [HttpClient]
}
// Option B: Native Fetch-based loading (No HttpClient dependency)
// loader: {
// provide: DIRECTO_LOADER,
// useValue: new DirectoFetchLoader('/assets/i18n/{{lang}}.json')
// }
})
]
};
Option C: Manual Hydration (Advanced)
If you need complete control over the loading process (e.g., merging multiple JSON files or complex logic), you can still use the APP_INITIALIZER pattern to call setTranslations() manually.
{
provide: APP_INITIALIZER,
useFactory: () => {
const directo = inject(DirectoService);
const http = inject(HttpClient);
return () => firstValueFrom(
http.get(`/assets/i18n/${directo.currentLang()}.json`).pipe(
tap(data => directo.setTranslations(directo.currentLang(), data))
)
);
},
multi: true
}
Quick Start (Zero-Config)
If you just want to use the directives and pipes without advanced font orchestration or translation management, you can skip the configuration entirely or pass an empty object:
providers: [
provideDirecto() // Automatically supports ar, en, he, fa, ur, and more!
]
Directo includes an Intelligent Registry. If you call directo.setLanguage('ar'), it automatically knows Arabic is RTL and swaps your entire layout, even if you didn't configure it.
Directives
[dirAuto] - Intelligent Script Detection
Detects the direction of content (RTL/LTR) automatically using first-strong-character logic.
<p [dirAuto]="dynamicText">{{ dynamicText }}</p>
<p dirAuto>This scans inner text content automatically.</p>
[dirFlip] - RTL Mirroring
Flips icons or elements horizontally only when the app is in RTL mode.
<i dirFlip class="pi pi-chevron-right"></i>
[dirOnly] - Conditional Rendering
Conditionally renders elements based on the active direction.
<div dirOnly="rtl">Only visible in RTL mode</div>
[dirInput] - LTR Input Lock
Forces inputs to remain LTR. Critical for phone numbers, passwords, and codes.
<input dirInput type="tel" placeholder="+966 5XX">
Pipes
| Pipe | Description | Example |
|---|---|---|
| localize | Multi-strategy localization. Supports direct values, object mapping, or auto-key resolution. | {{ enVal | localize : arVal }} or {{ item | localize : 'name' }} |
| directoTranslate | Resolves static UI strings via dot-notation. Can also force a specific language (optional parameter). | {{ 'KEY' | directoTranslate : 'ar' }} |
| dirMirror | Swaps directional keywords in strings (left <-> right, next <-> prev). | {{ 'chevron-right' | dirMirror }} |
| dirNumber | Transforms Western digits (0-9) to native Arabic-Indic digits (٠-٩). | {{ 2026 | dirNumber }} |
Zero-JS Directional Logic
This is a Senior-level feature: Directo enables "Zero-JS" UI logic by injecting reactive CSS variables into the :root element. This allows you to handle complex directionality in SCSS without a single line of component TypeScript.
--dir-sign:1in LTR,-1in RTL.--dir-align:leftin LTR,rightin RTL.--dir-align-inv: The inverse alignment side.
SCSS Example:
.sidebar {
transition: transform 0.3s ease;
// This automatically slides from the correct side in BOTH RTL and LTR!
transform: translateX(calc(var(--dir-sign) * -100%));
}
Legacy Support (Optional)
For projects using the classic @angular/animations DSL, Directo provides a mirroring utility. Note that @angular/animations is an optional peer dependency and is only required if you use this specific helper:
import { mirrorAnimation } from 'ngx-directo';
// Usage in trigger/transition definitions
Authorship and License
Copyright (c) 2026 Ahmad Alhafi. All rights reserved. MIT License