.NET WPF 应用程序的运行时本地化

问题描述 投票:0回答:1

我正在致力于本地化一个用 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 的文件)中使用事件处理程序。然而,我用这种方法并没有取得太大进展。另一位建议多线程,但现在我没有时间研究它。我也对不同的方法持开放态度。

c# wpf multithreading localization resourcemanager
1个回答
0
投票

我建议看看我的作品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

© www.soinside.com 2019 - 2024. All rights reserved.