解析大型.NET ERP系統 多國語言實現

實現多國語言有許多種實現方案,無外乎是一種字符串替換技術,將界面控件的文本標籤替換成相應語言的文字。.NET Windows Forms實現多國語言的方法有如下幾種:html

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格式的資源文件,保存一種或多種語言的字符串,運行時根據用戶所選的語言進行界面標籤字符串替換。app

例子Xml字符串文件以下:ide

<?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,分別表明英語,繁體,簡體。spa

字符串爲界面控件標籤上的文字,好比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/

相關文章
相關標籤/搜索