我正在致力于本地化一个用 C# 编写的旧软件应用程序。它是一个 .NET WPF 应用程序,使用两个 XAML 窗口作为 GUI。我创建了一个 LocalizationManager 类来处理翻译,并且字符串存储在两个 .resx 文件中(英语和德语)。
翻译工作正常 - 我可以在设置中更改语言,并且所选语言保存在 settings.xml 中,因此当我重新启动应用程序时它仍然存在。
现在,我需要在运行时实现语言切换。我希望语言更改立即生效,而无需重新启动应用程序。
我不是经验丰富的软件开发人员,因此我正在寻找针对此任务的简单解决方案或最佳实践。如何重新加载窗口或触发必要的事件以使用新语言更新 UI?
预先感谢您的帮助!
我的类 LocalizationManager.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Threading;
namespace ProgrammierstationV2.Logic.Localization
{
/// <summary>
/// A class for managing the localisation of texts based on resource files.
/// </summary>
class LocalizationManager
{
private ResourceManager _resourceManager;
// Property for defining and retrieving the current culture for localisation purposes
public CultureInfo CurrentCulture { get; set; }
static private bool eninitialized = false;
static private CultureInfo cinfo;
private static readonly Lazy<LocalizationManager> _instance = new Lazy<LocalizationManager>(() => new LocalizationManager());
/// <summary>
/// The singleton instance of LocalizationManager.
/// </summary>
public static LocalizationManager Instance => _instance.Value;
/// <summary>
/// Event that is triggered when the language is changed.
/// </summary>
public event EventHandler LanguageChanged;
/// <summary>
/// Private constructor to prevent instantiation.
/// Initialises the resource manager instance based on the name of the resource file and the assembly type.
/// </summary>
private LocalizationManager()
{
// Initialisation of the resource manager with the name of the resource file
// and the assembly type of the LocalisationManager class>
_resourceManager = new ResourceManager("ProgrammierstationV2.LocalizationResources.Strings", typeof(LocalizationManager).Assembly);
// Sets the default language to English
if (eninitialized == true)
{
CurrentCulture = cinfo;
}
else
{
cinfo = new CultureInfo("en-GB");
eninitialized = true;
CurrentCulture = cinfo;
}
}
/// <summary>
/// Returns a list of supported languages.
/// </summary>
/// <returns>A list of supported languages as culture codes.</returns>
public List<string> GetSupportedLanguages()
{
return new List<string> { "en-GB", "de-DE" };
}
/// <summary>
/// Displays the localised text for a specific key.
/// </summary>
/// <param name=‘key’>The key that references the desired localised text in the resource file.</param>
public string DisplayLocalizedText(string key)
{
SetCulture(CurrentCulture);
// Retrieve the localised text for the specified key
string localizedText = _resourceManager.GetString(key);
// Check whether the resource has been found
if (localizedText == null)
{
// Generate an error message that the resource is missing
Console.WriteLine($"Error: Resource with key '{key}' is missing in resource files.");
// Returns a standard text or null
return "Error: Missing Resource";
}
// Retrieve and return the localised text for the specified key
return localizedText;
}
/// <summary>
/// Sets the current culture for localisation.
/// </summary>
/// <param name=‘culture’>The desired culture.</param>
public void SetCulture(CultureInfo culture)
{
// Setting the current culture and UI culture
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
/// <summary>
/// Changes the current language for localisation.
/// </summary>
/// <param name=‘languageCode’>The culture code of the desired language.</param>
public void ChangeLanguage(string languageCode)
{
// Check whether the specified language is supported
if (GetSupportedLanguages().Contains(languageCode))
{
// Create a new CultureInfo instance with the specified language code
CultureInfo newCulture = new CultureInfo(languageCode);
cinfo = newCulture;
// Set the current culture for localisation
SetCulture(newCulture);
// Updating the CurrentCulture property
CurrentCulture = newCulture;
}
}
}
}
一位同事建议我可以在 MainViewModel.cs 文件(应用程序启动时加载 settings.xml 的文件)中使用事件处理程序。然而,我用这种方法并没有取得太大进展。另一位建议多线程,但现在我没有时间研究它。我也对不同的方法持开放态度。
我建议看看我的作品https://github.com/SAKryukov/dotnet-solution-struct。
不幸的是,该文档尚未发布,主要是因为 CodeProject 倒闭了,其网站只能只读。然而,WPF 全球化和本地化部分几乎是自我记录的。
您可以使用在其抽象基类
AdvancedApplication
中找到的类 AdvancedApplicationBase.Localize
的两个方法。每个 CultureInfo
的所有 tee 本地化资源都应使用基于 .NET 资源的全球化和本地化的常用命名约定,以 XAML 数据的形式放置为 卫星程序集。您可以在这里找到这些类和方法:https://github.com/SAKryukov/dotnet-solution-struct/tree/master/code/1-Agnostic/Ui/Application。
演示全球化和本地化技术的应用程序可以在这里找到:https://github.com/SAKryukov/dotnet-solution-struct/tree/master/code/3-Application/Demo.Localization,它也是几乎是自我记录的。
此外,使用此代码,您可以学习所有本地化原理,例如资源的动态加载、通过
CultureInfo
查找资源、后备、程序集元数据等等。
任何对此主题感兴趣的人都受邀参与存储库讨论。
谢谢。
—SA