You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#与WPF混合项目多语言本地化方案咨询(支持运行时切换)

跨项目C#与WPF本地化方案(支持运行时切换)

一、统一资源文件规划

为避免重复维护,先做资源分层:

  • 共享资源:在App.Core项目创建SharedResources.resx,存放两个项目共用的字符串(如系统通知标题、通用提示文本),并生成对应语言版本:SharedResources.nl.resx(荷兰语)、SharedResources.en.resx(英语)、SharedResources.fr.resx(法语)、SharedResources.de.resx(德语)。
  • 项目专属资源:在App.Windows项目创建WindowResources.resx,存放WPF界面专属字符串(如按钮标签、窗口标题),同样生成多语言版本。

注意:将所有.resx文件的访问修饰符设为public,这样会生成强类型资源类,方便跨项目调用。

二、App.Core纯C#项目本地化实现

  1. 字符串替换:直接用强类型资源类替代硬编码,比如:
    // 替换硬编码:"New Notification"
    var notificationTitle = SharedResources.Notification_Title;
    // 推送Windows系统通知时使用
    ToastNotificationManager.CreateToastNotification(new ToastContent()
    {
        Header = new ToastHeader(notificationTitle, SharedResources.Notification_Subtitle, ""),
        Body = new ToastBody() { TextBody1 = SharedResources.Notification_Content }
    });
    
  2. 自定义UI通知:ViewModel中绑定的字符串同样通过资源类获取,后续配合语言变更事件刷新即可。

三、App.Windows WPF项目本地化实现

1. XAML界面本地化(支持运行时切换)

  • 先在XAML根节点声明资源命名空间:
    <!-- 引用Core项目的共享资源 -->
    xmlns:sharedRes="clr-namespace:App.Core.Properties;assembly=App.Core"
    <!-- 引用本项目的专属资源 -->
    xmlns:windowRes="clr-namespace:App.Windows.Properties;assembly=App.Windows"
    
  • 使用DynamicResource绑定字符串(必须用DynamicResource才能支持运行时刷新):
    <Button Content="{DynamicResource {x:Static windowRes:WindowResources.Button_Save}}" />
    <TextBlock Text="{DynamicResource {x:Static sharedRes:SharedResources.Welcome_Message}}" />
    

2. WPF代码本地化

和Core项目用法一致,直接调用强类型资源类:

// 替换硬编码:"Are you sure you want to exit?"
MessageBox.Show(windowRes:WindowResources.Message_ConfirmExit);

四、运行时切换语言核心实现

1. 全局语言管理类(App.Core中实现)

创建静态类统一管理文化切换,触发变更通知:

public static class LanguageManager
{
    public static event EventHandler LanguageChanged;
    public static CultureInfo CurrentCulture { get; private set; }

    static LanguageManager()
    {
        // 默认使用系统UI文化,也可改为配置的默认语言
        CurrentCulture = CultureInfo.CurrentUICulture;
    }

    public static void SetLanguage(string cultureCode)
    {
        var targetCulture = new CultureInfo(cultureCode);
        if (CurrentCulture.Equals(targetCulture)) return;

        CurrentCulture = targetCulture;
        // 更新线程文化
        Thread.CurrentThread.CurrentCulture = targetCulture;
        Thread.CurrentThread.CurrentUICulture = targetCulture;
        // 更新所有资源类的文化
        App.Core.Properties.SharedResources.Culture = targetCulture;
        App.Windows.Properties.WindowResources.Culture = targetCulture;
        // 触发事件通知界面刷新
        LanguageChanged?.Invoke(null, EventArgs.Empty);
    }
}

2. 界面与ViewModel响应变更

  • WPF窗口刷新:在App.xaml.cs中订阅语言变更事件,强制刷新所有窗口资源:

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
LanguageManager.LanguageChanged += (s, args) =>
{
foreach (var window in Current.Windows)
{
window.InvalidateVisual();
// 若使用了自定义资源字典,可清空后重新加载
// window.Resources.MergedDictionaries.Clear();
// window.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Resources/Styles.xaml", UriKind.Relative) });
}
};
}

- **ViewModel属性刷新**:ViewModel实现`INotifyPropertyChanged`,订阅语言变更事件触发属性更新:
  ```csharp
public class MainViewModel : INotifyPropertyChanged
{
    public string WelcomeText => SharedResources.Welcome_Message;

    public MainViewModel()
    {
        LanguageManager.LanguageChanged += (s, args) => OnPropertyChanged(nameof(WelcomeText));
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

五、测试与维护建议

  • 用代码分析工具(如Roslyn分析器)扫描项目,找出遗漏的硬编码字符串。
  • 针对每种语言,测试Core的系统通知、自定义通知,以及WPF界面的所有文本是否正确切换。
  • 后续新增语言时,只需复制基础.resx文件,重命名为对应语言代码并翻译内容即可。

内容的提问来源于stack exchange,提问作者Richard Gale

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:09:24