在实际项目里,但凡给客户做TestStand测试工位,十个里面有八个会问同一个问题:这个界面能不能显示中文?尤其客户是国内的电子制造厂,产线上操作员英语水平参差不齐,一个全英文的Operator Interface摆在那里,误操作率极高。我印象最深的一次,客户验收时直接说“界面不改成中文,这项目我们没法签”。但真做起来才发现,TestStand的用户界面语言本地化远不是“设置里切个语言”那么简单——它有Sequence Editor、Operator Interface、报表、数据记录好几层,每一层的处理方式都不一样。
写这篇东西,是给正在做或者准备做TestStand工位交付的测试工程师、自动化项目负责人看的。我会把TestStand本地化的官方能力边界、我踩过的编码坑、自定义OI的多语言设计方案、以及一个真实中英文切换项目的实施过程都拆开讲。搞清楚这些,你至少能避开我当年走过的弯路。
1. 本地化范围先理清楚:Sequence Editor、Operator Interface和报表是三条线
很多第一次做TestStand本地化的人,第一反应是去“设置”里翻有没有语言下拉框。有,但这只是冰山一角。TestStand这套软件跟普通办公软件不一样,它不是一个单一的EXE,而是由开发环境(Sequence Editor)、执行引擎(Engine)、操作员界面(Operator Interface)、处理模型(Process Model)、报告生成器一整套组成。每一部分的本地化机制都不同,如果混为一谈,后面一定会乱。
1.1 官方语言包到底能管多少事
从TestStand 4.0开始,NI就为Sequence Editor提供了多语言界面支持。安装的时候,在NI Package Manager里可以勾选对应的语言包,比如中文(简体)、日文、韩文、德文、法文等。装好之后,在Sequence Editor里进入Tools»Options»General,把Language切到简体中文,重启编辑器,菜单、工具栏、对话框这些原生界面就会变成中文。
注意,这里有两个关键限制。第一,语言包是可选的,默认安装未必会装;第二,它只管Sequence Editor以及TestStand Engine弹出的标准对话框,管不到你自定义的Operator Interface。我在项目里见过有人把编辑器切成了中文,就以为产线工位界面也一起变了,结果一运行自研OI,满屏还是英文,当场无语。Sequence Editor是开发调试工具,正常情况下不会摆在产线上给操作员用,所以官方语言包解决的是“开发人员看不看得懂”的问题,而不是“操作员看不看得懂”的问题。
1.2 项目里最常见的误区:改完界面语言,报表还是英文
比OI界面更常被忽略的,是报表和日志。很多项目的验收标准是测试报告必须是中文的——操作员能看懂Pass/Fail、“测试通过/失败”,但TestStand默认生成的HTML报告,模板是纯英文的,而且状态那栏出现的Passed、Failed并不会因为界面语言切换而跟着变。为什么?因为报告是用XSLT模板生成的,模板里写的是英文标签,跟Sequence Editor的界面语言是两个完全独立的体系。
所以做本地化需求梳理时,我建议第一件事不是写代码,而是画一张清单,把项目里所有会出现人可读文本的地方列出来。我自己的分类通常是这样:
- 开发环境:Sequence Editor菜单、配置对话框——官方语言包覆盖。
- 产线界面:自定义OI的按钮、标签、标题栏、状态栏信息——自己做语言映射。
- 流程中的动态消息:MessagePopup、注释字符串、Stop/询问对话框——信号源在序列里,需要序列配合。
- 报表输出:HTML/XML/PDF报告里的标题、表头、状态、总结——改XSLT模板。
- 数据记录:数据库表字段、导出的CSV——靠编码和字段定义保证。
这五类做好了,才算真正完成了一个工位的本地化。只想改其中一两个模块的,建议直接跳过去。
2. 字符编码与字体:本地化项目里最容易翻车的地基
代码没写几行,先被乱码搞崩——这是我在好几个多语言项目里的真实经历。做TestStand本地化,第一个要面对的其实不是“翻译”,而是“编码”。TestStand底层很多字符串处理、文本文件读写都遵循Windows ANSI的旧习惯,一旦碰上中文,各种乱码就会冒出来。
2.1 系统“非Unicode程序语言”设置:隐形地雷
Windows控制面板里有一个“更改系统区域设置”选项,里面可以选择“非Unicode程序的语言”。这个设置对TestStand影响非常大。如果你把系统区域设置成英语(美国),而某个TestStand相关组件生成文本时又没走Unicode,那中文就会变成“??????”或者一团乱码。反之,如果区域设成中文(简体,中国),TestStand写出来的ANSI文本就能正确显示中文。
我在项目里遇到过一次很典型的情况:工位电脑在出厂镜像里设置了英语区域,TestStand序列里用WriteToFile写了一个包含中文步骤名的日志文件,用记事本打开全乱。后来把系统区域改成中文并重启,同样一段代码写出来的文件就正常了。如果你的工位电脑需要保留英文区域,那就得尽量让所有涉及中文的文件都走Unicode编码,别依赖ANSI隐式转换。
另外,系统区域设置还会影响就地安装的第三方组件、驱动程序,甚至某些DAQ驱动的默认语言行为。所以这个问题必须在项目部署前就定下来,不要等现场跑起来再改,否则你会陷入“这台电脑能用,那台电脑乱码”的玄学困境。
2.2 HTML报告模板的charset和字体坑
TestStand默认的HTML报告,其实是通过XSLT模板渲染的。模板文件的位置一般在TestStand安装目录下的Components...\ReportTemplates里面,最常见的是DefaultReport.xsl或类似名称。如果这个模板的头部没有明确指定中文字符集,浏览器打开报告时就会按默认编码解析,中文很容易变乱码。
解决的方法很简单:用文本编辑器打开对应的.xsl文件,在head标签里加一行:
<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Test Report</title> </head>改完保存,再生成一次报告,通常中文就正常了。但注意,如果报告里嵌入了中文注释、中文步骤名称,而模板指定的字体不是中文字体,显示出来也有可能是方块。更稳妥的方案是把样式表里的字体族改成“Microsoft YaHei, SimSun, sans-serif”这类带中文回退的字体组合,这样在中文Windows上就能正常显示。
2.3 数据库与CSV导出的中文乱码约定
测试结果要落数据库的话,编码问题会换个马甲继续出现。以SQL Server为例,如果表字段用的是varchar,而写入的中文走的是GBK编码,可能存进去正常、读出来乱码,甚至直接报字符串截断。最痛快的做法是字段类型直接用nvarchar/nchar,这是Unicode类型,中文和英文都能统一处理。
如果是CSV导出,Excel默认用ANSI解析CSV文件,生成UTF-8编码的CSV时中文可能乱码。常见解决办法是写文件时加上UTF-8 BOM,或者按Excel兼容的方式用GB2312/GBK编码输出。这两种方案看你的下游是谁:给MES系统用的,一般UTF-8没争议;给产线工程师用Excel打开看的,加BOM更省心。
3. 自定义Operator Interface的多语言方案设计与落地
真正决定产线操作员感受的,是Operator Interface。因为各家测试需求不一样,绝大多数项目里的OI都是自己用LabVIEW、C#或者.NET开发的。这里的本地化,没有官方一键按钮,全靠自己在架构上做设计。
3.1 先选一个能维护的语言包载体
语言映射关系放哪,基本就决定了后期维护的难度。我见过有人直接把所有字符串写在VI的Case结构里,界面上放一个Enum控件,选中文就执行中文分支,选英文就执行英文分支。小Demo没问题,但几十个控件的工位,Case分支会膨胀到没法看,客户还要隔三差五改文案,每次都得改源码重新编译。
比较务实的是把翻译丢到外部文件里,运行时动态加载。我个人最常用的是INI文件,结构简单,Excel可以直接编辑,现场不懂代码的工程师也能改。
[Chinese] MainTitle=功能测试工位 PassText=测试通过 FailText=测试失败 StartButton=开始测试 StopButton=停止测试 [English] MainTitle=Functional Test Station PassText=PASS FailText=FAIL StartButton=Start Test StopButton=Stop Test如果你的团队更习惯XML或者JSON,当然也可以,核心是一样的:控件标识符作为键,不同语言作为值。用外部文件的好处是,客户想改某个叫法,不用找你重新发版本,自己拿记事本改一下就能生效。
3.2 语言切换的两种触发时机
语言切换机制要考虑好“什么时候切”。我做过两种模式,各有各的适用场景。
一种是启动时加载。OI启动时先读本机配置文件,比如LocalConfig.ini里的Language=Chinese,然后在初始化阶段把语言包读进内存,一次性刷新所有控件文本。这个方式最稳定,适合工位语言固定、不需要频繁切换的场合。缺点是你改完语言选择,要重启程序才生效。
另一种是运行时即时切换。也就是说界面上放一个中/英切换控件,操作员一点,整个界面马上刷新。实现上其实不算复杂,关键是不要只改当前控件的Caption,而是把涉及字符串的地方统一走一个更新函数。尤其要小心状态机、轮询线程里正在显示的提示信息,切换语言时要有一个安全时机,否则容易出现“界面上半中半英”的中间态。我在项目里会把刷新动作放在主界面的Idle事件里处理,避免跟后台测试流程抢占资源。
3.3 一套可以直接抄的OI文本刷新流程
这里我以LabVIEW开发的OI为例,因为在测试行业LabVIEW还是占了很大比例。大致思路是这样:程序启动时读配置文件,确定语言;调用一个构建语言映射的子VI,把INI文件解析成字符串数组或Map;然后用一个RefreshUI子VI遍历所有需要本地化的控件,按控件的Tag值去语言映射里查新文本,再写入Caption属性。
控件比较多的话,建议统一规范Tag命名,比如所有主界面按钮都写成“Btn_Start”“Btn_Stop”这种形式,跟语言文件里的键名严格对应。这样语言文件里的键名、代码逻辑里的Tag、界面上的控件三者一一对应,排查问题会非常快。我在现场调试时,遇到某个按钮没翻译过来,第一件事就是检查控件Tag是不是跟语言文件里的键名拼写不一致——大部分“奇怪问题”都出在这种低级错误上。
如果OI里有些动态文本,比如“正在测试第3个工位”,不能简单做整句翻译,那就多用格式化字符串。
Status_Testing=正在测试第%d个工位代码里读取后调用格式化函数填入序号,这样就避免了反复拼接字符串导致的中英文语序问题。
4. Sequence Editor的汉化:为什么我不建议去动TestStand资源DLL
你在搜索引擎里找TestStand汉化资料时,大概率会看到一些“修改资源文件实现汉化”的偏方。比如用Resource Hacker打开TestStand安装目录下的某个DLL,把里面的英文菜单字符串改成中文。我明确说,这条路能不走就别走。
4.1 改资源文件的诱惑和代价
刚接触TestStand的人很容易动这个念头:既然官方语言包没有覆盖某些对话框,那我自己改DLL字符串不就行了?但TestStand作为商业软件,它的核心组件是有数字签名的,强改二进制资源后,程序可能直接拒绝加载,或者在后续版本升级、修复安装时被自动还原。更麻烦的是,一旦改了DLL,你很难判断某个偶发异常到底是自己代码问题还是改了系统组件导致的,排错成本骤增。
还有一个现实问题:TestStand内部很多字符串不是简单的“菜单文字”,它们会作为标识符参与程序逻辑判断。你在界面层看到一个“OK”,代码里可能拿的是“OK”这个字符串做匹配。如果只改了显示层,逻辑层没改,就会造成显示正常但功能异常的诡异Bug,这种问题拿到客户现场几乎没法解释。
4.2 官方支持的本地化路径到底有哪些
官方的路径其实很清晰,只是很多项目没注意到。
第一,安装时选语言包,让Sequence Editor原生界面变成目标语言,这个前面已经说过,是最推荐的。第二,对于自定义部分,NI的文档一直建议开发者使用可以本地化的字符串资源,而不是把文本硬编码。第三,如果不想在每台电脑上装语言包,也可以把语言配置文件随部署包一起分发,关键是别去动安装目录下的二进制文件。
部署层面也有一个容易被忽略的点。如果你需要给十台工位电脑批量安装语言包,别一台台打开NI Package Manager去勾选。用命令行静默安装,或者直接把装好语言包的工位做成镜像,会省很多事。语言包文件本质上就是若干资源文件,确认好版本和目录后,部署时只要版本一致放到对应路径也可以,但我个人更推荐走正规安装流程,避免版本不一致导致界面有些翻译失效。
另外提醒一句:TestStand帮助文档本身也有语言版本可选,可以配合界面语言一起安装。文档虽然是给开发人员看的,但项目交接时如果客户那边有人要看,至少不会因为语言问题增加沟通成本。
5. 报表和日志的中文化:客户真正盯着看的往往是这里
前面说了不少界面上的事,但很多项目里,客户逼得最紧的其实是报表。操作界面他们可能只要求按钮看得懂,但一张全是英文的报告要发给质量部、发给客户,那就不行了。所以报表和日志的语言本地化必须单独拿出来讲。
5.1 报告模板的本地化修改
TestStand的报告模板机制,本质上是把测试结果数据用XSLT转换成HTML/XML等格式。因此,报告里出现的所有固定文本——标题“Test Report”、表头“Step Name”“Result”“Units”等——都可以在XSLT模板里改。你直接把模板里的英文表头替换成中文,例如:
<xsl:for-each select="..."> <th><xsl:text>步骤名称</xsl:text></th> </xsl:for-each>保存后,下一次生成的报告就会用中文表头。不过工程上更细致一点的做法,是判断结果状态时分别输出“通过/失败/警告”,而不是简单按字面翻译。比如Passed对应“通过”,Failed对应“失败”,Warning对应“警告”。很多XSLT模板里已经有一个条件判断块来输出状态文本,你只要把那段文本换成中文即可。
还有一类文本是“在序列里写的步骤注释”,比如操作员在测试中途弹窗输入了备注。这些文本本身是数据,不是模板文本,所以模板改不改不影响它。但报告生成时字符集不对,一样会显示乱码。这就回到第2章说的charset了,模板和字符编码必须一起处理。
5.2 测试步骤、结果状态和错误消息的多语言做法
严格来说,TestStand的步骤名称、表达式、结果状态在引擎内部是英文体系,比如序列文件里StepName就是“Step Name”。但是展示层是可以做多语言的。项目里比较常见的做法是:StepName保留英文,因为工程师要知道对应哪条测试项;但报告里的Summary、状态、错误说明做成跟随语言设置的动态文本。
这里要区分“界面显示语言”和“报告语言”是不是必须同步。有的客户要求OI上切中文时报告也中文,切英文时报告也英文;但也有的客户无论操作员用什么语言,报告统一英文,因为要发给总部。面对后面这种需求,你最好在设计语言映射时就留出独立的ReportLanguage变量,不要让它跟界面语言强绑定。
错误消息的多语言相对麻烦。因为错误消息可能发生在底层驱动、测量板卡、TestStand引擎内部等各个层面,很难完全控制。我的原则是:测试工程师自己写的错误提示,一律通过多语言字典取字符串;第三方驱动抛出的原始错误信息,原样记录到日志里,同时在界面和报告里附上一句本地化的通用说明,比如“设备通信失败,请查看错误详情”。这样既保证了本地化体验,又不丢失纯英文环境下的技术细节。
6. 一个中英文切换工位项目的完整实施记录
理论讲得再多,不如讲一次完整落地。这个项目是给某电子制造商做的产线功能测试工位,客户要求操作员界面支持中英文一键切换,测试报告输出中文,同时要给MES系统提交数据。我把整个实施过程复盘一下,每个环节有什么坑也一并列出来。
6.1 需求梳理与方案选型
项目开始,我先跟客户确认了几个关键问题:序列编辑器要不要中文?产线OI是使用TestStand自带的还是定制?报告是HTML还是进数据库?操作员是固定中文还是需要自由切换?客户当时回答:OI必须定制,而且操作员有外籍员工,所以要能切换;报告要求HTML中文,同时数据要给MES,编码必须UTF-8。
基于这些需求,方案就定为:OI用LabVIEW开发,语言包用INI,启动时读取本机语言配置,界面上放一个中/英切换按钮;序列里的动态提示消息从同一个语言字典取;报告用TestStand的XML数据源配合自定义XSLT模板输出中文HTML;MES接口单独走UTF-8编码的JSON/XML。
6.2 分步实施过程
第一步,先做字符集地基。所有工位电脑系统区域设置为中文(简体,中国),数据库连接字符串明确标注字符集,XSLT报告模板加UTF-8声明。这一步不做,后面所有中文都会出幺蛾子。
第二步,写语言包。我按照OI上的每个控件先列出清单,生成键名表。然后让客户帮忙确认翻译,这步别自己拍脑袋。特别是“开始测试”“测试通过”“异常报警”这些产线上每天要看几百次的话,翻译一定要符合客户现场的习惯用语,不要按字面直译。
第三步,实现OI加载和切换逻辑。INI文件放工位目录的Config文件夹下,程序启动时读一次,切换按钮触发时刷新一次。主界面上的Tab页标题、按钮、Label、状态栏文本全部带Tag,统一走到RefreshUI方法。
第四步,序列与OI通信。TestStand序列通过全局变量或属性跟OI交换语言设置,比如设置一个Global变量LanguageCode,OI切换时写这个变量,序列里的MessagePopup、ReportText都根据LanguageCode取对应语言字符串。这一步需要跟写序列的同事约定好,别两边各搞一套。
第五步,报告模板改造。把表头、状态文本全部中文化;步骤名称保留英文,但每一步加一列“步骤描述”,由序列输出中文说明。客户看到报告后很满意,因为工程师能对英文步骤名,操作员和管理层能看中文描述,两边需求都满足了。
6.3 验证结果与踩坑清单
交付前,我们在两台工位电脑上做验证,一台中文系统一台英文系统。结果英文系统那台,在没改区域设置前报告中文乱码,后来在XSLT模板中强制UTF-8才稳定。另一个坑是OI点击切换时,测试线程正好在更新一个状态栏字符串,导致闪了一下英文,后来在Idle事件里做刷新解决。还有一个印象深刻的:INI文件被客户用Excel编辑过,Excel保存时默认带BOM,程序读取时解析出了奇怪字符。这个问题的根源是Excel在保存UTF-8文件时加了BOM头,后来程序里加了BOM兼容处理,问题消失。
这段时间踩下来的坑,我总结成了一张表:
| 问题现象 | 根因 | 解决方案 |
|---|---|---|
| 报告中文乱码 | XSLT模板未声明UTF-8 | 模板head加charset=UTF-8 |
| 英文系统下日志乱码 | 系统区域非中文,ANSI写中文 | 统一UTF-8编码写文件,或调系统区域设置 |
| 切换语言后部分控件仍是英文 | 控件Tag与语言包键名不一致 | 统一Tag命名规范,代码遍历刷新 |
| 动态状态字符串闪烁 | 线程中途刷新UI | 刷新动作放到Idle事件,避免抢占 |
| INI文件读取异常 | Excel加BOM头 | 读取时忽略BOM |
| 数据库中文显示乱码 | 字段类型为varchar | 改成nvarchar |
这张表我自己一直存着,每次做新的TestStand工位项目都会翻一遍。
最后说一点我个人的体会。TestStand界面本地化这件事,技术上没有任何一个步骤是“高科技”,真正花时间的都是细节和规范。最大的门槛往往在于,你有没有在设计阶段就把语言变量、字符编码、控件标识这些规矩定好。我后来再做项目时,都会先问自己一个问题:如果客户半年后要求把界面从中文改成第三种语言,我现在这套方案要改多少文件?如果答案是一两个语言包文件加几行配置,那这个项目的架构基本就稳了。希望这篇东西能帮你少踩几个坑。