提供多國使用者的軟件,界面上的文字也需要能夠切換成不同的語言,這被稱作多語言化。WinCC的控件中中的文本可以分別輸入中文和英文來實現多語言化,在這里輸入的文本會被添加到WinCC項目數據庫的TXTTable表中,在WinCC的文本庫頁面可以對翻譯的內容進行編輯。但是在腳本中也有許多用於提示或記錄的文本,WinCC沒有為腳本中的文本提供翻譯的功能。
在過去的一些項目中見過兩種簡陋的解決方法,一種是在腳本中分別寫兩條不同語言的文本,然后用if/else判斷當前語言環境,從中選擇一條文本輸出,這樣做的缺點是需要在寫代碼時去翻譯其中的文本,而且夾雜了用於多語言的語句,使得代碼的可讀性特別差;另一種方法是把多語言化的代碼提取出來封裝成函數,在函數中集中翻譯,這種方法相比前一種更加合理,但是同樣是用if/else翻譯文本,代碼示例如下,可見並不利於查看和編輯,如果需要再添加第三種語言,此刻就會非常難操作。
借鑒上述的第二種方法,在代碼用一個函數翻譯文本,但函數中用其他更好的方法去實現文本的翻譯,所用的方法要滿足以下要求:
- 能夠在類似於Excel表格的環境中編輯翻譯的文本;
- 需要添加其他語言的翻譯時,能夠方便的添加;
- 能夠隨項目移植,即存儲翻譯文本的文件能夠隨項目程序拷貝;
- 項目中經常需要集成兩個不同部分的項目程序,所以要能夠方便的將兩個項目程序的翻譯整合在一起。
根據上述要求的限制,如下一些方法將不能采用:
- 不便於依靠WinCC文本庫的TXTTable數據庫表存儲腳本中的翻譯,實際使用中文本庫中的內容非常混亂,不能確定哪些文本是腳本翻譯中需要的,整合兩個項目的程序時不便於操作,不能滿足第4點要求。
- 不能另建一個數據庫存儲翻譯文本,也不能用用戶歸檔存儲翻譯文本,因為拷貝項目時不會拷貝數據庫中的數據,不能滿足第3點要求。
目前所想到的較好的方法是用CSV文件存儲翻譯文本,依靠ADO對象能像數據庫一樣用SQL查詢CSV文件的內容;可以用Excel打開CSV文件進行編輯;需要添加其他語言時只需再CSV文件中新增一列,不需修改腳本;把CSV文件放在項目程序文件夾下,會隨着項目程序一起拷貝。下面將介紹具體實現方式。
腳本內文本多語言化的函數示例
函數語法如下:
Function TranslateText(text, iLangID)
參數:
- text:輸入的原文本;
- iLangID:輸入文本的語言ID。
返回值:
- 如果當前語言環境與輸入的語言ID相同,則返回原文本,如果不同,則查詢原文本對應的翻譯文本並返回該文本。
示例如下:
HMIruntime.Trace TranslateText("abc", 1033)
語言ID的全稱叫區域標志符(locale identifier,縮寫為LCID),WinCC支持的語言及對應的LCID如下:
- 1028 – Chinese (traditional)
- 1031 – German
- 1033 – English
- 1034 – Spanish
- 1036 – French
- 1040 – Italian
- 1041 – Japanese
- 1042 – Korean
- 2052 – Chinese (Simplified)
對於其他語言,雖然在WinCC中不支持,但是依然可以應用於腳本文本多語言化。其他地區的LCID可以從如下網站查詢:
http://www.mytju.com/classCode/tools/LCID.asp
如何存儲翻譯文本
用CSV文件存儲翻譯文件,用Excel打開CSV文本示例如下:
- ID:是一條文本的順序號,翻譯的代碼並不依靠ID,因此ID可以隨意更改,只要不與其他ID重復;
- TextGroup:這是一個預留的字段,用於對翻譯文本分組,因為工作中的WinCC程序經常要集成其他部門的程序,通過文本分組便於翻譯;
- SourceLcid:說明代碼以哪個語言的文本去查詢翻譯,這個字段提供給翻譯者查看,告訴翻譯者不要去修改原文本,只能修改其他需翻譯的文本;
- L1033:英文文本;
- L2052:中文文本。
如果需要添加第三種語言,只需新增一列,列名用“L”+LCID命名。例如新增德文,新增一列命名為“L1031 ”,然后該列下面填寫翻譯。
CSV是一個以逗號分隔內容的文本,用記事本打開顯示如下。
通過ADO查詢CSV文件要求字符是ANSI編碼,否則查詢出的漢字是亂碼,而用Excel編輯CSV文件時要求字符編碼是UTF-8,否則看到的漢字都是“????”,保存后漢字的內容也就丟失了。這是目前尚未解決的缺陷,編輯時要記得對文件轉碼。用記事本打開CSV文件,點擊“另存為”可以修改文件編碼。
CSV文件的同一文件夾下還需要有個schema.ini文件,該文件說明了CSV文件的分隔符,如何判斷列的類型等。如果沒有schema.ini文件,ADO會根據windows注冊表的配置值去處理CSV文件,有可能在某些電腦上不一致,導致讀取失敗,所以要建立schema.ini。schema.ini文件內容如下。
[Language.csv] Format=CSVDelimited DecimalSymbol=. ColNameHeader=True Col1=ID Long Col2=TextGroup Text Col3=SourceLcid Short Col4=L1033 Text Col5=L2052 Text
關於schema.ini文件的詳細介紹可以查閱微軟官方文檔:https://docs.microsoft.com/zh-cn/sql/odbc/microsoft/schema-ini-file-text-file-driver?view=sql-server-ver15
如何用ADO查詢CSV文件
ADO除了可以查詢關系型數據庫,也可以查詢非關系型數據源,例如CVS文件。建立ADO連接需指定一個“Provider”,即驅動引擎,查詢CSV文件用的“Provider”是“Microsoft.Jet.OLEDB.4.0”或“Microsoft.ACE.OLEDB.12.0”,Jet引擎可以訪問office 97-2003,ACE引擎是新的,可以訪問Office 2007,對於訪問CSV文件這兩個引擎沒有太多區別。
WinCC附帶安裝的SQL Server中帶有“Microsoft.Jet.OLEDB.4.0”,從Server Objects -> Linked Server -> Providers中可以查看到。
關於ADO的詳細使用說明可以查閱微軟官方文檔:https://docs.microsoft.com/zh-cn/sql/ado/guide/appendixes/using-ado-with-microsoft-visual-basic
多語言函數的實現
存儲多語言翻譯文本的文件命名為Language.csv,Language.csv和schema.ini都存儲在項目文件路徑內的“\GraCS\Translation”文件夾下。
首先TranslateText()函數會通過傳入的語言ID與當前環境語言ID對比,判斷是否需要翻譯,如果輸入的文本與當前環境語言一致則直接輸入,不需要經過翻譯。如果需要翻譯,則查詢Language.csv文件中對應文本的翻譯。如果翻譯者還未填入翻譯內容,即翻譯文本為空,那么還是輸出原文本。如果Language.csv文件中查詢不到輸入的文本,說明這條文本是代碼中新加的,將通過代碼在CSV文件中新加一條數據,翻譯者補充翻譯內容后再執行該函數就可以輸出翻譯內容。
Function TranslateText(text, iLangID) ' '根據語言ID判斷是否需要翻譯 ' If HMIRuntime.Language = iLangID Then ' TranslateText = text ' Exit Function ' End If If Trim(text) = "" Then TranslateText = "" Exit Function End If Dim conn, connStr, rs, SQL Dim dataDir Set conn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") '把CSV文件作為數據源用SQL查詢 dataDir = HMIRuntime.ActiveProject.Path & "\GraCS\Translation" connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dataDir & ";Extended Properties='text';FMT=Delimited" conn.ConnectionString = connStr conn.Cursorlocation = 3 conn.Open '查找最大ID Dim NextId SQL = "SELECT Max(ID) as MaxId FROM [Language.csv] " rs.Open SQL, conn, 1, 3 If IsNULL(rs("MaxId")) Then NextId = 1 Else NextId = rs("MaxId") + 1 End If rs.Close '查詢指定文本的翻譯 SQL = "SELECT * FROM [Language.csv] where L"& iLangID &" = '"& text & "'" rs.Open SQL, conn, 1, 3 ' HMIRuntime.trace rs.Fields.Count & " columns found." &vbNewline ' Dim field ' For Each field In rs.Fields ' HMIRuntime.Trace field.Name&vbNewline ' Next If Not rs.EOF Then If IsNUll(rs("L"& HMIRuntime.Language)) Or Trim(rs("L"& HMIRuntime.Language)) = ""Then TranslateText = text '無翻譯則輸出原內容 Else TranslateText = rs("L"& HMIRuntime.Language) '取得翻譯的文本 End If Else TranslateText = text '添加新的翻譯 rs.AddNew rs("ID") = NextId rs("SourceLcid") = iLangID rs("L"& iLangID) = text rs.Update End If rs.Close conn.Close Set rs = Nothing Set conn = Nothing End Function
關於ADODB.Connection對象的使用查看:https://docs.microsoft.com/zh-cn/sql/ado/reference/ado-api/connection-object-ado
關於ADODB.Recordset對象的使用查看:https://docs.microsoft.com/zh-cn/sql/ado/reference/ado-api/recordset-object-ado