實現多國語言有許多種實現方案,無外乎是一種字符串替換技術,將界面控件的文本標簽替換成相應語言的文字。.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或一些在線翻譯工具。
將存儲過程和語言轉換的方法封裝起來,做成一工具,輸入要翻譯的資源字符串和簡體翻譯,生成存儲過程調用。
程序啟動時,設計一個翻譯資源緩存字典表,分別存放對應語言的鍵值對。
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提供的解決方案,地址是
這篇問答中提到幾個工具,這幾個工具的網站都可以打開,讀者若是在尋找多國語言方案,可實際操作體會一下。
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/