C# WinForm 国际化/本地化/多语化的方法与各种坑
巨硬提供了完整的 WinForm 国际化方案,操作起来也比较简单(坑也比较多),本文主要记录一下国际化中会遇到的一些问题。
基本的国际化方案
基本的国际化/本地化操作我就不再赘述了,主要涉及以下3点:
- 窗体文本、图片等内容的国际化(窗体文本)
- 内部提示文本、时间等区域化内容的国际化(代码文本)
- 语言的动态切换(不退出程序动态切换语言)
可供参考的文章:
坑1:图片资源文件的重复使用
一个含有图标的窗体,VS在新建新的语言的资源文件(.resx)的时候会把图标也给复制一份放在里面,然后导致最后编译出来的资源 dll 体积很大。
个人的解决方案是:
不在属性窗口配置 Icon 。图标扔到一个资源文件里统一管理,然后直接修改窗体设计文件源码 FormMain.Designer.cs ,加上一行:
|
|
删除其他语言资源文件中的 Icon 节点。直接编辑源码,VS是用对应的资源管理器打开的,不好修改。图片内容是 base64 编码的,一下就能找到
|
|
具体可以参考我的这个提交 e2f5f94
坑2:无法修改语言 dll 的生成路径
这是很多使用过 WinForm 国际化方案的人都会说坑爹的地方,网上有很多相关讨论。
国际化后编译生成出来的程序目录下会出现和语言区域同名文件夹,内有相关的资源 dll 。
数量一多强迫症简直不能忍啊,如图:
stackoverflow 搜索一阵以后发现的几个比较靠谱的方案。
- 使用 ILMerge 或者 ILRepack 把 dll 直接嵌入到主程序 exe 中。两个我都试过,直接合并,反编译看到的内部路径是错误的,exe 无法找到相关的资源 dll 。
- 使用 AppDomain.CurrentDomain.AssemblyResolve 方法,在找不到 dll 的时候重新指定 dll 位置进行加载。相关解决方案 Costura 。
- 重写 System.ComponentModel.ComponentResourceManager ,随心所欲的修改生成和加载 dll 的位置与方式,但是方法过于复杂,不推荐。
- 放弃嵌入到 exe 中,修改 dll 的存放目录,然后增加程序集的解析目录。参考:如何控制 C# 引用 DLL 的位置
我最后无奈的使用了方法 4 ,在 App.config 添加如下内容,然后把那些多语言资源文件夹全扔到了 Language 文件夹下。好歹是清爽了点。
|
|
然而又发现如果程序运行的当前目录下 *.exe.config 不存在的话,这个配置不起效。(我 Release 新版本的时候都是删除这个文件的)
只好采用了一个过时方法来增加程序集的解析目录,在窗体载入前加上这行代码就可以了(Program.cs)
|
|