
今日のグローバル化したソフトウェア開発の波では、アプリケーションの国際化(i 18 n)とローカリゼーション(L 10 n)が特に重要になっている。Avalonia UIは強力なクロスプラットフォームUIフレームワークで、開発者に国際化への複数の道を提供します。その中でも、伝統的なResxリソースファイルを国際化に使用することは、元のWinform、WPF、ASP.NET Coreなどの開発シナリオの使用習慣と互換性があるだけでなく、いくつかのユーティリティと特定の開発プロセスの助けを借りて、国際化の実装を効率的かつ体系的にします。
1. はじめに:ResxリソースファイルとAvalonia UIの国際化
ソフトウェア開発においては、アプリケーションが言語や文化の境界を越えて世界中のユーザーに届くようにするためには、国際化が不可欠です。Avalonia UIは、その柔軟なアーキテクチャと豊富な機能により、クロスプラットフォームアプリケーション開発で頭角を現しました。ローカライズされたリソース管理の実証済みの方法であるResxリソースファイルは、Avalonia UIにも新たな役割を果たしています。この2つを組み合わせることで、開発者は使い慣れた開発モデルでアプリケーションに多言語サポートを提供し、異なる地域のユーザーのニーズに簡単に対応できます。
下图是使用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. T 4ファイル:リソースファイルから強型付きリソースクラスへのブリッジ
2.3.1. T 4ファイルの作成と構成
有了资源文件后,虽然已经能够在一定程度上实现国际化功能,但直接使用字符串 Key 在代码中进行资源引用既容易出错又不够直观。因此,我们引入 T4 文件来根据资源文件生成强类型的资源类。在之前创建的 I18n 目录下,添加一个 T4 文件,例如 Language.tt(文件名可根据项目需求灵活调整)。

2.3.2. T 4文書の内容解析と生成ロジック
打开 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";
}
この生成されたリソースクラスにより、コード内でリソースキーを強型付きで参照することができ、コードの可読性と保守性が大幅に向上します。
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}}" />
これにより、アプリケーションのロケールが変化すると、インタフェース要素のテキストが自動的に対応する翻訳テキストに更新され、インタフェースの動的な国際化が実現されます。
- 言語切り替えの実現
实现语言切换功能也非常简单,只需调用 I18nManager.Instance.Culture 属性,并传入目标语言的 CultureInfo 对象即可。例如:
I18nManager.Instance.Culture = new CultureInfo(language);
这里的 language 变量可以是任何有效的语言代码,如 zh-CN、ja-JP 等。当设置了新的语言文化后,整个应用的语言显示会立即更新,为用户提供无缝的多语言切换体验。
3. Resxリソース文書国際化スキームの長所と短所
Resxリソースファイルを介したAvalonia UIアプリケーションの国際化は、伝統的な開発者に馴染みのある便利な方法を提供します。ResXManagerやT 4ドキュメンテーション技術などの既存の開発経験とツールエコシステムを活用し、国際的な開発プロセスを既存のプロジェクトフローに効率的に統合することができます。しかし、この方法も完璧ではない。通常のユーザー側のメンテナンスには、いくつかの困難があります。一般ユーザーはResxファイルの構造や編集方法に精通しておらず、T 4ファイル生成コードのロジックを理解するのが難しいかもしれません。そのため、プロジェクトの設計と実装において、開発者はその後のメンテナンスコストを十分に考慮する必要があり、一般ユーザーが国際化されたリソースの更新と管理を支援するための使いやすいインターフェイスやツールを提供する必要がある場合があります。しかし、一般的に、Resxリソースファイルの国際化は、機能性、効率性、互換性の面で優れたパフォーマンスを備えた開発チームや特定の技術基盤を持つプロジェクトにとって推奨される選択肢のままです。
この記事がAvalonia UI開発者の国際的な実践における有用な参考とガイダンスを提供し、あなたのアプリケーションがグローバルな舞台で輝くことを願っています。
** 次の記事では、XMLドキュメントの国際化を紹介します **