@labeleer/translation-dataset-transformers
v2.2.3
Published
Utility parser methods used by all Labeleer tools
Readme
Labeleer Translation Dataset Transformers
Parse and serialize translation datasets across a wide range of localization
file formats through a single, standardized intermediate representation — the
TranslationDataset. Every supported format parses into a
TranslationDataset and serializes out of one, so any format can be
converted to any other.
Getting Started
npm install @labeleer/translation-dataset-transformersThe package is published as ES modules ("type": "module") with bundled type
declarations.
Usage
The primary entry point is defaultTransformerSet — a ready-made
ParserSet wired up with every supported format. It exposes
synchronous parse, parseAggregate and serialize methods.
Parsing a dataset
Parse a string into a standardized TranslationDataset. The format is selected
via the FileFormat enum.
import {
defaultTransformerSet,
FileFormat,
} from '.labeleer/translation-dataset-transformer.js';
const jsonString = `{
"hello_world": {
"translations": {
"en_US": "Hello World!",
"nl_NL": "Hallo Wereld!"
}
}
}`;
const dataset = defaultTransformerSet.parse(
jsonString,
FileFormat.JSON,
{ referenceLocale: 'en_US' }
);
// {
// hello_world: {
// translations: { en_US: 'Hello World!', nl_NL: 'Hallo Wereld!' }
// }
// }Some single-locale formats (Apple .strings, PO, …) carry no locale
information in the file itself and therefore require a targetLocale:
const dataset = defaultTransformerSet.parse(appleStrings, FileFormat.APPLE_STRINGS, {
referenceLocale: 'en_US',
targetLocale: 'nl_NL',
});Parsing multiple locale files at once
Formats that store a single locale per file can be aggregated into one dataset
with parseAggregate, which takes a map of locale → file content:
const dataset = defaultTransformerSet.parseAggregate(
{
en_US: englishStringsFile,
nl_NL: dutchStringsFile,
},
FileFormat.APPLE_STRINGS,
{ referenceLocale: 'en_US' }
);Serializing a dataset
Serialize a TranslationDataset back into files. Unlike a plain
string-returning serializer, serialize returns a
SerializationResult — a map of filename → file
content. Formats that emit one file per locale (Android, Apple, XLIFF, PO, Qt)
return several entries; single-file formats (JSON, YAML, XCStrings) return one.
import {
defaultTransformerSet,
FileFormat,
type TranslationDataset,
} from '.labeleer/translation-dataset-transformer.js';
const dataset: TranslationDataset = {
hello_world: {
translations: { en_US: 'Hello World!', nl_NL: 'Hallo Wereld!' },
},
};
const result = defaultTransformerSet.serialize(dataset, FileFormat.JSON, {
referenceLocale: 'en_US',
locales: ['en_US', 'nl_NL'],
});
// {
// labels: {
// content: '{\n "hello_world": {\n "translations": { ... }\n }\n}'
// }
// }An Android serialization, by contrast, yields one resource file per locale, each flagged as living in its own directory:
const result = defaultTransformerSet.serialize(dataset, FileFormat.ANDROID_STRINGS, {
referenceLocale: 'en_US',
locales: ['en_US', 'nl_NL'],
});
// {
// 'values-en/strings.xml': { content: '<?xml ...>', isDirectory: true },
// 'values-nl/strings.xml': { content: '<?xml ...>', isDirectory: true }
// }Supported Formats
Every format supports both parsing and serialization.
| Format Name | Enum Value | File Extensions |
|-----------------|------------------------------------|------------------|
| JSON | LanguageFileFormat.JSON | .json |
| YAML | LanguageFileFormat.YAML | .yaml, .yml |
| Qt Linguist | LanguageFileFormat.TS | .ts |
| PO (Gettext) | LanguageFileFormat.PO | .po, .pot |
| Android Strings | LanguageFileFormat.ANDROID_STRINGS | .xml |
| Apple Strings | LanguageFileFormat.APPLE_STRINGS | .strings |
| XLIFF (2.1) | LanguageFileFormat.XLIFF | .xliff, .xlf |
| Apple XCStrings | LanguageFileFormat.XCSTRINGS | .xcstrings |
Helpers for working with formats and extensions:
getFormatForExtension(extension)— resolve aFileFormatfrom a file extension.getFileExtensionsFromFormat(format)— list the extensions for a format.supportedFileExtensions()— every extension across all formats.isCompressedFormat(format)— whether a format emits multiple files (and so benefits from being zipped on export).
API
ParserSet
defaultTransformerSet is a ParserSet. You can also build your own over a
subset (or superset) of transformers with makeParserSet([...]).
| Method | Description |
|--------|-------------|
| parse(input, format, options) | Parse a single file's content into a TranslationDataset. |
| parseAggregate(inputs, format, options) | Parse a Partial<Record<Locale, string>> map of per-locale files into one dataset. |
| serialize(dataset, format, options) | Serialize a dataset into a SerializationResult. |
| formats() | List the FileFormats this set supports. |
| has(format) | Type guard: whether the set supports a format. |
| getByFormat(format) | Retrieve the underlying transformer for a format. |
All methods are synchronous.
ParsingOptions
interface ParsingOptions {
/** The locale to treat as the source/base language. */
referenceLocale: Locale;
/**
* The locale a single-locale file should be parsed into. Required by formats
* that do not encode locale information themselves (Apple Strings, PO).
*/
targetLocale?: Locale;
}SerializationOptions
type SerializationOptions = {
/** The source/base language; required by formats such as Android, Apple and Qt. */
referenceLocale: Locale;
/** The locales to include in the output. */
locales: Locale[];
};Locale values are POSIX-style identifiers such as en_US or nl_NL.
SerializationResult
Serialization returns a map keyed by output filename. Multi-file formats populate several entries.
type SerializationResult = {
[filename: string]: {
content: string;
/** True when the file is meant to live in its own directory (e.g. Android `values-*`). */
isDirectory?: boolean;
};
};TranslationDataset
The standardized intermediate representation shared by every format:
type TranslationDataset = {
[key: string]: {
translations: { [locale: string]: string };
tags?: string[];
description?: string;
plurals?: {
[quantity in 'zero' | 'one' | 'two' | 'few' | 'many' | 'other']?: {
[locale: string]: string;
};
};
};
};Dataset keys are sanitized to the [a-zA-Z0-9._-] character set. Individual
transformers additionally expose a formatKey(key) method that adapts a key to
the target format's own identifier rules — for example, the Android transformer
rewrites ./- to _ and guards leading digits so keys are valid resource
names.
Building datasets programmatically
DatasetBuilder provides a fluent API for assembling a TranslationDataset
without hand-writing the nested structure:
import { DatasetBuilder } from '.labeleer/translation-dataset-transformer.js';
const dataset = new DatasetBuilder()
.addTranslation('hello_world', { en_US: 'Hello World!', nl_NL: 'Hallo Wereld!' })
.addDescription('hello_world', 'Greeting shown on the home screen')
.build();Custom transformers
Define a transformer for a new format with makeLanguageTransformer, then
register it in a ParserSet via makeParserSet. A transformer supplies
parse and serialize; parseAggregate, formatKey and canParse are
provided with sensible defaults unless overridden.
