avalonia 國際化之路:resx 資源文件的深度應用與探索

avalonia 國際化之路:resx 資源文件的深度應用與探索

在當今全球化的軟體開發浪潮中,應用的國際化(i18n)與本地化(l10n)顯得尤為重要。avalonia ui 作為一款強大的跨平台 ui 框架,為開發者提供了多種實現國際化的途徑。其中,使用傳統的 resx 資源文件進行國際化處理,不僅兼容了原 winform、wpf、asp.net core 等開發場景下的使用習慣,還藉助一些實用工具和特定的開發流程,讓國際化的實現變得高效且有條理。

最后更新 2024/12/5 下午9:34
沙漠尽头的狼
预计阅读 10 分钟
分类
Avalonia UI
标签
.NET C# ASP.NET Core WPF Avalonia UI

在當今全球化的軟體開發浪潮中,應用的國際化(i18n)與本地化(l10n)顯得尤為重要。avalonia ui 作為一款強大的跨平台 ui 框架,為開發者提供了多種實現國際化的途徑。其中,使用傳統的 resx 資源文件進行國際化處理,不僅兼容了原 winform、wpf、asp.net core 等開發場景下的使用習慣,還藉助一些實用工具和特定的開發流程,讓國際化的實現變得高效且有條理。

1. 引言:resx 資源文件與 avalonia ui 國際化的邂逅

在軟體開發領域,國際化是確保應用能夠跨越語言和文化邊界,觸達全球用戶的關鍵。avalonia ui 以其靈活的架構和豐富的功能,在跨平台應用開發中嶄露頭角。而 resx 資源文件,作為一種久經考驗的本地化資源管理方式,在 avalonia ui 中也找到了新的用武之地。通過將兩者結合,開發者能夠在熟悉的開發模式下,為應用賦予多語言支持的能力,輕鬆應對不同地區用戶的需求。

下图是使用VS扩展 ResXManager 对Resx资源文件进行管理的截图:

2. 詳細使用步驟:構建多語言應用的基石

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

2.1.1.項目目錄規劃與基礎資源文件創建

开启您的 Avalonia UI 项目之旅,无论是已有的成熟项目还是全新创建的项目,首先在项目中添加一个用于存放国际化资源的目录,这里我们命名为 I18n(您可根据项目实际情况自定义目录名)。在这个目录下,创建默认的英文语言资源文件 Resource.resx。这个文件将作为整个国际化资源体系的基础,承载着应用在英文环境下的所有文本资源。

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

  • 当英文资源文件就绪后,我们可以进一步拓展其他语言的资源文件。以中文简体、中文繁体和日语为例,它们的文件名需要遵循特定的命名规则:文件名前缀与默认语言资源文件名保持一致,即 Resource,并添加对应的 CultureName 后缀。例如,中文简体对应的资源文件名为 Resource.zh-CN.resx,中文繁体为 Resource.zh-Hant.resx,日语则是 Resource.ja-JP.resx。这样的命名方式有助于 Avalonia UI 在运行时准确识别并加载不同语言的资源。
  • 借助强大的 ResXManager 工具,我们可以方便地打开这些资源文件进行多语言文本的编辑。在编辑过程中,需要特别注意语言 Key 的命名,它必须满足 C# 变量语法,因为后续的开发流程会依据这些 Key 生成对应的语言 Key 类,确保在代码层面能够精准地引用和操作这些资源。

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

Install-Package AvaloniaExtensions.Axaml

这个包为我们的项目带来了一系列实用的 API,包括多语言切换功能、便捷的获取 Key 对应翻译字符串的方法,以及在 axaml 前端界面中对语言标记的支持。这些功能将极大地简化我们在国际化开发过程中的代码编写和界面设计工作。

2.3. t4 文件:從資源文件到強類型資源類的橋樑

2.3.1. t4 文件的創建與配置

有了资源文件后,虽然已经能够在一定程度上实现国际化功能,但直接使用字符串 Key 在代码中进行资源引用既容易出错又不够直观。因此,我们引入 T4 文件来根据资源文件生成强类型的资源类。在之前创建的 I18n 目录下,添加一个 T4 文件,例如 Language.tt(文件名可根据项目需求灵活调整)。

2.3.2. t4 文件的內容解析與生成邏輯

打开 Language.tt 文件,其内容包含了一系列的指令和代码片段。首先,通过 #import 指令引入了多个命名空间,这些命名空间为后续的代码操作提供了必要的功能支持,如处理 XML 数据、文件操作等。

<#@ 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 变量指定了前面创建的默认 Resx 资源文件名,这是 T4 文件生成强类型资源类的依据。在 T4 文件的主体部分,通过 XElement.Load 方法加载指定的资源文件,并使用 LINQ 查询表达式从资源文件的 XML 结构中提取出所有的语言 Key。然后,针对每个提取到的 Key,生成一个对应的公共静态只读字符串字段,字段名与 Key 相同,初始值也为 Key。这样,当 T4 文件执行保存操作(通常通过 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.在項目中的具體應用:讓多語言功能鮮活起來

2.4.1.代碼中的資源引用

在 C# 代码中,我们可以借助 I18nManager 类来获取指定语言 Key 对应的翻译字符串。例如:

I18nManager.GetString(Language.Setting)

这里的 Language.Setting 就是通过 T4 文件生成的强类型资源类中的字段,通过这种方式,我们能够在代码的任何地方方便地获取并使用多语言资源,确保应用在不同语言环境下的正确显示。

2.4.2. axaml 界面中的語言綁定

axaml 前端界面中,我们首先需要引入相应的命名空间:

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

然後,通過數據綁定的方式將界面元素的文本屬性與語言資源關聯起來。例如:

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

這樣,當應用的語言環境發生變化時,界面元素的文本會自動更新為對應的翻譯文本,實現了界面的動態國際化。

  1. 語言切換的實現

实现语言切换功能也非常简单,只需调用 I18nManager.Instance.Culture 属性,并传入目标语言的 CultureInfo 对象即可。例如:

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

这里的 language 变量可以是任何有效的语言代码,如 zh-CNja-JP 等。当设置了新的语言文化后,整个应用的语言显示会立即更新,为用户提供无缝的多语言切换体验。

3. 總結:resx 資源文件國際化方案的優劣剖析

通過 resx 資源文件實現 avalonia ui 應用的國際化,無疑為傳統開發者提供了一條熟悉且便捷的道路。它充分利用了已有的開發經驗和工具生態,如 resxmanager 和 t4 文件技術,使得國際化的開發過程能夠高效地融入到現有的項目流程中。然而,這種方式也並非完美無缺。其對於普通用戶側的維護來說,可能存在一定的難度。普通用戶可能不熟悉 resx 文件的結構和編輯方式,也難以理解 t4 文件生成代碼的邏輯。這就要求在項目的設計和實施過程中,開發者需要充分考慮到後續的維護成本,可能需要為普通用戶提供一些簡單易用的界面或工具來輔助他們進行國際化資源的更新和管理。但總體而言,對於具有一定技術基礎的開發團隊和項目來說,resx 資源文件的國際化方案仍然是一種值得推薦的選擇,它在功能、效率和兼容性方面都有著出色的表現。

希望本文能夠為廣大 avalonia ui 開發者在國際化實踐中提供有益的參考和指導,讓您的應用能夠在全球舞台上綻放光彩。

彩蛋:下篇文章居間xml文件實現國際化

Keep Exploring

延伸阅读

更多文章