@flusys/ng-localization 4.1.1 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -387
- package/fesm2022/flusys-ng-localization.mjs +576 -922
- package/fesm2022/flusys-ng-localization.mjs.map +1 -1
- package/package.json +3 -3
- package/types/flusys-ng-localization.d.ts +12 -86
package/README.md
CHANGED
|
@@ -1,92 +1,21 @@
|
|
|
1
1
|
# @flusys/ng-localization
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Database-driven i18n for FLUSYS Angular apps — translations loaded from the backend at startup, signal-reactive `TranslatePipe`, RTL/LTR auto-switching, and a built-in language selector for the topbar.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@flusys/ng-localization)
|
|
6
|
-
[](https://www.typescriptlang.org)
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Table of Contents
|
|
13
|
-
|
|
14
|
-
- [Overview](#overview)
|
|
15
|
-
- [Features](#features)
|
|
16
|
-
- [Compatibility](#compatibility)
|
|
17
|
-
- [Installation](#installation)
|
|
18
|
-
- [Quick Start](#quick-start)
|
|
19
|
-
- [Module Registration](#module-registration)
|
|
20
|
-
- [TranslateService](#translateservice)
|
|
21
|
-
- [TranslatePipe](#translatepipe)
|
|
22
|
-
- [Variable Interpolation](#variable-interpolation)
|
|
23
|
-
- [Language Management](#language-management)
|
|
24
|
-
- [Components](#components)
|
|
25
|
-
- [LanguageSelectorComponent](#languageselectorcomponent)
|
|
26
|
-
- [Route Resolver](#route-resolver)
|
|
27
|
-
- [RTL Support](#rtl-support)
|
|
28
|
-
- [TRANSLATE_ADAPTER Token](#translate_adapter-token)
|
|
29
|
-
- [API Endpoints](#api-endpoints)
|
|
30
|
-
- [Configuration Reference](#configuration-reference)
|
|
31
|
-
- [Troubleshooting](#troubleshooting)
|
|
32
|
-
- [License](#license)
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## Overview
|
|
37
|
-
|
|
38
|
-
`@flusys/ng-localization` provides database-driven i18n for FLUSYS applications. Translations are stored in the backend (`nestjs-localization`) and loaded at app startup via `APP_INITIALIZER`. The `TranslatePipe` integrates with `TranslateService` through the `TRANSLATE_ADAPTER` injection token — keeping all other packages independent of `ng-localization`.
|
|
39
|
-
|
|
40
|
-
Unlike file-based i18n (ngx-translate), FLUSYS translations are managed in the database and can be updated at runtime without rebuilding.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Features
|
|
45
|
-
|
|
46
|
-
- ✅ Database-driven translations (updated without rebuild)
|
|
47
|
-
- ✅ `TranslatePipe` with signal reactivity — re-renders on language switch
|
|
48
|
-
- ✅ `{{variableName}}` interpolation with `messageVariables`
|
|
49
|
-
- ✅ RTL/LTR document direction auto-switch
|
|
50
|
-
- ✅ APP_INITIALIZER bootstrap — translations loaded before app renders
|
|
51
|
-
- ✅ Route resolver for per-route language loading
|
|
52
|
-
- ✅ Language selector component for topbar
|
|
53
|
-
- ✅ `provideLocalization()` — registers `TRANSLATE_ADAPTER` and `LAYOUT_LANGUAGE_SELECTOR`
|
|
54
|
-
- ✅ Missing key detection and fallback
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Compatibility
|
|
59
|
-
|
|
60
|
-
| Package | Version |
|
|
61
|
-
|---------|---------|
|
|
62
|
-
| Angular | 21+ |
|
|
63
|
-
| @flusys/ng-core | 4.x |
|
|
64
|
-
| @flusys/ng-shared | 4.x |
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
65
7
|
|
|
66
8
|
---
|
|
67
9
|
|
|
68
10
|
## Installation
|
|
69
11
|
|
|
70
12
|
```bash
|
|
71
|
-
npm install @flusys/ng-localization
|
|
13
|
+
npm install @flusys/ng-localization
|
|
72
14
|
```
|
|
73
15
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
## Quick Start
|
|
16
|
+
## 1. Register Providers
|
|
77
17
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
// environments/environment.ts
|
|
82
|
-
export const environment = {
|
|
83
|
-
services: {
|
|
84
|
-
localization: { enabled: true },
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### 2. Register Localization Providers
|
|
18
|
+
Call `provideLocalization()` once in `app.config.ts`. It registers `TRANSLATE_ADAPTER` (consumed by `TranslatePipe` from `ng-shared`), an `APP_INITIALIZER` that loads translations before the first render, and optionally the topbar language selector.
|
|
90
19
|
|
|
91
20
|
```typescript
|
|
92
21
|
// app.config.ts
|
|
@@ -94,363 +23,118 @@ import { provideLocalization } from '@flusys/ng-localization';
|
|
|
94
23
|
|
|
95
24
|
export const appConfig: ApplicationConfig = {
|
|
96
25
|
providers: [
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
26
|
+
provideLocalization({
|
|
27
|
+
defaultLanguageCode: 'en', // required — fallback when no saved preference
|
|
28
|
+
loadStrategy: 'modules', // optional — 'modules' (default) or 'all'
|
|
29
|
+
initialModules: [], // optional — modules to pre-load at startup
|
|
30
|
+
enableLayoutSelector: true, // optional — renders language picker in AppTopbar
|
|
31
|
+
}),
|
|
102
32
|
],
|
|
103
33
|
};
|
|
104
34
|
```
|
|
105
35
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```html
|
|
109
|
-
<!-- Basic translation -->
|
|
110
|
-
<span>{{ 'common.save' | translate }}</span>
|
|
111
|
-
<button>{{ 'common.cancel' | translate }}</button>
|
|
112
|
-
<h1>{{ 'dashboard.title' | translate }}</h1>
|
|
113
|
-
|
|
114
|
-
<!-- With parameters -->
|
|
115
|
-
<p>{{ 'pagination.showing' | translate: { from: 1, to: 10, total: 100 } }}</p>
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Module Registration
|
|
121
|
-
|
|
122
|
-
### `provideLocalization()`
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
import { provideLocalization } from '@flusys/ng-localization';
|
|
126
|
-
|
|
127
|
-
providers: [
|
|
128
|
-
...provideLocalization(),
|
|
129
|
-
]
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Registers:
|
|
133
|
-
- `TRANSLATE_ADAPTER` — `TranslateService` implementation (used by `TranslatePipe` from `ng-shared`)
|
|
134
|
-
- `LAYOUT_LANGUAGE_SELECTOR` — `ILanguageSelectorProvider` implementation (used by `AppTopbar`)
|
|
135
|
-
- `APP_INITIALIZER` — loads translations for the default language before first render
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## TranslateService
|
|
140
|
-
|
|
141
|
-
The core service managing translations and language state:
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
import { TranslateService } from '@flusys/ng-localization';
|
|
145
|
-
|
|
146
|
-
@Component({ ... })
|
|
147
|
-
export class MyComponent {
|
|
148
|
-
private translate = inject(TranslateService);
|
|
149
|
-
|
|
150
|
-
// Signals
|
|
151
|
-
currentLanguage = this.translate.currentLanguage; // Signal<ILanguage>
|
|
152
|
-
availableLanguages = this.translate.languages; // Signal<ILanguage[]>
|
|
153
|
-
isLoading = this.translate.isLoading; // Signal<boolean>
|
|
154
|
-
|
|
155
|
-
// Methods
|
|
156
|
-
translate(key: string, params?: Record<string, string | number>): string {
|
|
157
|
-
return this.translate.get(key, params);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
switchLanguage(languageCode: string): void {
|
|
161
|
-
this.translate.setLanguage(languageCode);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
**TranslateService API:**
|
|
36
|
+
`loadStrategy: 'modules'` defers loading until a route resolver requests a module. Use `'all'` only for small translation sets.
|
|
167
37
|
|
|
168
|
-
|
|
169
|
-
|--------|------|-------------|
|
|
170
|
-
| `currentLanguage` | `Signal<ILanguage>` | Active language object |
|
|
171
|
-
| `languages` | `Signal<ILanguage[]>` | All available languages |
|
|
172
|
-
| `isLoading` | `Signal<boolean>` | True when switching languages |
|
|
173
|
-
| `get(key, params?)` | `string` | Translate a key synchronously |
|
|
174
|
-
| `setLanguage(code)` | `Observable<void>` | Switch language (loads translations) |
|
|
175
|
-
| `reloadTranslations()` | `Observable<void>` | Force reload from backend |
|
|
176
|
-
|
|
177
|
-
**ILanguage Model:**
|
|
38
|
+
## 2. Use TranslatePipe in Templates
|
|
178
39
|
|
|
40
|
+
Import `TranslatePipe` from `@flusys/ng-shared` (not from this package). The pipe is signal-reactive and re-renders automatically on language change.
|
|
41
|
+
language
|
|
179
42
|
```typescript
|
|
180
|
-
|
|
181
|
-
id: string;
|
|
182
|
-
name: string; // "English"
|
|
183
|
-
nativeName: string; // "English" / "العربية"
|
|
184
|
-
code: string; // "en" / "ar"
|
|
185
|
-
isDefault: boolean;
|
|
186
|
-
isRtl: boolean;
|
|
187
|
-
isActive: boolean;
|
|
188
|
-
flagIcon?: string; // Country flag identifier
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
---
|
|
43
|
+
import { TranslatePipe } from '@flusys/ng-shared';
|
|
193
44
|
|
|
194
|
-
|
|
45
|
+
@Component({
|
|
46
|
+
imports: [TranslatePipe],
|
|
47
|
+
template: `
|
|
48
|
+
<h1>{{ 'dashboard.title' | translate }}</h1>
|
|
49
|
+
<button>{{ 'shared.save' | translate }}</button>
|
|
50
|
+
<input [placeholder]="'form.search.placeholder' | translate" />
|
|
195
51
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<!-- With interpolation parameters -->
|
|
203
|
-
{{ 'user.greeting' | translate: { name: userName() } }}
|
|
204
|
-
|
|
205
|
-
<!-- In attribute binding -->
|
|
206
|
-
<input [placeholder]="'form.search.placeholder' | translate" />
|
|
207
|
-
|
|
208
|
-
<!-- In event handler label -->
|
|
209
|
-
<button [title]="'action.delete.tooltip' | translate">
|
|
210
|
-
<i class="pi pi-trash"></i>
|
|
211
|
-
</button>
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**Translation Key Convention:**
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
module.component.element
|
|
52
|
+
<!-- With interpolation -->
|
|
53
|
+
<p>{{ 'pagination.showing' | translate: { from: 1, to: 10, total: 100 } }}</p>
|
|
54
|
+
`,
|
|
55
|
+
})
|
|
56
|
+
export class DashboardComponent {}
|
|
218
57
|
```
|
|
219
58
|
|
|
220
|
-
|
|
59
|
+
Translation values stored in the database use `{{variableName}}` syntax:
|
|
221
60
|
```
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
common.delete
|
|
225
|
-
auth.login.title
|
|
226
|
-
auth.login.email.label
|
|
227
|
-
dashboard.title
|
|
228
|
-
menu.products
|
|
229
|
-
pagination.showing
|
|
61
|
+
Key: pagination.showing
|
|
62
|
+
Value: Showing {{from}}-{{to}} of {{total}} results
|
|
230
63
|
```
|
|
231
64
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
## Variable Interpolation
|
|
65
|
+
## 3. Load Translations Per Route (Module Strategy)
|
|
235
66
|
|
|
236
|
-
Use `
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
# In database:
|
|
240
|
-
Key: "pagination.showing"
|
|
241
|
-
Value: "Showing {{from}}-{{to}} of {{total}} results"
|
|
242
|
-
|
|
243
|
-
# In Arabic:
|
|
244
|
-
Key: "pagination.showing"
|
|
245
|
-
Value: "عرض {{from}}-{{to}} من {{total}} نتيجة"
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
```html
|
|
249
|
-
<!-- Angular template -->
|
|
250
|
-
{{ 'pagination.showing' | translate: { from: page * pageSize + 1, to: endItem, total: total() } }}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
**Backend `messageVariables` field:**
|
|
254
|
-
|
|
255
|
-
When the backend sends translation responses, it includes a `messageVariables` field with the variable names the translation expects:
|
|
256
|
-
|
|
257
|
-
```json
|
|
258
|
-
{
|
|
259
|
-
"key": "pagination.showing",
|
|
260
|
-
"value": "Showing {{from}}-{{to}} of {{total}} results",
|
|
261
|
-
"messageVariables": ["from", "to", "total"]
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
## Language Management
|
|
268
|
-
|
|
269
|
-
Languages are managed via the `ng-localization` admin pages:
|
|
67
|
+
Use `resolveTranslationModule()` in your route definition so translations for a feature load before the page renders. Pass `fallbackMessages` so the UI works even without a backend.
|
|
270
68
|
|
|
271
69
|
```typescript
|
|
272
|
-
//
|
|
273
|
-
import {
|
|
70
|
+
// Inside a feature's routes file
|
|
71
|
+
import { resolveTranslationModule } from '@flusys/ng-shared';
|
|
72
|
+
import { MY_FEATURE_MESSAGES } from './constants/messages';
|
|
274
73
|
|
|
275
|
-
export const
|
|
74
|
+
export const MY_ROUTES: Routes = [
|
|
276
75
|
{
|
|
277
|
-
path: '
|
|
278
|
-
|
|
76
|
+
path: '',
|
|
77
|
+
resolve: {
|
|
78
|
+
translations: resolveTranslationModule({
|
|
79
|
+
modules: ['myFeature'], // module name used by the backend
|
|
80
|
+
fallbackMessages: MY_FEATURE_MESSAGES, // static fallback map
|
|
81
|
+
}),
|
|
82
|
+
},
|
|
83
|
+
loadComponent: () => import('./my-feature-container.component')
|
|
84
|
+
.then(m => m.MyFeatureContainerComponent),
|
|
85
|
+
children: [/* ... */],
|
|
279
86
|
},
|
|
280
87
|
];
|
|
281
88
|
```
|
|
282
89
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
| `/localization/translations` | Manage translation keys and values |
|
|
287
|
-
| `/localization/translations/:module` | Filter by module |
|
|
90
|
+
Already-loaded modules are cached — navigating back to the same route does not re-fetch.
|
|
91
|
+
|
|
92
|
+
## 4. Translate Imperatively in Services / Components
|
|
288
93
|
|
|
289
|
-
|
|
94
|
+
Inject `TranslateService` when you need a string outside a template (e.g., toast messages, computed labels).
|
|
290
95
|
|
|
291
96
|
```typescript
|
|
292
|
-
import {
|
|
97
|
+
import { inject } from '@angular/core';
|
|
98
|
+
import { TranslateService } from '@flusys/ng-localization';
|
|
293
99
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
private translateApi = inject(TranslateApiService);
|
|
100
|
+
export class MyComponent {
|
|
101
|
+
private readonly translate = inject(TranslateService);
|
|
297
102
|
|
|
298
|
-
|
|
299
|
-
|
|
103
|
+
// Synchronous — returns fallback key if not found
|
|
104
|
+
getLabel(): string {
|
|
105
|
+
return this.translate.translate('shared.save');
|
|
300
106
|
}
|
|
301
107
|
|
|
302
|
-
|
|
303
|
-
|
|
108
|
+
// With params
|
|
109
|
+
getCountLabel(count: number): string {
|
|
110
|
+
return this.translate.translate('items.count', { count });
|
|
304
111
|
}
|
|
305
|
-
}
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
---
|
|
309
|
-
|
|
310
|
-
## Components
|
|
311
112
|
|
|
312
|
-
|
|
113
|
+
// Signal-based — updates automatically on language change
|
|
114
|
+
readonly pageTitle = this.translate.translateSignal('dashboard.title');
|
|
313
115
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<!-- Rendered automatically in AppTopbar when provideLocalization() is called -->
|
|
318
|
-
<!-- Manual embedding: -->
|
|
319
|
-
<flusys-language-selector />
|
|
116
|
+
// Read current language code
|
|
117
|
+
readonly lang = this.translate.languageCode; // Signal<string>
|
|
118
|
+
}
|
|
320
119
|
```
|
|
321
120
|
|
|
322
|
-
|
|
323
|
-
- Shows current language flag + name
|
|
324
|
-
- Dropdown lists all active languages
|
|
325
|
-
- Switches language and reloads translations on selection
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Route Resolver
|
|
330
|
-
|
|
331
|
-
Use the route resolver to ensure translations are loaded before a route renders:
|
|
121
|
+
## 5. Add Admin Routes (Language and Key Management)
|
|
332
122
|
|
|
333
123
|
```typescript
|
|
334
|
-
import { localizationResolver } from '@flusys/ng-localization';
|
|
335
|
-
|
|
336
124
|
// app.routes.ts
|
|
125
|
+
import { LOCALIZATION_ROUTES } from '@flusys/ng-localization';
|
|
126
|
+
|
|
337
127
|
export const routes: Routes = [
|
|
338
128
|
{
|
|
339
|
-
path: '',
|
|
340
|
-
|
|
341
|
-
children: [
|
|
342
|
-
// Routes that need translations pre-loaded
|
|
343
|
-
],
|
|
129
|
+
path: 'localization',
|
|
130
|
+
loadChildren: () => LOCALIZATION_ROUTES,
|
|
344
131
|
},
|
|
345
132
|
];
|
|
346
133
|
```
|
|
347
134
|
|
|
348
|
-
The resolver calls `TranslateService.reloadTranslations()` if translations are stale or not yet loaded for the current language.
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
|
|
352
135
|
## RTL Support
|
|
353
136
|
|
|
354
|
-
When
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
// Internal behavior (automatic)
|
|
358
|
-
document.documentElement.dir = language.isRtl ? 'rtl' : 'ltr';
|
|
359
|
-
document.documentElement.lang = language.code;
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
Tailwind CSS RTL classes (`rtl:`, `ltr:`) work automatically once the `dir` attribute is set.
|
|
363
|
-
|
|
364
|
-
PrimeNG also supports RTL via the `dir` attribute on the document root — no extra configuration needed.
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
|
-
## TRANSLATE_ADAPTER Token
|
|
369
|
-
|
|
370
|
-
`TRANSLATE_ADAPTER` is defined in `@flusys/ng-core`. All packages that use `TranslatePipe` or need translation access inject this token — not `TranslateService` directly. This keeps them independent of `ng-localization`.
|
|
371
|
-
|
|
372
|
-
```typescript
|
|
373
|
-
// Defined in ng-core
|
|
374
|
-
import { TRANSLATE_ADAPTER, ITranslateAdapter } from '@flusys/ng-core';
|
|
375
|
-
|
|
376
|
-
// ITranslateAdapter interface
|
|
377
|
-
interface ITranslateAdapter {
|
|
378
|
-
translate(key: string, params?: Record<string, string | number>): string;
|
|
379
|
-
currentLanguage: Signal<ILanguage>;
|
|
380
|
-
setLanguage(code: string): Observable<void>;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// ng-localization provides the implementation:
|
|
384
|
-
// provideLocalization() → { provide: TRANSLATE_ADAPTER, useClass: TranslateService }
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
## API Endpoints
|
|
390
|
-
|
|
391
|
-
| Method | Endpoint | Description |
|
|
392
|
-
|--------|----------|-------------|
|
|
393
|
-
| POST | `/localization/language/get-all` | List all languages |
|
|
394
|
-
| POST | `/localization/language/get/:id` | Get language by ID |
|
|
395
|
-
| POST | `/localization/language/insert` | Add language |
|
|
396
|
-
| POST | `/localization/language/update` | Update language |
|
|
397
|
-
| POST | `/localization/language/delete` | Delete language |
|
|
398
|
-
| POST | `/localization/translation/get-all` | List translations |
|
|
399
|
-
| POST | `/localization/translation/get-by-language` | Get all keys for a language |
|
|
400
|
-
| POST | `/localization/translation/insert` | Add translation key |
|
|
401
|
-
| POST | `/localization/translation/update` | Update translation value |
|
|
402
|
-
| POST | `/localization/translation/delete` | Delete translation key |
|
|
403
|
-
| POST | `/localization/translation/bulk-update` | Atomic bulk update |
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
## Configuration Reference
|
|
408
|
-
|
|
409
|
-
| Config Key | Type | Default | Description |
|
|
410
|
-
|------------|------|---------|-------------|
|
|
411
|
-
| `services.localization.enabled` | `boolean` | `false` | Enable localization module |
|
|
412
|
-
|
|
413
|
-
Default language is configured server-side in `nestjs-localization` via `ILanguage.isDefault`.
|
|
414
|
-
|
|
415
|
-
---
|
|
416
|
-
|
|
417
|
-
## Troubleshooting
|
|
418
|
-
|
|
419
|
-
**TranslatePipe shows raw key (e.g., `common.save`)**
|
|
420
|
-
|
|
421
|
-
Possible causes:
|
|
422
|
-
1. `provideLocalization()` is missing from `app.config.ts`
|
|
423
|
-
2. The key doesn't exist in the database for the current language
|
|
424
|
-
3. Translations failed to load — check network tab for `POST /localization/translation/get-by-language`
|
|
425
|
-
|
|
426
|
-
**APP_INITIALIZER delays app startup**
|
|
427
|
-
|
|
428
|
-
Translations are loaded before the first render. For large translation sets, this adds startup time. Consider splitting translations by module and using the route resolver for lazy loading.
|
|
429
|
-
|
|
430
|
-
**Language switch doesn't update all components**
|
|
431
|
-
|
|
432
|
-
`TranslatePipe` is signal-reactive. If a component uses raw `translate.get()` (synchronous call, not pipe), it won't auto-update. Use `{{ key | translate }}` in templates instead.
|
|
433
|
-
|
|
434
|
-
**RTL layout not applying**
|
|
435
|
-
|
|
436
|
-
Ensure Tailwind CSS is configured for RTL classes. Add to `tailwind.config.js`:
|
|
437
|
-
|
|
438
|
-
```javascript
|
|
439
|
-
module.exports = {
|
|
440
|
-
// Tailwind reads dir from document root automatically
|
|
441
|
-
// No extra config needed for rtl: classes
|
|
442
|
-
};
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
**`No provider for TRANSLATE_ADAPTER`**
|
|
446
|
-
|
|
447
|
-
Add `provideLocalization()` to `app.config.ts` providers.
|
|
448
|
-
|
|
449
|
-
**Missing translations after adding new keys**
|
|
450
|
-
|
|
451
|
-
Call `TranslateService.reloadTranslations()` or navigate away and back (triggers the route resolver). In-memory translations are cached until the next load.
|
|
452
|
-
|
|
453
|
-
---
|
|
137
|
+
When the user switches to an RTL language, `LocalizationStateService` sets `document.documentElement.dir` and `lang` automatically. Tailwind `rtl:` utility classes and PrimeNG RTL support both activate from this single attribute change — no extra configuration needed.
|
|
454
138
|
|
|
455
139
|
## License
|
|
456
140
|
|