Avalonia 國際化之路:Resx 資源文件的深度應(yīng)用與探索

0104.gif

在當今全球化的軟件開發(fā)浪潮中,應(yīng)用的國際化(i18n)與本地化(L10n)顯得尤為重要。Avalonia UI 作為一款強大的跨平臺 UI 框架,為開發(fā)者提供了多種實現(xiàn)國際化的途徑。其中,使用傳統(tǒng)的 Resx 資源文件進行國際化處理,不僅兼容了原 Winform、WPF、ASP.NET Core 等開發(fā)場景下的使用習慣,還借助一些實用工具和特定的開發(fā)流程,讓國際化的實現(xiàn)變得高效且有條理。

1. 引言:Resx 資源文件與 Avalonia UI 國際化的邂逅

在軟件開發(fā)領(lǐng)域,國際化是確保應(yīng)用能夠跨越語言和文化邊界,觸達全球用戶的關(guān)鍵。Avalonia UI 以其靈活的架構(gòu)和豐富的功能,在跨平臺應(yīng)用開發(fā)中嶄露頭角。而 Resx 資源文件,作為一種久經(jīng)考驗的本地化資源管理方式,在 Avalonia UI 中也找到了新的用武之地。通過將兩者結(jié)合,開發(fā)者能夠在熟悉的開發(fā)模式下,為應(yīng)用賦予多語言支持的能力,輕松應(yīng)對不同地區(qū)用戶的需求。

下圖是使用VS擴展 ResXManager 對Resx資源文件進行管理的截圖:

0101.gif

2. 詳細使用步驟:構(gòu)建多語言應(yīng)用的基石

2.1. Resx 資源文件的精心布局

2.1.1. 項目目錄規(guī)劃與基礎(chǔ)資源文件創(chuàng)建

開啟您的 Avalonia UI 項目之旅,無論是已有的成熟項目還是全新創(chuàng)建的項目,首先在項目中添加一個用于存放國際化資源的目錄,這里我們命名為 I18n(您可根據(jù)項目實際情況自定義目錄名)。在這個目錄下,創(chuàng)建默認的英文語言資源文件 Resource.resx。這個文件將作為整個國際化資源體系的基礎(chǔ),承載著應(yīng)用在英文環(huán)境下的所有文本資源。

0102.png

2.1.2. 多語言資源文件的拓展

  • 當英文資源文件就緒后,我們可以進一步拓展其他語言的資源文件。以中文簡體、中文繁體和日語為例,它們的文件名需要遵循特定的命名規(guī)則:文件名前綴與默認語言資源文件名保持一致,即 Resource,并添加對應(yīng)的 CultureName 后綴。例如,中文簡體對應(yīng)的資源文件名為 Resource.zh-CN.resx,中文繁體為 Resource.zh-Hant.resx,日語則是 Resource.ja-JP.resx。這樣的命名方式有助于 Avalonia UI 在運行時準確識別并加載不同語言的資源。
  • 借助強大的 ResXManager 工具,我們可以方便地打開這些資源文件進行多語言文本的編輯。在編輯過程中,需要特別注意語言 Key 的命名,它必須滿足 C# 變量語法,因為后續(xù)的開發(fā)流程會依據(jù)這些 Key 生成對應(yīng)的語言 Key 類,確保在代碼層面能夠精準地引用和操作這些資源。

2.2. NuGet 包的引入:增強國際化功能的得力助手

Install-Package AvaloniaExtensions.Axaml

這個包為我們的項目帶來了一系列實用的 API,包括多語言切換功能、便捷的獲取 Key 對應(yīng)翻譯字符串的方法,以及在 axaml 前端界面中對語言標記的支持。這些功能將極大地簡化我們在國際化開發(fā)過程中的代碼編寫和界面設(shè)計工作。

2.3. T4 文件:從資源文件到強類型資源類的橋梁

2.3.1. T4 文件的創(chuàng)建與配置

