WinCC脚本内文本多语言化的一种方法


提供多国使用者的软件,界面上的文字也需要能够切换成不同的语言,这被称作多语言化。WinCC的控件中中的文本可以分别输入中文和英文来实现多语言化,在这里输入的文本会被添加到WinCC项目数据库的TXTTable表中,在WinCC的文本库页面可以对翻译的内容进行编辑。但是在脚本中也有许多用于提示或记录的文本,WinCC没有为脚本中的文本提供翻译的功能。

在过去的一些项目中见过两种简陋的解决方法,一种是在脚本中分别写两条不同语言的文本,然后用if/else判断当前语言环境,从中选择一条文本输出,这样做的缺点是需要在写代码时去翻译其中的文本,而且夹杂了用于多语言的语句,使得代码的可读性特别差;另一种方法是把多语言化的代码提取出来封装成函数,在函数中集中翻译,这种方法相比前一种更加合理,但是同样是用if/else翻译文本,代码示例如下,可见并不利于查看和编辑,如果需要再添加第三种语言,此刻就会非常难操作。

 借鉴上述的第二种方法,在代码用一个函数翻译文本,但函数中用其他更好的方法去实现文本的翻译,所用的方法要满足以下要求:

  1. 能够在类似于Excel表格的环境中编辑翻译的文本;
  2. 需要添加其他语言的翻译时,能够方便的添加;
  3. 能够随项目移植,即存储翻译文本的文件能够随项目程序拷贝;
  4. 项目中经常需要集成两个不同部分的项目程序,所以要能够方便的将两个项目程序的翻译整合在一起。

根据上述要求的限制,如下一些方法将不能采用:

  • 不便于依靠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