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
Serializers for generating translation files in multiple formats: XLIFF, XLIFF2, XMB, and XTB.
Generates XLIFF 1.2 format translation files, the default format used by Angular i18n.
/**
* Generates XLIFF 1.2 format translation file content
* @param messages - Array of i18n messages to serialize
* @param locale - Target locale for the translation file
* @param existingNodes - Optional existing XML nodes to merge with
* @returns XLIFF XML content as string
*/
function xliffWrite(
messages: i18n.Message[],
locale: string | null,
existingNodes?: xml.Node[]
): string;
/**
* Loads XLIFF content and converts to i18n messages
* @param content - XLIFF XML content string
* @returns Object mapping message IDs to translated strings
*/
function xliffLoadToI18n(content: string): I18nMessagesById;
/**
* Loads XLIFF content to XML nodes
* @param content - XLIFF XML content string
* @returns Object mapping message IDs to XML nodes
*/
function xliffLoadToXml(content: string): XmlMessagesById;
/**
* Generates digest/hash for XLIFF message identification
* @param message - Message to generate digest for
* @returns Message digest string
*/
function xliffDigest(message: i18n.Message): string;Generates XLIFF 2.0/2.1 format translation files with improved features and structure.
/**
* Generates XLIFF 2.0 format translation file content
* @param messages - Array of i18n messages to serialize
* @param locale - Target locale for the translation file
* @param existingNodes - Optional existing XML nodes to merge with
* @returns XLIFF2 XML content as string
*/
function xliff2Write(
messages: i18n.Message[],
locale: string | null,
existingNodes?: xml.Node[]
): string;
/**
* Loads XLIFF2 content and converts to i18n messages
* @param content - XLIFF2 XML content string
* @returns Object mapping message IDs to translated strings
*/
function xliff2LoadToI18n(content: string): I18nMessagesById;
/**
* Loads XLIFF2 content to XML nodes
* @param content - XLIFF2 XML content string
* @returns Object mapping message IDs to XML nodes
*/
function xliff2LoadToXml(content: string): XmlMessagesById;
/**
* Generates digest/hash for XLIFF2 message identification
* @param message - Message to generate digest for
* @returns Message digest string
*/
function xliff2Digest(message: i18n.Message): string;Generates XMB (XML Message Bundle) format files, Angular's internal message bundle format.
/**
* Generates XMB format translation file content
* @param messages - Array of i18n messages to serialize
* @param locale - Target locale for the translation file
* @param existingNodes - Optional existing XML nodes to merge with
* @returns XMB XML content as string
*/
function xmbWrite(
messages: i18n.Message[],
locale: string | null,
existingNodes?: xml.Node[]
): string;
/**
* Loads XMB content to XML nodes
* @param content - XMB XML content string
* @returns Object mapping message IDs to XML nodes
*/
function xmbLoadToXml(content: string): XmlMessagesById;
/**
* Generates digest/hash for XMB message identification
* @param message - Message to generate digest for
* @returns Message digest string
*/
function xmbDigest(message: i18n.Message): string;
/**
* Creates placeholder mapper for XMB format
* @param message - Message to create mapper for
* @returns Placeholder mapper instance
*/
function xmbMapper(message: i18n.Message): PlaceholderMapper;Handles XTB (XML Translation Bundle) format, used for translated message files.
/**
* Loads XTB content and converts to i18n messages
* @param content - XTB XML content string
* @returns Object mapping message IDs to translated strings
*/
function xtbLoadToI18n(content: string): I18nMessagesById;
/**
* Generates digest/hash for XTB message identification
* @param message - Message to generate digest for
* @returns Message digest string
*/
function xtbDigest(message: i18n.Message): string;
/**
* Creates placeholder mapper for XTB format
* @param message - Message to create mapper for
* @returns Placeholder mapper instance
*/
function xtbMapper(message: i18n.Message): PlaceholderMapper;Common utilities used across all serializer formats.
/**
* Serializes HTML nodes to string with locale-specific formatting
* @param nodes - HTML nodes to serialize
* @param locale - Target locale string
* @param params - Interpolation parameters
* @returns Array of serialized node strings
*/
function serializeNodes(
nodes: html.Node[],
locale: string,
params: {[key: string]: any}
): string[];
/**
* Default placeholder mapper implementation
*/
class SimplePlaceholderMapper implements PlaceholderMapper {
constructor(message: i18n.Message, placeholderNames: string[]);
toPublicName(internalName: string): string | null;
toInternalName(publicName: string): string | null;
}| Feature | XLIFF 1.2 | XLIFF 2.0 | XMB | XTB |
|---|---|---|---|---|
| Use Case | Standard translation exchange | Modern translation exchange | Angular source messages | Angular translated messages |
| File Extension | .xlf | .xlf2 | .xmb | .xtb |
| Angular Default | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Industry Standard | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
| Translation Memory | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
| Metadata Support | ✅ Good | ✅ Excellent | ✅ Basic | ✅ Basic |
import { xliffWrite } from "@ngx-translate/i18n-polyfill/serializers";
import { MessageBundle } from "@ngx-translate/i18n-polyfill/extractor";
// Create message bundle and add messages
const bundle = new MessageBundle("en");
bundle.updateFromTemplate("Hello {{name}}", "app.component.ts");
bundle.updateFromTemplate({
value: "Welcome to our app",
id: "welcome.message",
description: "Main welcome message"
}, "app.component.ts");
// Generate XLIFF content
const messages = bundle.getMessages();
const xliffContent = xliffWrite(messages, "en");
console.log(xliffContent);
// Output: XLIFF XML with translation unitsimport { xliffLoadToI18n, xliffWrite } from "@ngx-translate/i18n-polyfill/serializers";
// Load existing translations
const existingTranslations = xliffLoadToI18n(existingXliffContent);
// Add new messages and merge
const newMessages = extractedMessagesFromCode;
const mergedContent = xliffWrite(newMessages, "en", existingNodes);import { xliffWrite, xliff2Write, xmbWrite } from "@ngx-translate/i18n-polyfill/serializers";
// Export same messages to different formats
const messages = bundle.getMessages();
const xliffOutput = xliffWrite(messages, "en");
const xliff2Output = xliff2Write(messages, "en");
const xmbOutput = xmbWrite(messages, "en");
// Save to different files
fs.writeFileSync("messages.xlf", xliffOutput);
fs.writeFileSync("messages.xlf2", xliff2Output);
fs.writeFileSync("messages.xmb", xmbOutput);Each format uses digest functions to generate unique identifiers for messages:
import { xliffDigest, xliff2Digest, xmbDigest } from "@ngx-translate/i18n-polyfill/serializers";
const message = createI18nMessage("Hello {{name}}", "greeting");
const xliffId = xliffDigest(message); // e.g., "2345678901234567890"
const xliff2Id = xliff2Digest(message); // e.g., "3456789012345678901"
const xmbId = xmbDigest(message); // e.g., "4567890123456789012"XMB and XTB formats use placeholder mappers to handle interpolation parameters:
import { xmbMapper, xtbMapper } from "@ngx-translate/i18n-polyfill/serializers";
const message = createI18nMessage("Hello {{name}}, you have {{count}} items");
const mapper = xmbMapper(message);
// Map internal placeholder names to public names
const publicName = mapper.toPublicName("INTERPOLATION"); // "name"
const internalName = mapper.toInternalName("count"); // "INTERPOLATION_1"