Working with translation files

Business Central is multi-language enabled, which means that you can display the user interface (UI) in different languages. In Business Central, this is done using XLIFF files, which is a standardized format used for computer-based translations.

Tip

Optionally, use the Dynamics 365 Translation Service to get translations for your target languages. For more information, see Translate user interface files.

For an overview of how translations are applied, see Translations overview.

Generating the XLIFF file

To add a new language to the extension that, you've built, first, you must enable the generation of XLIFF files. The XLIFF file extension is .xlf. The generated XLIFF file contains the strings that are specified in properties such as Caption, CaptionML, and Tooltip.

Note

To submit an app to AppSource, you must use XLIFF translation files.

In the app.json file of your extension, add the following line:

  "features": [ "TranslationFile" ]

Note

If the Incremental Build setting is enabled in the AL Language extension configuration then all translations will be ignored, even though the "features": [ "TranslationFile" ] setting is specified in the app.json file. For more information, see AL Language Extension Configuration. The same is true when using RAD publishing, all translations will also be ignored. For more information, see Work with Rapid Application Development.

Now, when you run the build command (Ctrl+Shift+B) in Visual Studio Code, a \Translations folder is generated and populated with the .xlf file that contains all the labels, label properties, and report labels that you're using in the extension. The generated .xlf file can now be translated.

Important

The ML versions of properties are not included in the .xlf file:

The TextConst data type is not included in the .xlf file either.

Important

Make sure to rename the translation file before building the extension next time, as it'll be overwritten.

By setting the GenerateCaptions flag in the app.json file, you specify that you want to generate captions based on the object name for pages, tables, reports, XMLports, and request pages. If the object already has a Caption property set, that value is used. For the table fields, the OptionCaption is used. The syntax is as follows:

  "features": [ "TranslationFile", "GenerateCaptions" ]

GenerateLockedTranslations

APPLIES TO: Business Central 2020 release wave 2 and later

By setting the GenerateLockedTranslations flag in the app.json file, you specify that you want to generate <trans-unit> elements for locked labels in the XLIFF file. The default behavior is that these elements aren't generated. For more information, see JSON Files.

  "features": [ "GenerateLockedTranslations" ]

Label syntax

The label syntax is shown in the example below for the Caption property:

Caption = 'Developer translation for %1',  Comment = '%1 is extension name', locked = false, MaxLength=999; 

Note

The comment, locked, and maxLength attributes are optional and the order isn't enforced. For more information, see Label Data Type.

Use the same syntax for report labels:

labels
{
  LabelName = 'Label Text', Comment='Foo', MaxLength=999, Locked=true;
} 

And the following is the syntax for Label data types:

var
    a : Label 'Label Text', Comment='Foo', MaxLength=999, Locked=true;

The XLIFF file

In the generated .xlf file, you can see a <source> element for each label. For the translation, you'll now have to add the target-language and a <target> element per label. The target-language must be specified in the format "<language code>-<country code>", for example "da-DK", "es-ES", or "de-DE". The <trans-unit id> attribute corresponds to the object ID in the extension. This is illustrated in the example below.

<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
  <file datatype="xml" source-language="en-US" target-language="da-DK" original="ALProject16">
    <body>
      <group id="body">
        <trans-unit id="PageExtension 50110" maxWidth="999" size-unit="char" translate="yes" xml:space="preserve">
          <source>Developer translation for %1</source>
          <target>Udvikleroversættelse for %1</target>
          <note from="Developer" annotates="general" priority="2">%1 is extension name</note>
          <note from="Xliff Generator" annotates="general" priority="3">PageExtension - PageExtension</note>
        </trans-unit>
      </group>
    </body>
  </file>
</xliff>

Note

You can have only one .xlf file per language. If you translate your extension to multiple languages, you must have a translation file per language. There is no enforced naming on the file, but it's a good practice to name it <extensionname>.<language>.xlf.

When the extension is built and published, you can change the language of Dynamics 365 Business Central to view the UI in the translated language.

Translating other extensions

To translate other extensions, for example, when adding translations to the Base Application, you must reference the project to be translated using the dependencies section in the app.json file. For more information, see JSON Files. When the dependencies are set, you can add xliff files in your current project that translates the object captions of the referenced extension. Create a directory named Translations, in the root of the extension, and place the translated xliff file there. When your extension is then built and published, change the language of Dynamics 365 Business Central to view the UI in the translated language.

Note

When translating other extensions, make sure that the attribute original in the <file> element in the xliff file is not set to the name of the current app. Otherwise, translations are only used to translate labels in the same app.

For apps where translations are meant to translate the current app, the generated xliff file will have the correct value of the app name.

Use the <trans-unit id> of the label where it was defined

In order to translate other apps, you must use the <trans-unit id> of the original property, not the one of an extension object as that might have been modified.

If MyPage is defined as:

page 50000 MyPage {
  Caption = 'Base Page'
}

and it has <trans-unit id> for the page corresponding to Page 2931038265 - Property 2879900210.

And if the following page extension of MyPage called MyPageExtension:

pageextension 50000 MyPageExtension extends MyPage
{
    Caption = 'Extension Page';
}

has <trans-unit id> for the page extension corresponding to PageExtension 1716690578 - Property 2879900210, then if you want to change the caption on the page, you must use the ID Page 2931038265 - Property 2879900210, which is the <trans-unit id> of the original property.

Working with labels
Working with multiple AL project folders within one workspace
JSON Files
Translate user interface files using the Dynamics 365 Translation Service