A speculative polyfill to support i18n code translations in Angular
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Injectable Angular service that provides synchronous code-based translations using translation files in various formats (XLIFF, XLIFF2, XTB).
The main translation service that returns a callable function for performing translations.
/**
* Injectable Angular service for i18n code translations
* Returns a function that translates strings synchronously
*/
@Injectable()
class I18n {
constructor(
@Inject(TRANSLATIONS_FORMAT) format: string,
@Inject(TRANSLATIONS) translations: string,
@Inject(LOCALE_ID) locale: string,
@Optional()
@Inject(MISSING_TRANSLATION_STRATEGY)
missingTranslationStrategy?: MissingTranslationStrategy
);
}
interface I18n {
(def: string | I18nDef, params?: {[key: string]: any}): string;
}Parameters:
format - Translation file format: "xlf", "xlf2", "xliff", "xliff2", or "xtb"translations - Translation file content as stringlocale - Target locale stringmissingTranslationStrategy - Optional strategy for handling missing translations (default: Warning)Usage: The service constructor returns a function that can be called to translate strings. The function accepts either a simple string or an I18nDef object with metadata, plus optional interpolation parameters.
The function returned by the I18n service constructor.
/**
* Translates a string or I18nDef object
* @param def - String to translate or I18nDef object with metadata
* @param params - Optional interpolation parameters
* @returns Translated string with interpolations applied
*/
(def: string | I18nDef, params?: {[key: string]: any}): string;Examples:
import { I18n } from "@ngx-translate/i18n-polyfill";
@Component({...})
export class MyComponent {
constructor(private i18n: I18n) {}
translateStrings() {
// Simple string translation
const hello = this.i18n("Hello world");
// Translation with interpolation
const greeting = this.i18n("Hello {{name}}", { name: "John" });
// Translation with metadata
const message = this.i18n({
value: "Hello {{name}}",
id: "greeting.hello",
meaning: "A friendly greeting",
description: "Greeting message shown to users"
}, { name: "John" });
// ICU expressions
const pluralMessage = this.i18n(
"Updated {count, plural, =0 {no items} =1 {one item} other {{{count}} items}}",
{ count: 5 }
);
}
}The I18n service integrates with Angular's dependency injection system and requires several providers:
import { NgModule } from "@angular/core";
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID, MissingTranslationStrategy } from "@angular/core";
import { I18n, MISSING_TRANSLATION_STRATEGY } from "@ngx-translate/i18n-polyfill";
// Load translation file content
const translationFileContent = require("raw-loader!../locale/messages.fr.xlf");
@NgModule({
providers: [
I18n,
{ provide: TRANSLATIONS, useValue: translationFileContent },
{ provide: TRANSLATIONS_FORMAT, useValue: "xlf" },
{ provide: LOCALE_ID, useValue: "fr" },
{ provide: MISSING_TRANSLATION_STRATEGY, useValue: MissingTranslationStrategy.Warning }
]
})
export class AppModule {}For dynamic locale loading using a factory provider:
@NgModule({
providers: [
I18n,
{
provide: TRANSLATIONS,
useFactory: (locale: string) => {
locale = locale || 'en';
return require(`raw-loader!../locale/messages.${locale}.xlf`);
},
deps: [LOCALE_ID]
},
{ provide: TRANSLATIONS_FORMAT, useValue: "xlf" },
{ provide: LOCALE_ID, useValue: "fr" }
]
})
export class AppModule {}{{paramName}} syntax{param, plural, ...} and {param, select, ...}The service throws errors for:
Missing translations are handled based on the configured MissingTranslationStrategy:
Ignore: Return the source text without warningsWarning: Log warnings and return source text (default)Error: Throw an error for missing translations