ai-l10n-sdk
v1.7.0
Published
Lightweight SDK for AI-powered localization automation - programmatic API (no CLI)
Maintainers
Readme
ai-l10n-sdk
This is the core SDK package for ai-l10n, providing programmatic access to AI translation capabilities. Use this package when you want to integrate localization functionality into your applications without the CLI tool.
Supports JSON, JSONC, Flutter ARB, Shopify theme files, YAML, PO (gettext), XLIFF, and all other text-based localization formats. The file format is derived from the extension and passed to the API. See the full supported formats list.
Powered by l10n.dev
Installation
npm install ai-l10n-sdkRelated Packages
- ai-l10n-core — Core translation API client, logger interface, and shared types
- ai-l10n — CLI tool built on this SDK
Usage Examples
Basic Translation
import { AiTranslator } from 'ai-l10n-sdk';
const translator = new AiTranslator();
// Basic translation
const result = await translator.translate({
sourceFile: './locales/en.json',
targetLanguages: ['es', 'fr', 'de'],
});
console.log(`Translated to ${result.results.length} languages`);
console.log(`Used ${result.totalCharsUsed} characters`);Update Existing Translations
// Only translate new/changed strings, preserve existing translations
// If targetLanguages is not provided or empty, languages will be auto-detected from project structure
await translator.translate({
sourceFile: './locales/en.json',
translateOnlyNewStrings: true, // Updates existing files
});Advanced Configuration
import { AiTranslator, TranslationConfig } from 'ai-l10n-sdk';
const translator = new AiTranslator();
const config: TranslationConfig = {
sourceFile: './locales/en.json',
targetLanguages: ['es', 'fr', 'de', 'ja', 'zh-CN'],
apiKey: 'your-api-key', // Optional, can use env variable
generatePluralForms: true,
useShortening: false,
useContractions: true,
translateMetadata: false, // Keeps metadata unchanged (default)
saveFilteredStrings: true,
translateOnlyNewStrings: false,
instruction: "Use formal tone",
replace: true, // Replaces existing files, overwise it adds a copy number in the end.
verbose: true,
};
const result = await translator.translate(config);
// Check results
for (const translation of result.results) {
if (translation.success) {
console.log(`✅ ${translation.language}: ${translation.outputPath}`);
} else {
console.log(`❌ ${translation.language}: ${translation.error}`);
}
}Flutter ARB Files
Full support for ARB (Application Resource Bundle) files used in Flutter applications:
const result = await translator.translate({
sourceFile: './lib/l10n/app_en_US.arb',
targetLanguages: ['es_ES', 'fr_FR', 'de']
});ARB Features:
- Automatic Metadata Updates: The API automatically updates
@@localeto the target language code and@@last_modifiedto the current UTC timestamp - Metadata Translation Control: Use
translateMetadata: trueto translate description metadata entries (e.g.,@keydescriptions). By default (false), metadata remains in the source language - Custom Prefixes: Supports custom file naming patterns (e.g.,
app_en_US.arb,my_app_fr.arb)
JSONC Files
Full support for JSONC (JSON with Comments) files:
const result = await translator.translate({
sourceFile: './locales/en.jsonc',
targetLanguages: ['es', 'fr', 'de']
});JSONC Features:
- Works exactly like JSON files but with
.jsoncextension - Auto-detects
.jsoncfiles in project structure alongside.jsonfiles
Shopify Theme Localization
Full support for Shopify theme localization file patterns:
const result = await translator.translate({
sourceFile: './locales/en.default.schema.json',
targetLanguages: ['es-ES', 'fr', 'de']
});
// Creates: es-ES.schema.json, fr.schema.json, de.schema.jsonShopify Theme Features:
- Automatic Pattern Recognition: Detects files with
.default.in the name (e.g.,en.default.schema.json) - Smart Output Naming: Removes
.default.from target files while preserving the.schema.suffix - Language Detection: Auto-detects target languages from existing files (e.g.,
es-ES.schema.json,fr.schema.json)
Other Text-Based Formats (YAML, PO, XLIFF, and more)
The format is derived from the file extension and sent to the API automatically:
// YAML
const result = await translator.translate({
sourceFile: './locales/en.yaml',
targetLanguages: ['es', 'fr', 'de']
});
// PO (gettext)
const result = await translator.translate({
sourceFile: './locales/en.po',
targetLanguages: ['es', 'fr']
});
// XLIFF
const result = await translator.translate({
sourceFile: './locales/en.xliff',
targetLanguages: ['es', 'de']
});For the full list of supported formats see the API documentation.
Multiple Files
const files = ['./locales/en/common.json', './locales/en/admin.json', './locales/en/errors.json'];
for (const file of files) {
await translator.translate({
sourceFile: file,
targetLanguages: ['es', 'fr', 'de'],
});
}Glossary & Terminology
Generate and Save a Glossary
When generateGlossary is enabled, a glossary is built from the source and translated target content and saved as the active glossary for this source/target language pair. It is then used automatically on future translations.
Balance note: Balance is debited for the full source content upfront — even when
translateOnlyNewStringsistrue. When disabled (default), a temporary internal glossary is generated at no extra cost only for content that exceeds the AI chunk size.
const result = await translator.translate({
sourceFile: './locales/en.json',
targetLanguages: ['de', 'fr'],
generateGlossary: true,
});Manage your saved glossaries at l10n.dev/ws/translation-glossary.
Override the Glossary for a Single Request
Supply your own term mappings via glossary. Each GlossaryEntry maps a source term to the preferred target translation with an optional context note.
import { AiTranslator, GlossaryEntry } from 'ai-l10n-sdk';
const glossary: GlossaryEntry[] = [
{ sourceTerm: 'Settings', targetTerm: 'Einstellungen' },
{ sourceTerm: 'bank', targetTerm: 'Bank', context: 'financial institution' },
];
const result = await translator.translate({
sourceFile: './locales/en.json',
targetLanguages: ['de'],
glossary,
});Pass an empty array (glossary: []) to disable the active glossary entirely for this request.
Terminology
Use terminology to enforce consistent term usage. Synonyms listed for each entry are replaced with the preferred term.
import { AiTranslator, TerminologyEntry } from 'ai-l10n-sdk';
const terminology: TerminologyEntry[] = [
{ term: 'Settings', synonyms: ['Preferences', 'Options', 'Configuration'] },
{ term: 'Dashboard' },
];
const result = await translator.translate({
sourceFile: './locales/en.json',
targetLanguages: ['de', 'fr'],
terminology,
});Linguistic Instruction
Use instruction to guide AI the overall style, tone, and translation behavior. Combined with AI Glossaries, they give much more control over localization quality and brand consistency.
Core API
ILogger, ConsoleLogger, L10nTranslationService, and all related types are part of the core library. See ai-l10n-core for full documentation. These are also re-exported from ai-l10n-sdk for convenience.
API Reference
AiTranslator Class
Constructor
import { AiTranslator, ILogger, ConsoleLogger } from 'ai-l10n-sdk';
// Default: uses ConsoleLogger
const translator = new AiTranslator();
// With a custom logger (implements ILogger)
const customLogger: ILogger = new ConsoleLogger();
const translatorWithLogger = new AiTranslator(customLogger);Creates an instance of AiTranslator.
Parameters:
logger?: ILogger— Optional custom logger. Defaults toConsoleLoggerif not provided.
Implementation Details:
- Project Structure Detection: When
targetLanguagesis not specified, the translator automatically detects target languages by scanning the project directory structure (e.g.,locales/en.json,locales/es.json→ detectses) - File Reading: Reads i18n files from the file system using the
sourceFilepath - Results Saving: Automatically saves translated files adjacent to the source file with appropriate language suffixes (e.g.,
en.json→es.json,fr.json) - Incremental Updates: When
translateOnlyNewStrings: true, reads existing target files, merges new translations, and overwrites the files
Notes:
- If apiKey is not provided in TranslationConfig, the SDK uses the L10N_API_KEY environment variable.
Methods
translate(config: TranslationConfig): Promise<TranslationSummary>
Translates a i18n file to one or more target languages.
Parameters:
config: TranslationConfig- Translation configuration object
Returns: Promise<TranslationSummary> - Summary of translation results
Types
TranslationConfig
Configuration options for translation.
interface TranslationConfig {
/**
* Path to the source file to translate.
* Supports JSON, JSONC, ARB, YAML, PO, XLIFF, and all other text-based localization formats.
* The format is derived from the file extension. See the [full supported formats list](https://l10n.dev/ws/translate-i18n-files#supported-formats).
*/
sourceFile: string;
/**
* Target language codes (e.g., ["es", "fr", "de-DE", "zh-Hans-CN"])
* If not provided, will be auto-detected from project structure
*/
targetLanguages?: string[];
/**
* API key for l10n.dev service
* Can also be set via L10N_API_KEY environment variable
*/
apiKey?: string;
/**
* Generates additional plural form strings (e.g., for i18next) with plural suffixes.
* Do not enable for strict source-to-target mapping (default: false)
*/
generatePluralForms?: boolean;
/**
* Use shortening in translations (default: false)
*/
useShortening?: boolean;
/**
* Use contractions in translations (default: true)
*/
useContractions?: boolean;
/**
* Translate metadata along with UI strings (default: false)
* For example, in Flutter ARB files, metadata entries like `@key` contain descriptions
* that can also be translated. Disabling this option ensures that metadata remains
* unchanged in the target files.
*/
translateMetadata?: boolean;
/**
* Save filtered strings to separate file (default: true)
* Filtered strings are in i18n JSON format and contain source strings that violated
* content policies. Review the translation for successfully translated content.
*/
saveFilteredStrings?: boolean;
/**
* If true, update existing files with only new translations
* If false, create new files with unique names (default: false)
*/
translateOnlyNewStrings?: boolean;
/**
* Enable verbose logging (default: false)
*/
verbose?: boolean;
/**
* BCP-47 code of the source language (e.g., "en", "en-US", "zh-Hans-CN").
* If not specified, auto-detected from the source file path.
*/
sourceLanguageCode?: string | null;
/**
* When true, generates a glossary from source and translated target content and saves it as the
* active glossary for this language pair for future translations.
* Balance is debited for the full source content upfront — even when translateOnlyNewStrings is true.
* When false (default), an internal glossary is generated only for large content at no extra cost.
*/
generateGlossary?: boolean;
/**
* Glossary entries to apply during translation.
* null/omitted = use active glossary, [] = disable glossary, entries = replace active for this request.
* Manage saved glossaries at https://l10n.dev/ws/translation-glossary
*/
glossary?: GlossaryEntry[] | null;
/**
* A list of terms for consistent translations. Synonyms are replaced by the preferred term.
*/
terminology?: TerminologyEntry[] | null;
/**
* Linguistic instruction to apply during translation.
* If null or not specified, the active linguistic instruction is used.
* If an empty string is provided, linguistic instruction is disabled.
* If a non-empty string is provided, it replaces the active linguistic instruction for this request.
* Max length: 1000.
**/
instruction?: string | null;
/**
* If true, existing target files will be replaced. If false, new files will be created with unique names (default: false)
*/
replace?: boolean;
}TranslationSummary
Result of a translation operation.
interface TranslationSummary {
/** Whether at least one translation succeeded */
success: boolean;
/** Array of individual translation results */
results: TranslationOutput[];
/** Total characters used across all translations */
totalCharsUsed: number;
/** Remaining character balance (if available) */
remainingBalance?: number;
}TranslationOutput
Result of a single language translation.
interface TranslationOutput {
/** Whether translation succeeded */
success: boolean;
/** Target language code */
language: string;
/** Path to output file (if successful) */
outputPath?: string;
/** Characters used for this translation */
charsUsed?: number;
/** Error message (if failed) */
error?: string;
}GlossaryEntry
Maps a source term to a preferred target translation for use in TranslationConfig.glossary.
interface GlossaryEntry {
/** The term in the source language to be translated. Max length: 255. */
sourceTerm: string;
/** The preferred translation of the term in the target language. Max length: 255. */
targetTerm: string;
/**
* Optional context to clarify the meaning when the term is ambiguous. Max length: 500.
* Example: 'bank' could mean 'financial institution' or 'river bank'.
*/
context?: string | null;
}TerminologyEntry
Specifies a preferred term and disallowed synonyms for use in TranslationConfig.terminology.
interface TerminologyEntry {
/** The preferred term to use in translations. */
term: string;
/** Synonyms that should be replaced by `term`. */
synonyms?: string[];
}I18nProjectManager
Utility class for managing i18n project structure detection, language code validation, and file path generation.
Constructor
import { I18nProjectManager, ILogger, ConsoleLogger } from 'ai-l10n-sdk';
// Default: uses ConsoleLogger
const manager = new I18nProjectManager();
// With a custom logger
const customLogger: ILogger = new ConsoleLogger();
const managerWithLogger = new I18nProjectManager(customLogger);Creates an instance of I18nProjectManager.
Parameters:
logger?: ILogger— Optional custom logger. Defaults toConsoleLoggerif not provided.
Methods
extractLanguageCodeFromPath(sourceFilePath: string): string | null
Extracts the source language code from the file path using project structure detection.
Parameters:
sourceFilePath: string- Path to the source file
Returns: string | null — The detected language code (e.g., "en", "en-US") or null if the structure is unrecognised
Example:
const manager = new I18nProjectManager();
manager.extractLanguageCodeFromPath('./locales/en.json'); // Returns: 'en'
manager.extractLanguageCodeFromPath('./locales/en/common.json'); // Returns: 'en'
manager.extractLanguageCodeFromPath('./lib/l10n/app_en_US.arb'); // Returns: 'en_US'
manager.extractLanguageCodeFromPath('./strings.json'); // Returns: nulldetectLanguagesFromProject(sourceFilePath: string): string[]
Detects target language codes from the project structure by scanning directories and files.
Parameters:
sourceFilePath: string- Absolute path to the source file
Returns: string[] - Array of detected language codes, sorted alphabetically
Behavior:
- Folder-based structure: Scans parent directory for language-named folders (e.g.,
locales/en/,locales/es/) - File-based structure: Scans directory for language-named files (e.g.,
en.json,es.json,app_en.arb) - Automatically excludes the source language from results
- Handles both
.jsonand.jsoncfiles when source is JSON
Example:
const manager = new I18nProjectManager();
const languages = manager.detectLanguagesFromProject('./locales/en.json');
// Returns: ['es', 'fr', 'de']generateTargetFilePath(sourceFilePath: string, targetLanguage: string): string
Generates the target file path for a translated file based on the detected project structure.
Parameters:
sourceFilePath: string- Absolute path to the source filetargetLanguage: string- Target language code (e.g.,"es","fr-FR","zh-Hans-CN")
Returns: string - Absolute path where the translated file should be saved
Behavior:
- Folder-based: Creates
{basePath}/{language}/{filename}(e.g.,locales/es/common.json) - File-based JSON: Creates
{basePath}/{language}{suffix}.{ext}(e.g.,locales/es.schema.json) - File-based ARB: Creates
{basePath}/{prefix}{language}.arb(e.g.,lib/l10n/app_es.arb) - Automatically creates target directories if they don't exist
- Handles Shopify theme patterns (
.default.schema.json→.schema.json) - Converts hyphens to underscores for ARB files
Example:
const manager = new I18nProjectManager();
// Folder-based
manager.generateTargetFilePath('./locales/en/common.json', 'es');
// Returns: './locales/es/common.json'
// File-based JSON
manager.generateTargetFilePath('./locales/en.json', 'es');
// Returns: './locales/es.json'
// File-based ARB
manager.generateTargetFilePath('./lib/l10n/app_en_US.arb', 'es_ES');
// Returns: './lib/l10n/app_es_ES.arb'
// Shopify theme
manager.generateTargetFilePath('./locales/en.default.schema.json', 'es-ES');
// Returns: './locales/es-ES.schema.json'getUniqueFilePath(filePath: string): string
Generates a unique file path by appending a counter if the file already exists.
Parameters:
filePath: string- Desired file path
Returns: string - Unique file path (original or with counter suffix)
Example:
const manager = new I18nProjectManager();
// If 'output.json' doesn't exist
manager.getUniqueFilePath('./output.json');
// Returns: './output.json'
// If 'output.json' exists
manager.getUniqueFilePath('./output.json');
// Returns: './output (1).json'
// If 'output.json' and 'output (1).json' exist
manager.getUniqueFilePath('./output.json');
// Returns: './output (2).json'I18nProjectManager.extractLanguageCodeFromPath usage in AiTranslator
AiTranslator calls extractLanguageCodeFromPath() automatically on each translation to populate sourceLanguageCode in the API request. You can override this by setting sourceLanguageCode explicitly in TranslationConfig.
License
MIT
Credits
Powered by l10n.dev - AI-powered localization service