有了資源文件后,雖然已經(jīng)能夠在一定程度上實現(xiàn)國際化功能,但直接使用字符串 Key 在代碼中進行資源引用既容易出錯又不夠直觀。因此,我們引入 T4 文件來根據(jù)資源文件生成強類型的資源類。在之前創(chuàng)建的 I18n 目錄下,添加一個 T4 文件,例如 Language.tt(文件名可根據(jù)項目需求靈活調(diào)整)。

0103.png

2.3.2. T4 文件的內(nèi)容解析與生成邏輯

打開 Language.tt 文件,其內(nèi)容包含了一系列的指令和代碼片段。首先,通過 #import 指令引入了多個命名空間,這些命名空間為后續(xù)的代碼操作提供了必要的功能支持,如處理 XML 數(shù)據(jù)、文件操作等。


<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>
//------------------------------------------------------------------------------  
// <auto-generated>  
//     This code was generated by a tool.  
//     Changes to this file may cause incorrect behavior and will be lost if  
//     the code is regenerated.  
// </auto-generated>  
//------------------------------------------------------------------------------
<#
    const string ResourceFileName = "Resources.resx";
#>

namespace <#=System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint").ToString()#>;

public static class Language
{
<#
    var resourceKeys = XElement.Load(this.Host.ResolvePath(ResourceFileName))
        .Elements("data")
        .Select(item => item.Attribute("name")?.Value)
        .Where(item => item != null);

    var resourceDesignerName = Path.GetFileNameWithoutExtension(ResourceFileName);

    foreach (string resourceKey in resourceKeys)
    {
#>
    public static readonly string <#= resourceKey #> = "<#= resourceKey #>";
<#
    }
#>
}

其中,ResourceFileName 變量指定了前面創(chuàng)建的默認 Resx 資源文件名,這是 T4 文件生成強類型資源類的依據(jù)。在 T4 文件的主體部分,通過 XElement.Load 方法加載指定的資源文件,并使用 LINQ 查詢表達式從資源文件的 XML 結(jié)構(gòu)中提取出所有的語言 Key。然后,針對每個提取到的 Key,生成一個對應(yīng)的公共靜態(tài)只讀字符串字段,字段名與 Key 相同,初始值也為 Key。這樣,當 T4 文件執(zhí)行保存操作(通常通過 Ctrl + S)時,就會在相同目錄下生成一個名為 Language.cs 的 C# 文件,其中包含了強類型的資源類。例如:


//------------------------------------------------------------------------------  
// <auto-generated>  
//     This code was generated by a tool.  
//     Changes to this file may cause incorrect behavior and will be lost if  
//     the code is regenerated.  
// </auto-generated>  
//------------------------------------------------------------------------------

namespace CodeWF.Toolbox.I18n;

public static class Language
{
    public static readonly string AppName = "AppName";
    public static readonly string Home = "Home";
    public static readonly string SearchToolTip = "SearchToolTip";
    public static readonly string Setting = "Setting";
    public static readonly string DesiredAvailabilityNotification = "DesiredAvailabilityNotification";
    public static readonly string AccessToolbox = "AccessToolbox";
    public static readonly string MissingTool = "MissingTool";
    public static readonly string InterfaceStyleSettings = "InterfaceStyleSettings";
    public static readonly string GeneralSettings = "GeneralSettings";
    public static readonly string Theme = "Theme";
    public static readonly string FollowingSystem = "FollowingSystem";
    public static readonly string LightMode = "LightMode";
    public static readonly string DarkMode = "DarkMode";
    public static readonly string LanguageKey = "LanguageKey";
    public static readonly string AutoOpenToolboxAtStartup = "AutoOpenToolboxAtStartup";
    public static readonly string HideTrayIconOnClose = "HideTrayIconOnClose";
    public static readonly string TurnOn = "TurnOn";
    public static readonly string TurnOff = "TurnOff";
    public static readonly string Exit = "Exit";
    public static readonly string SureExit = "SureExit";
    public static readonly string FindInTrayIcon = "FindInTrayIcon";
    public static readonly string ShowMainWindow = "ShowMainWindow";
    public static readonly string DisplayPromptWhenClosing = "DisplayPromptWhenClosing";
    public static readonly string NoMorePrompts = "NoMorePrompts";
    public static readonly string About = "About";
    public static readonly string AboutMessage = "AboutMessage";
}

