| name | skill-translate |
| description | AL translation and localization for Business Central. Use when working with XLF files, NAB tools, or implementing multi-language support in extensions. |
Skill: AL Translation Management
Purpose
Manage multilingual translations for AL extensions using XLF files: create and refresh language files, batch-translate with NAB AL Tools, preserve placeholders, enforce character limits, maintain terminology consistency, and implement quality review workflows.
When to Load
This skill should be loaded when:
- A new target language needs to be added to an AL extension
- Untranslated texts need to be translated after code changes
- Translation quality review is needed (placeholder validation, character limits)
- Regional language variations must be managed (es-ES vs es-MX)
- Incremental translation is required after refreshing XLF files
Core Patterns
Pattern 1: Create Language File
Create a new XLF translation file from the generated source:
createLanguageXlf
generatedXlfFilePath: "Translations/MyApp.g.xlf"
targetLanguageCode: "es-ES"
matchBaseAppTranslation: true // pre-populate from Microsoft base translations
Rules:
- The
.g.xlf file is auto-generated by the AL compiler — never edit it manually
matchBaseAppTranslation: true copies existing Microsoft translations for standard terms
- One language file per locale:
MyApp.es-ES.xlf, MyApp.fr-FR.xlf, etc.
Pattern 2: Refresh and Retrieve Texts
After code changes, sync the language file and get new untranslated texts:
// Step 1: Refresh — adds new entries, preserves existing translations
refreshXlf
generatedXlfFilePath: "Translations/MyApp.g.xlf"
filePath: "Translations/MyApp.es-ES.xlf"
// Step 2: Get untranslated texts with context
getTextsToTranslate
filePath: "Translations/MyApp.es-ES.xlf"
limit: 50
offset: 0
Each text entry includes:
id — unique identifier for the translation unit
source — original text to translate
type — context: Table Customer - Field Name - Property Caption
maxLength — character limit (if set in AL source)
comments — notes about placeholders (%1, %2)
Pattern 3: Batch Translation
Translate multiple texts in a single operation:
saveTranslatedTexts
filePath: "Translations/MyApp.es-ES.xlf"
translations: [
{
"id": "Table_ContosoProject_Field_Description_Caption",
"targetText": "Descripción",
"targetState": "translated"
},
{
"id": "Page_ContosoProjectCard_Action_Release_Caption",
"targetText": "Lanzar",
"targetState": "translated"
},
{
"id": "Codeunit_ContosoMgt_Error_CustomerNotFound",
"targetText": "Cliente %1 no encontrado.",
"targetState": "translated"
}
]
Translation rules:
- Preserve placeholders —
%1, %2, %3 must appear in the same order
- Respect
maxLength — abbreviate if needed, never exceed
- Match context — same English word may have different translations depending on
type
- Follow Microsoft terminology — use base app translations for standard BC terms
Pattern 4: Translation Quality Review
Use translation states to implement a review workflow:
| State | Meaning | Who |
|---|
translated | Initial translation done | Translator |
needs-review-translation | Flagged for review | Translator / QA |
final | Reviewed and approved | Reviewer |
signed-off | Production-ready | Language lead |
// Find texts needing review
getTranslatedTextsByState
filePath: "Translations/MyApp.es-ES.xlf"
translationStateFilter: "needs-review-translation"
limit: 0
// After review, promote to final
saveTranslatedTexts
filePath: "Translations/MyApp.es-ES.xlf"
translations: [
{ "id": "...", "targetText": "...", "targetState": "final" }
]
Common quality issues:
// Issue 1: Missing placeholder
❌ Source: "Posted %1 of %2"
❌ Translation: "Registrado %2" // missing %1
✅ Translation: "Registrado %1 de %2"
// Issue 2: Character limit exceeded
❌ Source: "Post" (maxLength: 10)
❌ Translation: "Registrar y contabilizar" // 25 chars
✅ Translation: "Registrar" // 9 chars
// Issue 3: Context-dependent meaning
Source: "Post"
Context: Action caption → "Registrar" ✅
Context: Table name → "Correo" ✅ (different meaning!)
Pattern 5: Translation Memory and Glossary
Use existing translations for consistency:
// Get all translated texts as a reference map
getTranslatedTextsMap
filePath: "Translations/MyApp.es-ES.xlf"
limit: 0
// Search for specific terms across translations
getTextsByKeyword
filePath: "Translations/MyApp.es-ES.xlf"
keyword: "Customer|Vendor|Invoice"
isRegex: true
caseSensitive: false
searchInTarget: true
Glossary approach:
- Before translating a batch, retrieve existing translations with
getTranslatedTextsMap
- Search for related terms with
getTextsByKeyword to ensure consistent terminology
- Standard BC terms should match Microsoft's official base app translations
Pattern 6: Regional Variations
Manage locale-specific translations (e.g., es-ES vs es-MX):
// Step 1: Create base translation (es-ES)
createLanguageXlf
generatedXlfFilePath: "Translations/MyApp.g.xlf"
targetLanguageCode: "es-ES"
matchBaseAppTranslation: true
// Step 2: Create regional variant from base
createLanguageXlf
generatedXlfFilePath: "Translations/MyApp.g.xlf"
targetLanguageCode: "es-MX"
matchBaseAppTranslation: true
// Step 3: Get base translations as reference
getTranslatedTextsMap
filePath: "Translations/MyApp.es-ES.xlf"
limit: 0
// Step 4: Copy base, then adjust regional terms
// "Ordenador" (es-ES) → "Computadora" (es-MX)
// "Factura" stays the same in both
Workflow
Step 1: Setup
- Build the extension to generate the
.g.xlf file: Bash: al compile
- Create language file for each target locale (Pattern 1)
- If language files already exist, refresh them (Pattern 2)
Step 2: Translate
- Retrieve untranslated texts with
getTextsToTranslate (paginate with limit/offset)
- Check translation memory for consistency (Pattern 5)
- Translate in batches of 20-50 items (Pattern 3)
- Save progress frequently — use
targetState: "translated"
Step 3: Review
- Retrieve texts by state:
getTranslatedTextsByState with "translated" filter
- Validate:
- All placeholders preserved (
%1, %2, etc.)
- Character limits respected
- Context-appropriate translations
- Consistent terminology across the extension
- Mark reviewed texts:
targetState: "needs-review-translation" → "final"
Step 4: Finalize
- Verify no untranslated texts remain:
getTextsToTranslate with limit: 0
- Promote all
final texts to signed-off
- Build the extension to verify XLF integration:
Bash: al compile
- Test the UI in the target language
Common Language Codes
| Code | Language | Code | Language |
|---|
es-ES | Spanish (Spain) | fr-FR | French (France) |
es-MX | Spanish (Mexico) | fr-CA | French (Canada) |
de-DE | German | pt-BR | Portuguese (Brazil) |
it-IT | Italian | nl-NL | Dutch |
da-DK | Danish | sv-SE | Swedish |
nb-NO | Norwegian | fi-FI | Finnish |
pl-PL | Polish | cs-CZ | Czech |
ja-JP | Japanese | zh-CN | Chinese (Simplified) |
References
Constraints
- This skill covers XLF translation management, batch translation, and quality review workflows
- Do NOT edit
.g.xlf files manually — they are compiler-generated
- Do NOT remove or reorder placeholders (
%1, %2) in translations
- Do NOT exceed
maxLength character limits defined in AL source
- Do NOT translate without checking existing translation memory first (consistency)
- Translation testing in UI →
skill-testing.md | Page captions and tooltips → skill-pages.md