Xbox Advanced Technology Group
Updated November 9th, 2017
Localization of package manifest resources
Localizing app name and description
Xbox One supports multiple languages, and titles are encouraged to support different languages as well. Users are provided with a more seamless experience when the language used in their locale is utilized by titles. This white paper details how to localize package manifest resources and in-title resources in exclusive apps and shared apps. It also gives details about the National Language Support (NLS) API supported by Xbox One.
Users can select a language/locale combination during OOBE (out-of-box experience) or later through the Settings app. The languages and locales are tied together in Xbox One. The locale drop-down menu contains only those countries that support the selected language. Changing the selected language changes the locale drop-down menu values.
Table 1. Supported languages (updated June 2015).
| Country | Default Language | Console Locale | Strings Localized | Keyboard Layout | Catalog Strings | Voice Support | Global Voice Commands | Voice Search |
|---|---|---|---|---|---|---|---|---|
| ARGENTINA | Spanish (MX) | es-AR | es-MX | es-MX | es-AR | N/A | N/A | N/A |
| AUSTRALIA | English (GB) | en-AU | en-GB | en-US | en-AU | en-AU | ✓ | ✓ Basic |
| AUSTRIA | German | de-AT | de-DE | de-DE | de-AT | N/A | N/A | N/A |
| BELGIUM | French | fr-BE | fr-FR | fr-FR | fr-BE | N/A | N/A | N/A |
| BELGIUM | Dutch | nl-BE | nl-NL | nl-BE | nl-BE | N/A | N/A | N/A |
| BRAZIL | Portuguese | pt-BR | pt-BR | pt-BR | pt-BR | pt-BR | ✓ | ✓ Basic |
| CANADA | English (GB) | en-CA | en-GB | en-US | en-CA | en-CA | ✓ | ✓ Natural |
| CANADA | French | fr-CA | fr-FR | fr-FR | fr-CA | fr-CA | ✓ | ✓ Basic |
| CHILE | Spanish (MX) | es-CL | es-MX | es-MX | es-CL | N/A | N/A | N/A |
| CHINA | Chinese Simp. | zh-CN | zh-CN | zh-CN | zh-CN | N/A | ✓ (Alpha) | N/A |
| COLOMBIA | Spanish (MX) | es-CO | es-MX | es-MX | es-CO | N/A | N/A | N/A |
| CZECH REPUBLIC | English (GB) | en-CZ | en-GB | en-US | en-CZ | N/A | N/A | N/A |
| DENMARK | Danish | da-DK | da-DK | da-DK | da-DK | N/A | N/A | N/A |
| FINLAND | Finnish | fi-FI | fi-FI | sv-SE | fi-FI | N/A | N/A | N/A |
| FRANCE | French | fr-FR | fr-FR | fr-FR | fr-FR | fr-FR | ✓ | ✓ Natural |
| GERMANY | German | de-DE | de-DE | de-DE | de-DE | de-DE | ✓ | ✓ Natural |
| GREECE | English (GB) | en-GR | en-GB | en-US | en-GR | N/A | N/A | N/A |
| HONG KONG | English (GB) | en-HK | en-GB | en-US | en-HK | N/A | N/A | N/A |
| HONG KONG | Chinese Trad. | zh-HK | zh-TW | zh-HK | zh-HK | N/A | N/A | N/A |
| HUNGARY | English (GB) | en-HU | en-GB | en-US | en-HU | N/A | N/A | N/A |
| INDIA | English (GB) | en-IN | en-GB | en-US | en-IN | N/A | N/A | N/A |
| IRELAND | English (GB) | en-IE | en-GB | en-GB | en-IE | N/A | N/A | N/A |
| ISRAEL | English (GB) | en-IL | en-GB | en-US | en-IL | N/A | N/A | N/A |
| ISRAEL | Hebrew | he-IL | he-IL | he-IL | he-IL | N/A | N/A | N/A |
| ITALY | Italian | it-IT | it-IT | it-IT | it-IT | it-IT | ✓ | ✓ Basic |
| JAPAN | Japanese | ja-JP | ja-JP | ja-JP | ja-JP | ja-JP | ✓ (Beta) | ✓ Basic (Beta) |
| MEXICO | Spanish (MX) | es-MX | es-MX | es-MX | es-MX | es-MX | ✓ | ✓ Basic |
| NETHERLANDS | Dutch | nl-NL | nl-NL | en-US | nl-NL | N/A | N/A | N/A |
| NEW ZEALAND | English (GB) | en-NZ | en-GB | en-GB | en-NZ | N/A | N/A | N/A |
| NORWAY | Norwegian | nb-NO | nb-NO | nb-NO | nb-NO | N/A | N/A | N/A |
| POLAND | Polish | pl-PL | pl-PL | pl-PL | pl-PL | N/A | N/A | N/A |
| PORTUGAL | Portuguese (PT) | pt-PT | pt-PT | pt-PT | pt-PT | N/A | N/A | N/A |
| RUSSIA | Russian | ru-RU | ru-RU | ru-RU | ru-RU | N/A | N/A | N/A |
| SAUDI ARABIA | Arabic (AE) | ar-AE | ar-AE | ar-AE | ar-AE | N/A | N/A | N/A |
| SAUDI ARABIA | English (GB) | en-SA | en-GB | en-US | en-SA | N/A | N/A | N/A |
| SINGAPORE | English (GB) | en-SG | en-GB | en-US | en-SG | N/A | N/A | N/A |
| SINGAPORE | Chinese Simp. | zh-SG | zh-SG | zh-CN | zh-SG | N/A | N/A | N/A |
| SLOVAKIA | English (GB) | en-SK | en-GB | en-US | en-SK | N/A | N/A | N/A |
| SOUTH AFRICA | English (GB) | en-ZA | en-GB | en-US | en-ZA | N/A | N/A | N/A |
| SOUTH KOREA | Korean | ko-KR | ko-KR | ko-KR | ko-KR | N/A | N/A | N/A |
| SPAIN | Spanish (ES) | es-ES | es-ES | es-ES | es-ES | es-ES | ✓ | ✓ Basic |
| SWEDEN | Swedish | sv-SE | sv-SE | sv-SE | sv-SE | N/A | N/A | N/A |
| SWITZERLAND | German | de-CH | de-DE | de-de | de-CH | N/A | N/A | N/A |
| SWITZERLAND | French | fr-CH | fr-FR | fr-ch | fr-CH | N/A | N/A | N/A |
| TAIWAN | Chinese Trad. | zh-TW | zh-TW | zh-TW | zh-TW | N/A | N/A | N/A |
| TURKEY | Turkish | tr-TR | tr-TR | tr-TR | tr-TR | N/A | N/A | N/A |
| UNITED ARAB EMIRATES | English (GB) | en-AE | en-GB | en-US | en-AE | N/A | N/A | N/A |
| UNITED KINGDOM | English (GB) | en-GB | en-GB | en-US | en-GB | en-GB | ✓ | ✓ Natural |
| UNITED STATES | English (US) | en-US | en-US | en-US | en-US | en-US | ✓ | ✓ Natural |
The locale name can be retrieved by using the GetUserDefaultLocaleName() API. The “user” in this case is simply the logged-on session. This API actually retrieves the locale that the console is set in. (Note: This API was ported over from Windows and was not renamed.)
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
int retVal = GetUserDefaultLocaleName( localeName, ARRAYSIZE( localeName ) );
// The value is returned in localeName
The value returned by GetUserDefaultLocaleName() should be used to determine the locale to be used for localizing the game resources. This might be different from the locale selected by the user on the console, as it depends on which languages the game supports and the locale fallback mechanism. A few scenarios are possible, which are described in the following examples.
On his Xbox One, a user selects French for his Language setting, and selects France (fr-FR) for his Country setting. The user locale is fr-FR.
The user has a game that contains the following in the Resources section of the package manifest:
<Resources>
<Resource Language="en-US"/>
<Resource Language="fr-FR"/>
<Resource Language="de-DE"/>
<Resource Language="en-GB"/>
</Resources>
This implies that the game has localized strings/images for English-United States (en-US), French-France (fr-FR), German-Germany (de-DE), and English-Great Britain (en-GB). Because the user’s locale matches a supported locale in the manifest, GetUserDefaultLocaleName() returns the value fr-FR. All the in-game text will be in French (fr-FR).
The return value of GetUserDefaultLocaleName() is fr-FR.
On her Xbox One, a user selects English for her Language setting, and selects UK (en-GB) for her Country setting. The user locale is en-GB.
The user has a game that contains the following in the Resources section of the package manifest:
<Resources>
<Resource Language="en-US"/>
<Resource Language="fr-FR"/>
<Resource Language="de-DE"/>
</Resources>
Because the user’s locale is not present in the manifest, the fallback locale with the same language (English) will be chosen as the default language. In this case, it will be en-US, and so GetUserDefaultLocaleName() returns this value. All the in-game text will be in English (en-US) in this case.
The return value of GetUserDefaultLocaleName() is en-US.
In a scenario similar to the earlier examples, a user’s settings on a console result in a user locale of fr-FR.
The Resources section of the package manifest contains the following:
<Resources>
<Resource Language="en-US"/>
<Resource Language="de-DE"/>
</Resources>
Because the user’s locale is not present in the manifest and no other locale with the same language is present, the first language in the <Resources> tag will be selected as the default language (en-US), and GetUserDefaultLocaleName() returns this value. All the in-game text will be in English (en-US).
The return value of GetUserDefaultLocaleName() is en-US.
To summarize, the locale is returned by the API based on the following:
If your game supports or plans to support Traditional Chinese, your code should be similar to the following:
wchar_t localeName[ LOCALE_NAME_MAX_LENGTH ];
int retVal = GetUserDefaultLocaleName( localeName, ARRAYSIZE( localeName ) );
if (wcscmp(localeName, L"zh-SG") == 0 || wcscmp(localeName, L"zh-CN") == 0)
{
if (wcscmp(localeName, L"zh-SG") == 0)
{
[Preferred localization mapping code to Simplified Chinese from Singapore]
}
else
{
[Traditional Chinese localization mapping code to Simplified Chinese from China mainland]
}
}
else
{
…
[Actual localization mapping code]
}.
The resources (strings and images) used in the package manifest can be localized according to the user’s locale. A resource.pri file, a data file that contains references to images and strings, is automatically created whenever you build the title by using Visual Studio 2012 Update 2 or later. This file is auto-generated and is a specifically named file that the OS looks for. The default resources.pri file, in the absence of resources, contains only the name of the title defined in the package manifest. You can check the contents of this file by using the XDK/ADK command prompt:
MakePri.exe dump /if resources.pri /of out.xml
This command dumps all the resources included in the resources.pri file into an XML format. You can check if all the resources (images and strings) to be localized have been included in this file.
The resources.pri file can be updated to include strings/images for different languages so that the name, splash screens, and logos are in different languages based on the user locale. The following sections give you more details about localizing strings and images by using Visual Studio 2012 Update 2 or later.
All the resources (strings and images) included in the manifest can be localized. The pattern for including localized strings is slightly different from those for images. These are detailed in the following section.
The strings in the manifest can be localized based on the user locale and the locales supported by the title. It is important to provide a default string, which acts as a fallback if the user locale is not supported by the game. This section gives more details about adding default and localized strings to a game, which can then be consumed by the package manifest.
On Windows 8/10
This will create a resources.resx file at the root of your package directory. This file is where you would add your language-independent resource strings. An editing UI will be presented with a default String1 entry that is blank.
On Windows 7
You won’t see the option of adding a resource file if you are running Windows 7. As a workaround, you can use the template file MyTemplate.vstemplate that is included in the .zip file that contains this white paper. Paste the .zip file under C:\Users\
Add AppName with a value. The comments field is a good place to provide instructions to translators who localize the strings to different languages.
Add AppDescription with a value.
Right-click the resources file and then select Properties. Select the Item Type as PRI Resource if it is not already selected. This ensures that the data from this file is written into the resources.pri file.
Update the package manifest to include string references
Referencing the newly added string descriptions is done in the package.appxmanifest file by using the “ms-resource:” syntax. Note that the name used is the same name added in the resource file.
<VisualElements
DisplayName="ms-resource:AppName"
Logo="ATGGraphicsLogo.png"
SmallLogo="ATGSmallLogo.png"
Description="ms-resource:AppDescription"
ForegroundText="dark"
BackgroundColor="#000040">
<SplashScreen Image="ATGSplashScreen.png" />
</VisualElements>
On Windows 8
Repeat this for each additional language that your title supports.
On Windows 7
You won’t see the option of adding a resource file if you are running Windows 7. As a workaround, you can use the template file MyTemplate.vstemplate located at XGD downloads. Paste the file under C:\Users\
Update languages in the package manifest
Add each supported language under the
<Resources>
<Resource Language="en-US"/>
<Resource Language="fr-FR"/>
<Resource Language="de-DE"/>
</Resources>
Update languages in the package manifest to include Traditional Chinese
If your game supports or plans to support Traditional Chinese, either zh-TW or zh-HK will already be in the list. To ensure proper language fallback, add zh-SG and zh-CN to the list as well.
<Resources>
<Resource Language="en"/>
<Resource Language="en-US"/>
<Resource Language="en-GB"/>
<Resource Language="fr"/>
<Resource Language="fr-FR"/>
<Resource Language="de-DE"/>
<Resource Language="ja-JP"/>
<Resource Language="zh-TW"/>
<Resource Language="zh-SG"/>
<Resource Language="zh-CN"/>
</Resources>
Update package manifest to include the strings
Add the string to be localized with the “ms-resource:” tag as shown in the example under Update the package manifest to include string references.
The package manifest has images for Logo, SmallLogo, and SplashScreen. These can be localized for each language. Follow these steps for all localizable images in the package manifest:
Repeat this for each additional language that your title supports.
Create a default image to be used in case the selected language is not supported, for each of Logo, SmallLogo, SplashScreen, and StoreLogo in the root folder of the package. For information about image sizes, see this forum post from the Microsoft Entertainment Developer Forums.
Update the Resources section in the package manifest as shown in the previous example.
Update the image paths in the manifest with the name of the image created. The default image must be present in the root folder of the package. For any language, it will first check for the image file in the particular language folder and use that file if available. Otherwise, if the image is missing from the language folder or the language is not supported (i.e., if the language folder is missing), it defaults to the image file in the root folder.
<VisualElements
DisplayName="ms-resource:AppName"
Logo="ATGGraphicsLogo.png"
SmallLogo="ATGSmallLogo.png"
Description="ms-resource:AppDescription"
ForegroundText="dark"
BackgroundColor="#000040">
<SplashScreen Image="ATGSplashScreen.png" />
</VisualElements>
Note: Instead of creating all the language folders in the root, you can create a folder (for example, Images) and then create the language folders within this folder. The default images will then be present under the Images folder (for example, C:\MyProject\Images). This will help in better organization of images. The title is free to organize resources in any manner. In this case, the paths will be as follows.
<VisualElements
DisplayName="ms-resource:AppName"
Logo="Images\ATGGraphicsLogo.png"
SmallLogo=" Images\ATGSmallLogo.png"
Description="ms-resource:AppDescription"
ForegroundText="dark"
BackgroundColor="#000040">
<SplashScreen Image=" Images\ATGSplashScreen.png" />
</VisualElements>
After all the images and strings are in their respective folders, they are automatically consumed into the resources.pri file. For any language, it will first check for the resources in the particular language folder and use it, if available. Otherwise, if the image is missing from the language folder or the language is not supported (i.e., if the language folder is missing), it picks up the default resource.
Note the difference here between the in-title and package manifest resource localization. In the package manifest, the default resource is used to resolve the strings and images. In the in-title case, however, it is recommended that you use the language returned by the GetUserDefaultLocaleName() API. As mentioned earlier, you can check the contents of the resources.pri file by using the XDK/ADK command prompt:
MakePri.exe dump /if resources.pri /of out.xml
Note: Include at least one image resource with the following values in its Properties: Item Type as Image and Content as Yes. This is necessary to ensure that the localized string is resolved during runtime. Not including this will display the name as “ms-resource:AppName” instead of the resolved name of the title from the resources file.
The chunk layout file should be updated to include the resources.pri file generated as part of the localization process. The resource files need not be included as all the strings from these files are packed in the resources.pri file. However, you have to include all the image files being used in the manifest file. The resources.pri file indicates the path to the image files and doesn’t contain the image itself. Include these image files and the resources.pri file in the launch chunk of the chunk layout file.
<Chunk Id="1000" Marker="Launch">
… (All required files)
<FileGroup DestinationPath="\Images" SourcePath="Images" Include="*.*"/>
<FileGroup DestinationPath="\Images\en-US" SourcePath="Images\en-US" Include="*.*"/>
<FileGroup DestinationPath="\Images\fr-FR" SourcePath="Images\fr-FR" Include="*.*"/>
… (Other language files)
<FileGroup DestinationPath="\" SourcePath="." Include="resources.pri"/>
</Chunk>
… (Other Chunks)
You can tag chunks in your layout file with languages and locales to specify that they contain localized content to be associated only with the specified tag value. Separating localized content reduces installation times for users by installing only the content needed for the language their console is set to. This separation can also reduce iteration times when testing an installation package created with MakePkg.exe, by giving you the option of excluding tagged chunks that aren’t relevant to testing. For example, if you want to test French audio files, you can reduce the time required for an xbapp install command by pushing only the French content files. Consider the following layout file for these examples.
<Chunk Id="1005" Languages="en-US">
<FileGroup DestinationPath="\assets\audio" SourcePath="." Include="en_us_commentary.mp3"/>
</Chunk>
<Chunk Id="1006" Languages="fr-FR">
<FileGroup DestinationPath="\assets\audio" SourcePath="." Include="fr_fr_commentary.mp3"/>
</Chunk>
<Chunk Id="1007" Languages="es-MX">
<FileGroup DestinationPath="\assets\audio" SourcePath="." Include="es_mx_commentary.mp3"/>
</Chunk>
<Chunk Id="1008" Languages="es-MX, en-US">
<FileGroup DestinationPath="\assets" SourcePath="." Include="mixed_content.dat"/>
</Chunk>
Using the Languages tag in your layout file is the only step required to take advantage of intelligent installation.
Note: Intelligent delivery can also make use of several other tags such as OnDemand or Devices. It is beyond the scope of this document to provide a comprehensive overview of intelligent delivery and chunk layout tags. For more information about intelligent delivery, see the XDK documentation.
The primary benefit of splitting your localized assets is the reduced installation size for the user. When a user initiates the download of a game that uses the Languages tag, the console won’t download the content from any chunks that are not associated with the appropriate language/locale based on the user’s settings. If the user’s language and/or locale is not present in any of the Languages tags in your layout file, the system determines the most appropriate substitute to make sure the assets required for gameplay are available. Here are some examples that show which chunks from the preceding layout file would be downloaded, depending on the user’s settings:
Intelligent delivery reduces the size of the installation package required to play a game. Testing the installation process is most easily done with the xbapp install command from an XDK command prompt. The StreamingInstall sample available on GDN shows an overview of the basic steps required to create an installation package from a layout file and install it on your development console for testing.
If your layout file contains tags needed for intelligent delivery and you simply run xbapp install with only the package path, the behavior will be similar to the retail experience. Chunks that are tagged with languages different from the console’s setting are not installed.
If you want to test multiple languages and locales, use the /Languages flag to force the installation of all chunks for multiple languages regardless of the console settings. Using the /AllChunks flag installs the entire package to the console.
If you want to test changing the console language settings after the initial installation, the /w flag is required. This keeps the connection between the console and the PC hosting the package open after installation is complete, to allow you to install more chunks at a later time. This is especially useful for testing OnDemand content that would otherwise be installed only by using the /AllChunks flag.
The National Language Support (NLS) API supported on Xbox One is one of the APIs available on Windows.
In case you need to retrieve the country that the console is set in, independent of the package manifest, you can use the GetUserGeoID() API. After retrieving the GeoID by using this API, you can use GetGeoInfoW() to retrieve different values based on the location the console is in (like retrieving the two-digit country code). For examples, see the NLS API and Localization sample.
Note: We do not support any of the strings that can be returned from GetGeoInfoW, so GEOTYPE values such as GEO_FRIENDLYNAME or GEO_OFFICIALNAME cannot be used.
The GetUserLocaleEx() API can be used as well to retrieve information about the locale/language that is returned by using GetUserDefaultLocaleName(). Examples of using this API are present in the NLS APIs and Localization sample. You can use the LOCALE_NAME_USER_DEFAULT as the lpLocaleName parameter in the function call and the LCType can be any of the constants used by GetLocaleInfoEx. These constants are defined on MSDN: see the section “Constants Used by GetLocaleInfo and GetLocaleInfoEx Only.”
Note: The GetUserGeoID() API is useful for determining the country of origin when the language/locale returned by GetUserDefaultLocaleName() is “en-GB”. For simplification, the locale name for several countries indicates that the language is UK English. These countries include Saudi Arabia, United Arab Emirates, Czech Republic, Hungary, Slovakia, and Greece.
The API functions defined under the WINAPI_PARTITION_TV_TITLE partition in the WinNLS.h header file are available for use on Xbox One. These functions have been adapted from the Windows app model. The following functions are currently available for use by using the WinNls.h header file:
- Identifier for the geographical location of the user. The list of GeoIDs can be found on Microsoft Developer Network (MSDN).
A few other API functions are exposed through the WINAPI_PARTITION_TV_TITLE partition, but haven’t been made available for use on Xbox One. Including these functions will result in an “error LNK2001: unresolved external symbol” on compilation.
Any method can be used to localize in-title resources. The NLS APIs and Localization sample on GDN shows how strings and images can be localized in different languages by using the resources file. Apps can adopt a similar method or are free to use the method of their choice to localize all resources within the app. The WinRT resource system APIs are not exposed for in-title localization.
Note: Regarding the NLS APIs and Localization sample, the resource file used in the sample has a very basic structure. The structure is used for communicating how localization works. These are just for reference and do not include error checking while parsing the files.
To load a specific speech recognizer for a given country, change the existing SpeechRecognizer initialization code from:
// Create a speech recognizer
m_reco = ref new SpeechRecognizer();
To:
// Attempt to create recognizer and verify speech locale matches title.
// If default recognition locale does not match title locale speech should not be enabled by default.
// Only if the user explicitly chooses (via title UI) to enable speech in a specific locale should a
// non-default locale be used.
Windows::Xbox::Speech::Recognition::SpeechRecognizer^ m_reco;
{
// Create a speech recognizer.
// If the default speech recognition language is unsupported it will throw
m_reco = ref new SpeechRecognizer();
// To ensure a good user experience (and per XR), speech should only be enabled by default if
// the language being used for speech recognition by the system matches that of the game.
wchar_t localeName[ LOCALE_NAME_MAX_LENGTH ];
GetUserDefaultLocaleName( localeName, ARRAYSIZE( localeName ) );
if ( 0 != _wcsicmp( localeName, m_reco->GetRecognizer()->Language->Data() ) )
{
// Speech should not be initialized due to locale mismatch
m_reco = nullptr;
}
else
{
// Initialize speech as the locales match
}
}
The SpeechRecognizer throws an exception (HRESULT = 0x800455bc) if the language doesn’t support voice commands. The SpeechRecognizer should be used only if the value returned by GetUserDefaultLocaleName matches the SpeechRecognizer language.
Titles are expected to include all the locales that they are planning to support with all the resources in their package even though they might not be supported by Xbox One at this time. Include all the locales that you plan to support in the Resources section of the manifest. These unsupported locales will not work for users during launch as they won’t be able to select these locales through the console UI. But including everything in the initial package ensures that it automatically works when these locales become supported.
Titles can also provide users with a locale drop-down menu at startup to choose the language of their preference. This can be used to localize all the in-title resources.
You can use the following methods to test your title for unsupported locales:
Set the unsupported locale by using the command line. (For example, xbconfig preferredlanguages=ja-JP). After you have set the locale and it is present in the manifest, you can test all the resources for that locale.
You can create a temporary UI in your title for selecting a language. You can then select an unsupported language through this UI and then check for all the localized resources.
The first method ensures that you can test both the manifest localized resources and the in-title resources. The second method can be used only to test the in-title resources.
You can check the behavior in the NLS APIs and Localization sample by running xbconfig preferredlanguages=ja-JP and xbreboot before running the sample.
Titles can localize the package manifest resources in addition to the in-title resources. The .resw file can be used for the localization of resources in the package manifest. Titles can use their own method for localizing in-title resources based on the user locale. The National Language Support (NLS) API is exposed through the Xbox One XDK/ADK so that developers can make use of locale information to localize title resources. The geographic information exposed through this API can help make games better based on regional preferences.
Click the links that are relevant to your partner program.
Samples
Games/Hub Apps: NLS APIs and Localization sample, available for download on XGD
Media Apps: NLS APIs and Localization sample, available for download on XGD
Template file: The item template for including .resw resources on a Windows 7 computer can be found at XGDDL.