這個生成的資源類使得我們在代碼中能夠以強類型的方式引用資源 Key,大大提高了代碼的可讀性和可維護性。

2.4. 在項目中的具體應(yīng)用:讓多語言功能鮮活起來

2.4.1. 代碼中的資源引用

在 C# 代碼中,我們可以借助 I18nManager 類來獲取指定語言 Key 對應(yīng)的翻譯字符串。例如:

I18nManager.GetString(Language.Setting)

這里的 Language.Setting 就是通過 T4 文件生成的強類型資源類中的字段,通過這種方式,我們能夠在代碼的任何地方方便地獲取并使用多語言資源,確保應(yīng)用在不同語言環(huán)境下的正確顯示。

2.4.2. Axaml 界面中的語言綁定

axaml 前端界面中,我們首先需要引入相應(yīng)的命名空間:

xmlns:i18n="https://codewf.com"
xmlns:language="clr-namespace:CodeWF.Toolbox.I18n"

然后,通過數(shù)據(jù)綁定的方式將界面元素的文本屬性與語言資源關(guān)聯(lián)起來。例如:

<TextBlock Text="{i18n:I18n {x:Static language:Language.AppName}}" />

這樣,當應(yīng)用的語言環(huán)境發(fā)生變化時,界面元素的文本會自動更新為對應(yīng)的翻譯文本,實現(xiàn)了界面的動態(tài)國際化。

  1. 語言切換的實現(xiàn)

實現(xiàn)語言切換功能也非常簡單,只需調(diào)用 I18nManager.Instance.Culture 屬性,并傳入目標語言的 CultureInfo 對象即可。例如:

I18nManager.Instance.Culture = new CultureInfo(language);

這里的 language 變量可以是任何有效的語言代碼,如 zh-CNja-JP 等。當設(shè)置了新的語言文化后,整個應(yīng)用的語言顯示會立即更新,為用戶提供無縫的多語言切換體驗。

3. 總結(jié):Resx 資源文件國際化方案的優(yōu)劣剖析

通過 Resx 資源文件實現(xiàn) Avalonia UI 應(yīng)用的國際化,無疑為傳統(tǒng)開發(fā)者提供了一條熟悉且便捷的道路。它充分利用了已有的開發(fā)經(jīng)驗和工具生態(tài),如 ResXManager 和 T4 文件技術(shù),使得國際化的開發(fā)過程能夠高效地融入到現(xiàn)有的項目流程中。然而,這種方式也并非完美無缺。其對于普通用戶側(cè)的維護來說,可能存在一定的難度。普通用戶可能不熟悉 Resx 文件的結(jié)構(gòu)和編輯方式,也難以理解 T4 文件生成代碼的邏輯。這就要求在項目的設(shè)計和實施過程中,開發(fā)者需要充分考慮到后續(xù)的維護成本,可能需要為普通用戶提供一些簡單易用的界面或工具來輔助他們進行國際化資源的更新和管理。但總體而言,對于具有一定技術(shù)基礎(chǔ)的開發(fā)團隊和項目來說,Resx 資源文件的國際化方案仍然是一種值得推薦的選擇,它在功能、效率和兼容性方面都有著出色的表現(xiàn)。

希望本文能夠為廣大 Avalonia UI 開發(fā)者在國際化實踐中提供有益的參考和指導(dǎo),讓您的應(yīng)用能夠在全球舞臺上綻放光彩。

彩蛋:下篇文章介紹XML文件實現(xiàn)國際化

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內(nèi)容