doc/WebSite/Zero/Language-Management.md
ASP.NET Boilerplate defines a strong UI localization system which is used both on the server and client sides. It allows us to easily configure application languages and define localization texts (strings) in different sources (Resource files and XML files are two pre-defined sources).
While it's good for most cases, we may want to define languages and texts dynamically and on a database. Module Zero allows us to dynamically manage application languages and texts per tenant.
We strongly recommend you read the localization documentation before this document.
If you create your project from the startup templates, you can skip this section since the template comes with the database-based localization enabled by default. If you created your project before this feature, please read this to enable it for your application.
Database localization is designed to be backwards-compatible with ASP.NET Boilerplate's existing localization system. It actually replaces all the existing dictionary-based localization sources with MultiTenantLocalizationSource.
MultiTenantLocalizationSource wraps existing DictionaryBasedLocalizationSource based sources. We generally wrap XML based localization sources. It can not wrap Resource File sources since resource files are designed as hard-coded and static files which are not proper for dynamic localization.
Since it's a wrapper, the underlying XML files are used as a fallback source if a text is not localized in the database. It may seem complicated, but it's easy to implement for your application. Let's see how to enable the database-based localization.
First, we enable it:
Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();
This should be done in the top level module's PreInitialize method (it's the web module for a web application. Import the Abp.Zero.Configuration namespace (using Abp.Zero.Configuration) to see the Zero() extension methods).
This configuration makes all the magic happen, but we must add some more code to make it work properly.
Since ABP will get a list of languages from the database, we must insert the default languages into it. If you're using EntityFramework, you can use this seed code:
If you have a static language configuration like the one shown below, you can delete these lines from your configuration code, since they will get the languages from the database.
Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
Do not delete your XML localization files and source configuration code. These files are used as a fallback source and all localization keys are obtained from this source.
So when you need a new localized text, define it into the XML files as you do normally. You must at least define it in the default language's XML file. Note: you don't need to add the default values of the localized texts to the database migration code.
The IApplicationLanguageManager interface is injected and used to manage languages. It has methods like GetLanguagesAsync, AddAsync, RemoveAsync, UpdateAsync... to manage languages for the host and tenants.
The list of languages are stored per tenant and for the host, and calculated as follows:
The ApplicationLanguage entity represents a language for a tenant or the host.
[Serializable]
[Table("AbpLanguages")]
public class ApplicationLanguage : FullAuditedEntity, IMayHaveTenant
{
//...
}
Its basic properties are:
The ApplicationLanguage also inherits from FullAuditedEntity. This means it's a soft-delete entity and automatically audited (see the entity document for more info).
The ApplicationLanguage entities are stored in the AbpLanguages table in the database.
The IApplicationLanguageTextManager interface is injected and used to manage localization texts. It has the needed methods to get/set a localization text for a tenant or the host.
Let's see what happens when you want to localize a text;
Getting a localized text is a bit complicated, but it works fast since it uses the cache.
The ApplicationLanguageText entity is used to store localized values in the database.
[Serializable]
[Table("AbpLanguageTexts")]
public class ApplicationLanguageText : AuditedEntity<long>, IMayHaveTenant
{
//...
}
It's basic properties are;
ApplicationLanguageText entities are stored in the AbpLanguageTexts table in the database.