6.0 KiB
Hybrid Localization
Hybrid localization lets you combine backend localizations (from the ABP server) with UI localizations (JSON files in your Angular app). UI values take priority over backend values for the same key, so you can override or extend server-side texts without changing the backend.
How It Works
- Backend localizations: Loaded from the server (e.g.
ApplicationLocalizationResourceDto). Keys use the formatResourceName::Key. - UI localizations: Loaded from static JSON files under your app's assets (e.g.
/assets/localization/en.json). The same key formatResourceName::Keyis used. - Priority: When a key exists in both backend and UI, the UI value is used (UI overrides backend).
The existing abpLocalization pipe and localization APIs work unchanged; they resolve keys from the merged set (backend + UI), with UI winning on conflicts.
Configuration
Enable hybrid localization in your app config via provideAbpCore and withOptions:
// app.config.ts
import { provideAbpCore, withOptions } from '@abp/ng.core';
export const appConfig: ApplicationConfig = {
providers: [
provideAbpCore(
withOptions({
// ...other options
uiLocalization: {
enabled: true,
basePath: '/assets/localization', // optional; default is '/assets/localization'
},
}),
),
// ...
],
};
| Option | Description | Default |
|---|---|---|
enabled |
Turn on UI localization loading from {basePath}/{culture}.json. |
— |
basePath |
Base path for JSON files. Files are loaded from {basePath}/{culture}.json. |
'/assets/localization' |
When enabled is true, the app loads a JSON file for the current language (e.g. en, tr) whenever the user changes language. Loaded data is merged with backend localizations (UI overrides backend for the same key).
UI Localization File Format
Place one JSON file per culture under your basePath. File name must be {culture}.json (e.g. en.json, tr.json).
Structure: resource name → key → value.
{
"MyProjectName": {
"Welcome": "Welcome from UI (en.json)",
"CustomKey": "This is a UI-only localization",
"TestMessage": "UI localization is working!"
},
"AbpAccount": {
"Login": "Sign In (UI Override)"
}
}
- Top-level keys are resource names (e.g.
MyProjectName,AbpAccount). - Nested keys are localization keys; values are the display strings for that culture.
In templates you keep using the same key format: ResourceName::Key.
Using in Templates
Use the abpLocalization pipe as usual. Keys can come from backend only, UI only, or both (UI wins):
<!-- Backend (if available) or UI -->
<p>{{ 'MyProjectName::Welcome' | abpLocalization }}</p>
<!-- UI-only key (from /assets/localization/{{ culture }}.json) -->
<p>{{ 'MyProjectName::CustomKey' | abpLocalization }}</p>
<!-- Backend key overridden by UI -->
<p>{{ 'AbpAccount::Login' | abpLocalization }}</p>
No template changes are needed; only the configuration and the JSON files.
UILocalizationService
The UILocalizationService (@abp/ng.core) manages UI localizations and merges them with backend data.
Get loaded UI data
To inspect what was loaded from the UI JSON files (e.g. for debugging or display):
import { UILocalizationService, SessionStateService } from '@abp/ng.core';
export class MyComponent {
private uiLocalizationService = inject(UILocalizationService);
private sessionState = inject(SessionStateService);
currentLanguage$ = this.sessionState.getLanguage$();
ngOnInit() {
// All loaded UI resources for current language
const loaded = this.uiLocalizationService.getLoadedLocalizations();
// Or for a specific culture
const loadedEn = this.uiLocalizationService.getLoadedLocalizations('en');
}
}
getLoadedLocalizations(culture?: string) returns an object of the form { [resourceName: string]: Record<string, string> } for the given culture (or current language if omitted).
Add translations at runtime
You can also add or merge UI translations programmatically (e.g. from another source or lazy-loaded module):
this.uiLocalizationService.addAngularLocalizeLocalization(
'en', // culture
'MyProjectName', // resource name
{ MyKey: 'My value' }, // key-value map
);
This merges into the existing UI localizations and is taken into account by the abpLocalization pipe with the same UI-over-backend priority.
Example: Dev App
The ABP dev app demonstrates hybrid localization:
- Config (
app.config.ts):
uiLocalization: {
enabled: true,
basePath: '/assets/localization',
},
-
Files:
src/assets/localization/en.jsonandsrc/assets/localization/tr.jsonwith the structure shown above. -
Component (
localization-test.component.ts): UsesabpLocalizationfor backend keys, UI-only keys, and overrides; and usesUILocalizationService.getLoadedLocalizations()to show loaded UI data.
See apps/dev-app/src/app/localization-test/localization-test.component.ts and apps/dev-app/src/assets/localization/*.json in the repository for the full example.
Summary
| Topic | Description |
|---|---|
| Purpose | Combine backend and UI localizations; UI overrides backend for the same key. |
| Config | provideAbpCore(withOptions({ uiLocalization: { enabled: true, basePath?: string } })). |
| File location | {basePath}/{culture}.json (e.g. /assets/localization/en.json). |
| JSON format | { "ResourceName": { "Key": "Value", ... }, ... }. |
| Template usage | Same as before: {{ 'ResourceName::Key' | abpLocalization }}. |
| API | UILocalizationService: getLoadedLocalizations(culture?), addAngularLocalizeLocalization(culture, resourceName, translations). |