通用多语言方案(1)

通用多语言方案(1)

经过实际项目需求打磨,多语言的要求如下

客户所处环境为zh-cn,环境为en-US,实际用户为不确定,可能是北韩,也能是南韩,也可以东京南,也可以大板北.,操作系统为Windows内核为主,版本从Win98到WinXP,从Win7到Win8,从Win10到Win11,服务端为2008R2/2012

注:微软给我们提供的多语言区域是根据Windows系统所处区域,以及系统初始化安装语言来选择的,但是实际有小语种的区分,

有三种方案,分别是我均踩过坑的,分别是现在流行的PO方案,第三方工具法,资源文件大法

PO方案大法

可参考开源软件:NAPS2(http://www.naps2.com)

该软件的作者很久以前就写了个自动翻译并生成PO文件的代码,并根据PO文件,自动加载多语言资源,我也是参考此作者的开源代码进行了多语言的探索

代码可参考NAPS2.Localization这个,里面写的很详尽了.

切换界面上的语言的代码可在NAPS2.Core\WinForms中找到

第三方工具

曹旭升:http://www.cnblogs.com/sheng_chao/p/5958846.html

曹大佬的工具也是生成资源文件,并加载资源文件内容,具体使用教程不详述,

ResXManager:https://marketplace.visualstudio.com/items?itemName=TomEnglert.ResXManager

资源文件

传统的WinForm,先将窗体的Localizable属性设置为True,再将language属性设置为目标语言,切换到窗体设计界面,对现有的内容进行人肉编辑

但是以上的种种方法均存在2个问题,

1.无法翻译枚举类型,

2.多值显示,即Key/Value组合的数据,多种显示,有下拉框,以及GridView/DataGrid控件

用我的场景解释是,客户是简体中文,操作系统是美式英语,但是操作人员可能是韩国或者朝鲜,甚至还分具体区域,比如说美国,英国,日本等

还有返回的信息,可能提示信息是中文,但是返回的报错信息必须是中文或者英文,因为维护人员是客户,操作员是不分国籍的.

枚举类型的翻译方案选择参考的是<--青青子衿-->的这篇博客https://www.cnblogs.com/jiangyan219/articles/12120552.html

多值显示也即他写的这个方法

使用如下,在枚举文件中加入,

这样的扩展方法,[Display(ResourceType = typeof(DisplayEnumCode), Name = "Pallet")]

需要加入using System.ComponentModel.DataAnnotations;命名空间,此命名空间从3.5时代就有,是ASP.NET框架中的,所以本方法不限版本.

接下来就是编辑并生成,DisplayEnumCode.resx文件,怎么生成如何生成,就都是人肉级别的代码,不多叙述

生成后,可使用ResXManager翻译,半自动人工AI的话可使用百度翻译的API进行翻译.

需要注意的坑点:

1.ResXManager要选择窗体资源文件,人肉翻译要导出为Excel,打开Excel后,需要取消锁定,再进行人肉翻译,翻译完成导入(导入前建议删除掉资源文件正在编辑的资源文件内容),并且控件会进行重新序号,

第三方控件包会自动生成字段的,需要二次加工翻译

2.ResXManager的半自动AI翻译,无法访问是常有的事儿,但是他们默认使用的都是半专业AI的翻译引擎,专业词汇会词不达意,让你哭笑不得,所以请使用人工翻译进行校正,可使用付费专业翻译,或者AI专业翻译,百度翻译,有道,科大讯飞,搜狗翻译

当然也有在线人工翻译的网站,具体水平只能说钱是好东西,但是能找对专业人士才是本事.

3.WinForm的翻译效果以及界面布局,都是需要实际测试的,跟系统设置,以及窗体的AutoScaleMode设置有关系,所以在进行翻译后,建议你切换到你翻译的语言下,针对的重新设置窗体的控件位置以及字体大小

4.字体的选择也很重要,如果选择的字体在语言环境中没有,那你看到的都是火星文或者方块,或者是烫烫烫,请使用微软雅黑字体,此字体全世界微软操作系统都自带默认有,如没有,那你的操作系统版本需要安装兼容多个语言的字体

即有英文和中文,以及韩文显示的.

5.每个多语言所选择的字符集也有区分,并不是和区域挂钩的,所以出现乱码的情况下,并不是统一设置为UTF-8就能解决,而是要去历史悠久的网站找找该死的某国人为什么要使用小语种的字符集(就是宇宙国和大和民族),不是用国际通用的UTF-8或者UTF-16

6.就是中文的话,也有不同的字符集,包括简体中文,所以请问我阿姆卢*刘秀秀,中间那个点会不会是个乱码呢?所以存储的时候一定要切忌这点,否则就是个棍棒伺候,解决办法是查询字符集,这也是个难点.

7.谁敢给自己的中文名称里取个NULL,或者使用不同字符集的特殊符号,请拖走该用户,并友好提示查无此人

8.大佬的方案肯定经过不少项目实战,但是有不少坑点,方案最新的,不一定适合我们国人,请使用人肉翻译以及多个翻译引擎的不同翻译,去校正自己的翻译内容,不然就是挨揍的份儿,更严重的说不得了,所以请注意程序和你之间一定有一个必定是你能跑

9.金额等问题,我没经历过,但是知道部分类型并不通用,且有精度差值,所以用什么类型,并无定论,所以我没有解决方案,但是我知道使用字符串肯定没毛病 ,反正计算的方法不在我这里,谁死就不管了哦

10.以上提到的所有方法均适用Windows操作系统环境,均以C#语言,WinForm为主,第三方控件为主

提供两个好用的扩展方法,也是从开源网站获取以及各大博客园博主的类库中提取,分别是获取上文中的描述属性,以及转为String转为枚举类型

ToDescription方法是扩展了任意的枚举,可在枚举类型.ToDescription中获取到枚举类型的描述字段内容,以此类推,可以尽情获取需要的类型

ToEnum方法是扩展了String类型,可"".ToEnum<枚举类型>()自动将任意字符串转为对应的枚举类型.

public static string ToDescription(this Enum value)
{
    if (value == null) return string.Empty;

    System.Reflection.FieldInfo fieldInfo = value.GetType().GetField(value.ToString());

    object[] attribArray = fieldInfo.GetCustomAttributes(false);
    if (attribArray.Length == 0)
        return value.ToString();
    else
        return (attribArray[0] as DescriptionAttribute).Description;
}

public static T ToEnum<T>(this string value, T defaultValue = default(T)) where T : struct
{
    if (!typeof(T).IsEnum)
    {
        throw new ArgumentException("Type T Must of type System.Enum");
    }

    T result;
    bool isParsed = Enum.TryParse(value, true, out result);
    return isParsed ? result : defaultValue;
}

 

posted on 2022-08-31 18:06  澜紫癜青  阅读(203)  评论(0编辑  收藏  举报

导航