Project Awesome project awesome

Internationalization > ngx-directo

Angular 18+ Signals-based library for RTL/LTR directionality, Arabic localization, and Google Font orchestration.

Package 6 stars GitHub

Directo / NG Banner

ngx-directo

NPM Version License Bundle Size Angular Version GitHub Stars

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: 1 in LTR, -1 in RTL.
  • --dir-align: left in LTR, right in 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

Back to Angular