Localize an XAF Application (.NET)
- 9 minutes to read
This topic describes how to localize XAF .NET applications (WinForms and ASP.NET Core Blazor).
Tip
Refer to the following topic for information on how to localize XAF .NET Framework Applications: Localize an XAF Application (.NET Framework).
Review the Application Model Basics and Localization Basics topics before proceeding.
Choose the language you want to use in your XAF application.
Pre-installed languages: German (de), Spanish (es), and Japanese (ja). These assemblies are available in the DevExpress Local NuGet Feed (for example,
DevExpress.ExpressApp.de
orDevExpress.ExpressApp.Core.All.de
).Other languages:
- Use the Localization Service to download satellite assemblies. See the Localize Standard XAF Modules and DevExpress Controls Used in an Application topic for more information on how to use this service to localize XAF modules.
- Place the downloaded assemblies in the following folders:
- In your application bin folder (for example,
\Solution1.BlazorServer\bin\Debug\net6.0\fr
for French). This enables runtime localization. - In your Model Editor’s folder (for example,
C:\Program Files\DevExpress 22.1\Components\Tools\eXpressAppFrameworkNetCore\Model Editor\fr
for French). This enables design-time localization.
- In your application bin folder (for example,
You can reuse satellite assemblies in any other project.
Note
Remember to deploy the required satellite assemblies when you deploy an XAF application. Refer to the Deployment Tutorial for more details.
For XAF ASP.NET Core Blazor applications, add the ApplicationBuilderExtensions.UseRequestLocalization() method call. This enables the RequestLocalizationMiddleware.
namespace MainDemo.Blazor.ServerSide { public class Startup { // ... public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ... app.UseHttpsRedirection(); // Enable the RequestLocalizationMiddleware app.UseRequestLocalization(); app.UseStaticFiles(); app.UseRouting(); // ... } } }
In
appsettings.json
, specify languages used in your application in theDevExpress:ExpressApp:Languages
section. You should always use the fully qualified language name (for example:xx-YY
instead ofxx
). This languages list is used to:- Load satellite assemblies.
- Specify the RequestLocalizationMiddleware’s RequestLocalizationOptions.SupportedCultures option.
The first language in this list is the default language (specified in the RequestLocalizationOptions.DefaultRequestCulture).
{ // "DevExpress": { "ExpressApp": { "Languages": "en-US;de-DE;fr-FR" // ... } } }
In the module project, double-click the Model.DesignedDiffs.xafml file to invoke the Model Editor. Focus the root node and click Languages Manager… in the Language combo box on the Model Editor Toolbar. Add the target language in the invoked dialog and click OK. Restart Visual Studio to load localized values from the satellite assemblies and specify the application’s target language in the Language combo box.
All the changes for a particular language are saved to the corresponding Model.DesignedDiffs.Localization.<language code>.xafml or Model<language code>.xafml_ file. These files resemble the Model.DesignedDiffs.xafml and Model.xafml files, which store the changes made in the Application Model in the default language (English).
Ensure the newly created Model.DesignedDiffs.Localization.XX.xafml files are processed as embedded resources: in the Property Editor, Build Action is set to Embedded resource.
Refer to the Localization Basics topic for more information.
- To learn how to add a new or modify an existing translation value, refer to the following topic: How to: Localize XAF Application Items Using XAF Tools.
- To specify an application’s language, invoke the Model Editor for an application project, navigate to the Application node, and set the IModelApplication.PreferredLanguage property to a language. Refer to the Localization Basics topic for more details. If you want your application’s language to match the language on the user’s device, set the PreferredLanguage property to (User language).
- Localizable resources of Windows Forms Templates are not available in the Application Model (the default setting). Refer to the How to: Localize a WinForms Template topic to learn how you can localize Windows Forms templates.
- The splash screen form displayed on the Windows Forms application at startup contains a “Loading“ text label. To change the text, refer to the following topic: Localize a Splash Form.
- Start the application to ensure that all the text values are localized.
Change Language at Runtime (Blazor UI)
In UI (Runtime Language Switcher)
For XAF ASP.NET Core Blazor UI applications, you can enable the Runtime Language Switcher. You can see the Language Switcher in the following:
The login page
The settings menu
To enable the Runtime Language Switcher, set the DevExpress: ExpressApp: ShowLanguageSwitcher
value to True
in appsettings.json
:
{
//
"DevExpress": {
"ExpressApp": {
"Languages": "en-US;de-DE;fr-FR",
"ShowLanguageSwitcher": true
}
}
}
The Languages
section must contain at least two supported languages to enable the Runtime Language Switcher. These languages will be displayed in the Language Switcher’s drop-down list.
The application retrieves the language name from CultureInfo.NativeName
.
Note
The Runtime Language Switcher requires that IModelApplication.PreferredLanguage
is set to (User language)
.
In Code
To change the XAF ASP.NET Core Blazor application language in code, use the IXafCultureInfoService.SetCultureAsync method.
The call of the SetCultureAsync
method initiates the following:
- Recreation of the XafApplication in a new culture. The new culture is read from cookies in
RequestLocalizationMiddleware
. - Reload of the ASP.NET Core Blazor application even if there were no changes in the culture.
The code sample below demonstrates how to use IXafCultureInfoService to change the application localization:
File:
MySolution.Blazor.Server\Controllers\GermanCultureController.cs in solutions without the ASP.NET Core Blazor-specific module project.
MySolution.Module.Blazor\Controllers\GermanCultureController.cs in solutions with the ASP.NET Core Blazor-specific module project.
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Blazor;
using DevExpress.ExpressApp.Blazor.Services;
using DevExpress.Persistent.Base;
// ...
public class GermanCultureController : ViewController {
BlazorApplication BlazorApplication => (BlazorApplication)Application;
IXafCultureInfoService CultureInfoService => (IXafCultureInfoService)BlazorApplication.ServiceProvider.GetService(typeof(IXafCultureInfoService));
public GermanCultureController() {
SimpleAction myAction = new SimpleAction(this, "SetGermanCulture", PredefinedCategory.Edit);
myAction.Execute += async (s, e) => await CultureInfoService.SetCultureAsync("de-DE");
}
}
Note
In .NET 5, the libraries used for globalization functionality have been changed. Refer to the following topic for details: Globalization APIs use ICU libraries on Windows.
If a current thread’s culture is set to a culture that includes only the language and not the country (for example, “de” or “en”), the currency symbol renders as an international currency symbol (¤
), for example: 100.00 ¤
.
Refer to the following topics for details:
Current Culture in XAF ASP.NET Core Blazor Applications
In XAF ASP.NET Core Blazor applications, the current culture is set in the following order of priority:
- From a user’s cookies.
- If the culture is not set in cookies, the application uses the default culture from a user’s browser. The
Languages
collection inappsettings.json
should contain this culture. - If the
Languages
collection does not contain the user’s culture, the application uses the first culture from the collection.
When users change the current culture in the Language Switcher, their cookies are updated with the new culture value.
The IModelApplication.PreferredLanguage option affects only the XAF parts of the application (Action’s captions, navigation, layout, etc.), and do not affect the application’s culture.
The application’s current culture depends on both the following settings:
- The
Languages
option inappsettings.json
- User’s browser preferred language, if the application supports multiple languages.
Single Language Support
If your application supports only a single language, specify this language in both appsettings.json
and IModelApplication.PreferredLanguage. You should always use the fully qualified language name, for example: xx-YY
instead of xx
:
{
//
"DevExpress": {
"ExpressApp": {
"Languages": "de-DE"
// ...
}
}
}
Localize Reports and Filter Editor in ASP.NET Core Blazor Applications
Note
The technique described in this section applies to projects that use DxDocumentViewer - the default component in XAF since v.24.1. For more information about migrating to DxDocumentViewer
, refer to the following Breaking Change ticket: ReportsV2Module - Migration from DxDocumentViewer to DxReportViewer
DxReportViewer does not require additional changes. You can follow the common scenario of a .NET application localization.
The Reporting Module and Filter Editor use DevExpress Web Reporting components - you can use the same technique to localize both.
Note
The example described in this section is available in the following demo and reference materials:
- Blazor Reporting - UI Customization API
- XAF’s Blazor UI Demo
- The MainDemo demo project. This project is installed as a part of the XAF package. The default project location is %PUBLIC%\Documents\DevExpress Demos 23.1\Components\XAF.
The example below shows how to localize an XAF ASP.NET Core Blazor application to German.
Add German language to the YourSolutionName.Blazor.Server\appsettings.json file of your ASP.NET Core Blazor application.
{ // "DevExpress": { "ExpressApp": { "Languages": "en-US;de-DE" // } } }
Add the JSON files with localization resources to the wwwroot\js\localization folder. You can obtain the JSON files from the DevExpress Localization Service. For additional information, refer to the following help topic: Obtain JSON Files from the Localization Service. For the purposes of this example, the following files are used:
- de-DE.json
- dx-analytics-core.de-DE.json
- dx-reporting.de-DE.json
In the YourSolutionName.Blazor.Server\Controllers folder, create a View Controller. In this Controller, specify the
CustomizeLocalization
handler forDxReportDesigner
,DxDocumentViewer
, andFilterEditor
and set the current culture to the client usingJSInterop
.File: YourSolutionName.Blazor.Server\Controllers\ReportLocalizationController.cs
using DevExpress.ExpressApp; using DevExpress.ExpressApp.Blazor.Editors; using DevExpress.ExpressApp.Blazor.Services; using DevExpress.ExpressApp.ReportsV2.Blazor; using Microsoft.JSInterop; namespace YourSolutionName.Blazor.Server.Controllers; public class ReportLocalizationController : ViewController<DetailView> { private readonly IXafCultureInfoService cultureInfoService; private readonly IJSRuntime jSRuntime; public ReportLocalizationController() { } [ActivatorUtilitiesConstructor] public ReportLocalizationController(IXafCultureInfoService cultureInfoService, IJSRuntime jSRuntime) { this.cultureInfoService = cultureInfoService; this.jSRuntime = jSRuntime; } protected override void OnActivated() { base.OnActivated(); View.CustomizeViewItemControl<ReportViewerViewItem>(this, CustomizeReportViewer); View.CustomizeViewItemControl<ReportDesignerViewItem>(this, CustomizeReportDesigner); View.CustomizeViewItemControl<FilterPropertyEditor>(this, CustomizeFilterPropertyEditor); } private async void CustomizeReportDesigner(ReportDesignerViewItem propertyEditor) { propertyEditor.CallbacksModel.CustomizeLocalization = "ReportingLocalization.onCustomizeLocalization"; await jSRuntime.InvokeVoidAsync("ReportingLocalization.setCurrentCulture", cultureInfoService.CurrentCulture.Name); } private async void CustomizeReportViewer(ReportViewerViewItem propertyEditor) { if(propertyEditor.DocumentViewerCallbacksModel is not null) { propertyEditor.DocumentViewerCallbacksModel.CustomizeLocalization = "ReportingLocalization.onCustomizeLocalization"; await jSRuntime.InvokeVoidAsync("ReportingLocalization.setCurrentCulture", cultureInfoService.CurrentCulture.Name); } } private async void CustomizeFilterPropertyEditor(FilterPropertyEditor filterPropertyEditor) { filterPropertyEditor.ComponentModel.CustomizeLocalization = "ReportingLocalization.onCustomizeLocalization"; await jSRuntime.InvokeVoidAsync("ReportingLocalization.setCurrentCulture", cultureInfoService.CurrentCulture.Name); } }
Add the
CustomizeLocalization
handler to the YourSolutionName.Blazor.Server\wwwroot\js\scripts.js file:window.ReportingLocalization = { currentCulture: null, setCurrentCulture: function (culture) { window.ReportingLocalization.currentCulture = culture; }, onCustomizeLocalization: function (_, e) { const currentCulture = window.ReportingLocalization.currentCulture; if (currentCulture == "de-DE") { e.LoadMessages($.get("/js/localization/dx-analytics-core." + currentCulture + ".json")); e.LoadMessages($.get("/js/localization/dx-reporting." + currentCulture + ".json")); $.get("/js/localization/" + currentCulture + ".json").done(result => { e.WidgetLocalization.loadMessages(result); }).always(() => { e.WidgetLocalization.locale(currentCulture); }) } } }
Add a jQuery library to your project’s YourSolutionName.Blazor.Server\wwwroot\js folder.
Add
scripts.js
and jQuery references to the YourSolutionName.Blazor.Server\Pages\_Host.cshtml file.<!----> <script src="_framework/blazor.server.js"></script> <script src="js/jquery.min.js"></script> <script src="js/scripts.js"></script> <!---->
Tip
Since the components’ UI is built on DevExtreme widgets, you can also use one of the techniques described in the following topic: Localization.
Localize Scheduler Module
To localize the Scheduler module, you need to take additional steps after you follow the general localization scenario for XAF .NET applications described in this topic.
Navigate to the DevExpress Localization Service web page. Add or modify translations for the following strings:
SchedulerStringId.AppointmentLabel_*
andSchedulerStringId.Caption_*
.Save changes and download updated assemblies.
Add all assemblies from the downloaded package to the corresponding language folder in your application’s bin folder (for example, \YourSolutionName.BlazorServer\bin\Debug\netX.X\fr-FR and \YourSolutionName.Win\bin\Debug\netX.X\fr-FR for French language).
Build and run the application.