解析大型.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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM