• 解析大型.NET ERP系统 多国语言实现


    实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字。.NET Windows Forms实现多国语言的方法有以下几种:

    1 .NET的方案,使用资源文件

    分别做三个语言的资源文件,比如String.resx,String.zh-cn.resx,String.zh-tw.resx,编译程序集,运行时用下面的代码设置程序的语言区域。

    string languageName="zh-cn";
    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(languageName)  
    Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(languageName)  
    

    2 使用Xml格式的资源文件

    创建Xml格式的资源文件,保存一种或多种语言的字符串,运行时根据用户所选的语言进行界面标签字符串替换。

    例子Xml字符串文件如下:

    <?xml version="1.0"?>
    <configuration>
    <add key="Login"   Default="Login"     zhcn="登录"         zhtw="登錄"  />
    <add key="UserId"  Default="User Id"   zhcn="用户编码"     zhtw="使用者編碼"  />
    </configuration>
    

    3 数据库方案

    将语言资源字符串存放在数据库中,运行时读取并替换,这是我推荐的方案。

    设计语言翻译数据库表,用于存放语言翻译内容,表结构如下:

    CREATE TABLE [dbo].[LanguageTranslation]
    (
    [LanguageCode] [nvarchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [KeyText] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT,
    [DisplayText] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [CreatedDate] [datetime] NULL,
    [CreatedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [RevisedDate] [datetime] NULL,
    [RevisedBy] [nvarchar] (10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
    ) ON [PRIMARY]
    GO
    ALTER TABLE [dbo].[LanguageTranslation] ADD CONSTRAINT [PK_LanguageTranslation] PRIMARY KEY CLUSTERED  ([LanguageCode], [KeyText]) ON [PRIMARY]
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'翻译', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', NULL, NULL
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'语言编码
    0  英语
    1  繁体中文
    2  简体中文
    ', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'LanguageCode'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'索引词', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'KeyText'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'显示词', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'DisplayText'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'创建日期', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'CreatedDate'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'建立人', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'CreatedBy'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'修改日期', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'RevisedDate'
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'修改人', 'SCHEMA', N'dbo', 'TABLE', N'LanguageTranslation', 'COLUMN', N'RevisedBy'
    GO

    我以Language Code和相应的字符串为主键,Language Code的值是0,1,2,分别代表英语,繁体,简体。

    字符串为界面控件标签上的文字,比如User Id, Department等。

    为方便编辑字符串资源,增加一个存储过程,用于增加和修改语言资源:

    SET QUOTED_IDENTIFIER ON
    SET ANSI_NULLS ON
    GO
    CREATE PROCEDURE [dbo].[spAddTranslationText]
    @KeyText nvarchar(200),
    @EnglishText nvarchar(200),
    @ChtText nvarchar(200),
    @ChsText nvarchar(200)
    AS
    BEGIN
    
    SET NOCOUNT ON;
    SET @KeyText = UPPER(@KeyText)
    DELETE LanguageTranslation WHERE KEYTEXT = @KeyText
    
    INSERT LanguageTranslation (LANGUAGECODE, KEYTEXT, DISPLAYTEXT, CREATEDDATE, CREATEDBY, REVISEDDATE, REVISEDBY)
    VALUES ('0', @KeyText, @EnglishText, GETDATE(), 'MIS', GETDATE(), 'MIS')
    
    INSERT LanguageTranslation (LANGUAGECODE, KEYTEXT, DISPLAYTEXT, CREATEDDATE, CREATEDBY, REVISEDDATE, REVISEDBY)
    VALUES ('1', @KeyText, @ChtText, GETDATE(), 'MIS', GETDATE(), 'MIS')
    
    INSERT LanguageTranslation (LANGUAGECODE, KEYTEXT, DISPLAYTEXT, CREATEDDATE, CREATEDBY, REVISEDDATE, REVISEDBY)
    VALUES ('2', @KeyText, @ChsText, GETDATE(), 'MIS', GETDATE(), 'MIS')
    
    END
    
    GO
    

    为了简化简体到繁体的转化,调用.NET  VB类库中的方法,实现简体转化为繁体的功能,简体转化为繁体:

    public string ConvertToTraditionalChinese(string label)
    {
        return Strings.StrConv(label, VbStrConv.TraditionalChinese, 0);
    }
    

    基本上满足需求,转换的准确率不如Word或一些在线翻译工具。

    将存储过程和语言转换的方法封装起来,做成一工具,输入要翻译的资源字符串和简体翻译,生成存储过程调用。

    image

    程序启动时,设计一个翻译资源缓存字典表,分别存放对应语言的键值对。

    private static Dictionary<int, DataTable> _cachedLanguageTranslation;
    

    以下的代码从数据库中读取翻译数据到内存中,参考

    DataTable languageTable = null;
    DbFunctionCall isNullDisplayText = new DbFunctionCall("ISNULL", new object[] { LanguageTranslationFields.DisplayText, string.Empty });
    EntityField2 displayTextField = new EntityField2("DisplayText", isNullDisplayText);
    ResultsetFields fields = new ResultsetFields(2);
    fields.DefineField(LanguageTranslationFields.KeyText, 0, "KeyText");
    fields.DefineField(displayTextField, 1, "DisplayText");
    
    ISortExpression sortExpression = new SortExpression(LanguageTranslationFields.KeyText | SortOperator.Ascending);
    
    using (DataAccessAdapterBase adapter = GetSystemDataAccessAdapter())
    {
             languageTable = new FastSerializableDataTable();
             languageTable.RemotingFormat = SerializationFormat.Binary;
    
             IRelationPredicateBucket bucket = new RelationPredicateBucket();
             bucket.PredicateExpression.Add(LanguageTranslationFields.LanguageCode == languageCode);
             bucket.PredicateExpression.Add(displayTextField != string.Empty);
             bucket.PredicateExpression.Add(LanguageTranslationFields.KeyText != displayTextField);
    
             adapter.FetchTypedList(fields, languageTable, bucket, 0, sortExpression, false);
    
    

    最后,设计一个公共接口方便调用:

    //Shared.cs
    public static string TranslateText(string textToTranslate)
    {
           return LanguageTranslator.TranslateText(textToTranslate);
    }

    用数据库作为ERP多国语言实现方案有以下几个原因:

    1  资源字符串可以被修改。这是最主要的原因,软件公司以程序员为主,没有实际的行业经验,不足以恰当(信,达,雅)的设计出各行业的翻译。产品发布到客户后,还可以修改资源字符串,不合理的地方以用户的经验为主。

    2  资源字符串部署。以数据库表作为字符串资源的存储方式,部署时只需要发布SQL语句文件即可。

    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N'-- PRODUCTION REQ --', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N'-- LOC.TOTAL_QTY. --', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N'-- LOC TOTAL_QTY. --', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N'--- JOB ---', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N' DR ', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N' DISC. ALLOWED ', N'')
    
    INSERT INTO [LanguageTranslation] ([LanguageCode],[KeyText],[DisplayText])
    VALUES(N'0', N'-------------- DEMAND --------------', N'')
    
    

    写完了多国语言实现方案,意犹未尽,去Google上搜索一下stackoverflow提供的解决方案,地址是

    http://stackoverflow.com/questions/373388/best-way-to-implement-multi-language-globalization-in-large-net-project

    http://stackoverflow.com/questions/119568/best-practice-to-make-a-multi-language-application-in-c-winforms

    这篇问答中提到几个工具,这几个工具的网站都可以打开,读者若是在寻找多国语言方案,可实际操作体会一下。

    Sisulizer   http://www.sisulizer.com/

    WPF LocalizationExtension  http://wpflocalizeextension.codeplex.com/

    GetText http://gnuwin32.sourceforge.net/packages/gettext.htm

    DBResource Provider  http://www.west-wind.com/presentations/wwDbResourceProvider/

  • 相关阅读:
    iOS开发UIKit框架-可视化编程-XIB
    ios swift例子源码网址总结
    两个单链表相交问题
    库函数atoi
    C++类型萃取
    【Swift】iOS导航栏错乱的原因
    【Swift】iOS裁剪或者压缩后出现的白边问题
    Linux进程调度分析
    【scala】可变与不可变的理解
    【scala】模式匹配
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/4722929.html
Copyright © 2020-2023  润新知