Module Zero之語言管理


返回《Module Zero學習目錄》


概覽介紹##

ABP定義了一個健壯的UI本地化系統,它可用於服務端和客戶端。它允許在不同的資源中(Resource文件和XML文件是兩種預定義的資源)輕松地配置應用語言以及定義本地化文本(字符串)。

雖然這對於大多數情況是沒問題的,但是我們可能想要將語言和文本動態地定義到數據庫中。Module-zero允許我們動態地管理每個租戶的應用語言和文本。

如何開啟##

啟動模板

如果你是從ABP官網的啟動模板創建的項目,那么你可以跳過本節。因為該模板自帶的基於數據庫的本地化默認是開啟的。如果你在這個特征之前創建了項目,那么請通過閱讀本節來為你的應用開啟此功能。

基於數據庫的本地化是為了向后兼容ABP中已存在的本地化系統而設計的。它實際上取代了所有基於MultiTenantLocalizationSource本地化資源的字典。

MultiTenantLocalizationSource包裝了基於資源的DictionaryBasedLocalizationSource。因此,我們一般包裝基於XML的本地化資源。它可能不會包裝Resource文件資源,因為resource文件是為硬編碼設計的,而且靜態文件也不適合動態本地化。

因為它是一個包裝器,所以如果一個文本沒有在數據庫中本地化,那么潛在的XML文件就會用作回退資源(我理解為xml文件就是退而求其次的資源,也就是優先級小於數據庫資源)。可能看着很復雜,但是對於你的應用實現起來很簡單。下面讓我們看一下如何開啟基於數據庫的本地化。

開啟數據庫本地化(EnableDbLocalization)####

首先要開啟它:

Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();

這一步應該在高級別的模塊中的PreInitialize方法中完成(對於Web應用,它是web module。導入Abp.Zero.Configuration命名空間查看Zero()擴展方法)。

實際上,該配置使得一切變得富有魔力。但是,我們應該多做一點來使它更合適地工作。

種子數據庫語言####

因為ABP會從數據庫中獲得所有的語言列表,因此我們應該將默認的語言插入數據庫。如果你正在使用的是EF,那么你可以像這里一樣使用種子代碼。

移除靜態的語言配置####

如果你使用了像下面一樣的靜態語言配置,那么你可以刪除它們,因為以后會從數據庫中獲得它們。

Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));

注意已存在的XML本地化資源####

不要刪除XML本地化資源和資源配置代碼。因為如果數據庫中沒有相應的資源的話,這些文件會用作回退資源,並且所有的本地化鍵值會從這些資源中獲得。

這樣,當你需要一個新的本地化文本時,你可以像往常一樣將它定義到XML文件中。你至少應該將它定義到默認語言的XML文件中。也只有這樣,你才不用將默認的本地化文本的值添加到數據庫遷移代碼中。

管理語言##

可以將接口IApplicationLanguageManager進行注入,然后使用它管理語言。該接口有諸如GetLanguagesAsync ,AddAsync,RemoveAsync,UpdateAsync...的方法,可以用來管理租主和租戶的語言。

語言列表邏輯####

語言列表為每個租戶和租主單獨存儲和計算,如下:

  • 存在一個為租主定義的語言列表。該列表對所有租戶都是默認的。
  • 存在為每個租戶獨立的語言列表。該列表繼承了租主的語言列表,並加入了租戶特定的語言。租戶可以不刪除或更新租主定義(默認)的語言(但是可以重寫本地化文本,后面會看到)。

應用語言實體(ApplicationLanguage Entity)####

應用語言實體表示了一個租戶或租主的語言。

[Serializable]
[Table("AbpLanguages")]
public class ApplicationLanguage : FullAuditedEntity, IMayHaveTenant
{
    //...
}

基本屬性有:

  • TenantId(nullable):如果該語言是特定租戶的,那么該屬性就包含相關的租戶Id。如果該語言是租主的,那么就是null。
  • Name:語言的名字。該屬性必須是來自這里的列表里的文化代碼
  • DisplayName:該語言的展示名稱。可以是任意的名字,一般是CultureInfo.DisplayName
  • Icon:該語言的一個任意圖標或旗幟。這個可用於在UI上展示該語言的旗幟。

而且,應用語言實體繼承了FullAuditedEntity。這意味着,它是一個軟刪除且自動 審計的實體。
應用語言實體存儲在數據庫中的AbpLanguages表中。

管理本地化文本##

可以通過注入IApplicationLanguageTextManager接口來管理本地化文本。該接口擁有為一個租戶或租主獲取或設置本地化文本需要的方法。

使文本本地化####

當你想要本地化一個文本時,讓我們看一下發生了什么:

  • 嘗試獲取當前文化(使用CurrentThread.CurrentUICulture獲得)。
    • 檢查給定的文本在數據庫中是否以當前的文化當前的租戶(使用IAbpSession.TenantId獲得)已經定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本在數據庫中是否以當前的文化為該租主已定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本是否以當前的文化在潛在的XML文件中已經定義。若定義則返回該值。
  • 嘗試找出該回退文化。它是這樣計算的:如果當前文化是“en-GB”,那么回退文化就是“en”。
    • 檢查給定的文本在數據庫中是否以回退文化當前的租戶(使用IAbpSession.TenantId獲得)已經定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本在數據庫中是否以回退文化為該租主已定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本是否以回退文化在潛在的XML文件中已經定義。若定義則返回該值。
  • 嘗試找出默認的文化
    • 檢查給定的文本在數據庫中是否以默認的文化當前的租戶(使用IAbpSession.TenantId獲得)已經定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本在數據庫中是否以默認的文化為該租主已定義(或重寫)。如果定義了就返回該值。
    • 然后檢查給定的文本是否以默認的文化在潛在的XML文件中已經定義。若定義則返回該值。
  • 獲得相同的文本或者拋出異常
    • 如果給定的文本(或鍵值)壓根沒有找到,那么ABP會拋出異常或者返回相同的使用[and]包裝的文本(或鍵值)。(可以在啟動時配置,詳情查看

因此,獲得一個本地化的文本有點復雜。但是它運行起來很快,因為它使用了緩存(cache)。

應用語言文本實體(ApplicationLanguageText Entity)####

在數據庫中,應用語言文本實體存儲了本地化的值。

[Serializable]
[Table("AbpLanguageTexts")]
public class ApplicationLanguageText : AuditedEntity<long>, IMayHaveTenant
{
    //...
}


它的基本的屬性是:

  • TenantId(nullable):若該本地化的文本是特定租戶的,那么它包含了與之相關的租戶的Id。如果這是租主本地化的文本,那么該值為null。
  • LanguageName:語言的名稱。該屬性必須是來自這里的列表里的文化代碼。這個和ApplicationLanguage.Name是匹配的,但是沒有強制的外鍵從而使它獨立於語言實體。IApplicationLanguageTextManager會合適地對它處理。
  • Source:本地化資源名稱。
  • Key:本地化文本的Key或者名稱。
  • Value:本地化的值。

ApplicationLanguageText實體存儲在數據庫中的“AbpLanguageTexts ”表。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM