11 12
发新话题
打印

【转贴】在BCB中製作多國語言程式

【转贴】在BCB中製作多國語言程式

在BCB中製作多國語言程式  如果您......(原贴为繁体中文)

原文的地址是http://www.dev.idv.tw:8080/folde ... 05-02-15.7432095461  

    第一次发贴,本想给大家做点好事,结果...

    拷过来格式全没了,刚发了几分钟就看到winnick大哥的留言,摆弄了半天南极星也没转换成功,过了两天看到热心的 progholic、精致工作室 已经给转换了,我又把他们转换的重新排了版,贴在下面,本来想编辑原贴的,发现以不能编辑了。

    说道BCB,第一眼看到就由衷的喜欢,而且是越来越喜欢,可是看到Borland的日趋没落,看到BCB的没有后续版本,不免时时生出一种忧虑,不过我们的技术毕竟不应捆绑在一个开发工具上。

   
    在BCB中制作多国语言程式  如果您写的软体需要考虑到转换成为不同语言,那麽由Borland C++ Builder EnterpriseEdition 所提供给您的多国语言翻译环境将是极为有帮助的。他可以很快的帮助您将各国语言版本制作出来。并且也提供动态的方式让您可以轻易的制作出您所需要的版本。甚至可以让您在不用变动程式码本身的状态下,将GUI 的外观字型等进行适度的调整。除了多国语言介面的制作外,透过本文後面所叙述的技巧,将可以让您动态的切换不同的语系。这些BCB 都已经帮您处理得很好了,不过有些小细节您仍然需要注意,小心的处理或是避开,否则很容易的做不出来您想要的结果。

首先,我们先来看一下在设计程式时要注意的东西。

1、第一个版本务必使用英文。这点非常重要,其理由有二。第一点是通常比较好的文字翻译最好是由该国自己翻译。举例来说,要制作日文版本,当然是请道地的日本人来翻译会好的多。那麽你认为懂得英文的日本人多,还是懂得中文的日本人多?同理,换成韩文,法文与西班牙文也是一样。第二点是由於在处理上, BCB 所提供的环境通常比较能够正确的支援英文及该平台的语系。也就是说,您可以很容易找到可同时显示及处理英文及日文的平台,或者是英文及法文的平台。因为,没有一个语系的平台不能处理英文。可是你比较难找到一个可同时处理中文及日文的平台,或是同时处理中文及法文的平台。例外,还有一个理由未列在上面的是,在大部分的状况下,英文的句子长度比较长。

2、不要强制设定任何元件及Form的预设字形。这是因为每个平台系统所使用的预设字型及大小都有所不同。像是英文作业系统中预设字型是 Tohoma,但是中文及日文的windows作业系统就不是这样。使用的语系一定要使用正确语系的字型才有办法显示。所以,使用预设字形,可让AP字型随着系统自动调整为正确字形。或酗ㄗㄠo比较好看( 大部分非英语系Windows 作业系统的预设英文字型都很难看,不知理由为何? ),但至少是正确的。要做的这点很简单,确定您所有元件的属性中,只要有ParentFont这项的一定要强制设为true。尤其是Form的 ParentFont一定要设为true。否则你一定会在多国语言版本的过程中遇到big trouble 。相信我!否则我就不会写这篇文章来提醒你了。

3、别把要显示的字串写死在程式里。像是这样: ShowMessage("Hello World!");或是 MainForm->Caption = "Main Form" ; 理由很简单,写在程式里的字串Borland C++ Builder的工具无法帮你处理他们,这样在翻译时,就得自己把所有的Source Code搜寻一遍找出这些字串。平常,随便写个小程式,这样的字串就已经有十来个,您想想看,要是稍微大点的Project,这会有多恐怖?所以,我们要采用一个集中的方法,这个方法还要能够与Borland C++ Builder的翻译工具相结合。或许您之前看过我写的那个使用Resource File 的StringTable的文章。但是,我要告诉你,忘了它吧。我在写那篇文章的时候没注意到Borland C++ Builder无法使用那个方法。也不是说那个方法是C++ Builder完全不能用,而是,如果您想要动态进行各国语系的切换,请放弃使用Resouce File的StringTable。不过,就算不为这个理由,我也是建议你换成本文後面要介绍的Resourcestring的方式,理由是他比较方便使用。也比较像是C++ Builder的作法。不过,这个作法的缺点有二,一为要使用Pascal的语法。别担心,保证不要一分钟就学会。二是只有C++ Builder跟Delphi可用。其它的Compiler像是MS VC++就不能用罗。

4、写程式时,无论任何理由都不要让自己的程式绑死在某个语系上面。例如:你可能会想说要好看一点所以写成"92年2月2日"。可是,这样的东西在其它语言马上变成乱码。因此,基本的方式是使用国际通用的格式。当然最好的方式还是要能自动转换成为各国的常用表示方法。但是这个部分属於i10n的范畴,我还没研究过,有空再说罗。

    现在,就让我们来看看这个Delphi语法的ResourceString要怎麽用在C++ Builder中。其实,在多国语言上,Borland已经准备好了一个范例,放在$(BCB)\ExamplesAppsRichEdit。这个范例很重要的,他里面有些程式是我们後面介绍动态变换语系时要借来用用的。不过,这边我们先借他的ReConst.pas这个档案来用一下。您会看到这个档案有下面的内容:

unit ReConst;interfaceuses Windows;
const  
      ENGLISH = (SUBLANG_ENGLISH_US shl 10) or LANG_ENGLISH;  
      GERMAN  = (SUBLANG_GERMAN shl 10) or LANG_GERMAN;
      FRENCH  = (SUBLANG_FRENCH shl 10) or LANG_FRENCH;
resourcestring  
      SUntitled = 'Untitled';  
      SPercent_s = '%s - %s';
       SSaveChanges = 'Save Changes?';  
      SConfirmation = 'Confirmation';
      SNumberbetween = 'The number must be between 1 and 1638.';  
      SLcid = '1033'; { US = 1033; DE = 1031; FR = 1036 }
implementationend.

    看到那个resourcestring了没?没错,就是这样!只要把那些resourcestring中的字串换成你自己的定义就可以罗。稍微要注意的是这个字串是使用单引号来括住的,因为他是Pascal语法嘛!例如,您可定义自己的字串为:

resourcestring   
       MyResString1 = 'My First resource string' ;

    你可能觉得SLcid那行有点看不懂,别担心!在那行的分号後面的字串全是注解。因为,在Pascal中,大括号被当成注解符号使用。您也可以如法炮制的来为您的字串加上注解。另外,const中定义的是常数,其型态为Word,也就是2 Bytes。值介於0-65535之间。所以,建议您一并将程式内用到的常数定义在此,这样比较符合集中管理的精神。最後,别忘了将第一行的Unit叙述换掉。不过,您要先为您自己的档案命名。建议您学ReConst.pas 的命名方式。例如,您的Project缩写是My,那麽就叫他MyConst.pas吧。所以,"Unit ReConst;"也要改成"Unit MyConst;"才行罗。好吧,完成後,请将这个pas 档案加入到你的Project 中。OK!光是这样是没用的。因为,C++ 需要有include 档案。那麽,MyConst.pas的include档案从何而来?还好,C++ Builder有自动产生include 档案的能力,请在打开MyConst.pas後,按下Alt-F9,让C++ Builder单独compile它。成左尔陧A您就可看到MyConst.hpp这个档案的出现。理论上,您该在所有的cpp 档案中都会用到这个include档案才对。另外,别把这个include档案跟precompiledheader的技巧合用喔。因为他会为常数进行初始化,所以precompiled header技巧遇到他就做不出来了。请个别在需要的程式档中include这个header file就可以了。 OK! 接下来要怎麽在程式内使用这些常数及Resource字串呢?非常简单!!用就对了!举例来说,您要使用MyResString1。您可使用下面的方式:

    ShowMessage(MyConst_MyResString1);

    是的!在您要用的Resource string名称前面加个"MyConst_"的prefix。就可以了。当然,这个prefix完全是根据您Unit的定义而来。您可叁考前面步骤所做出的include档案中,的namespace名称,就可看到罗。在了解了这个部分後,接下来就是要把你的程式写好罗。请注意,多国语言化的翻译务必在最後进行。而且是要在程式完成度已经相当高的时候才进行。否则,画面一下子变化太大的话,C++ Builder的多国语言环境也吃不消的。现在,假设您的程式已经完成了,接下来要如何才能够进行多国语言化呢?首先,您需要开启Resource DLL Wizard来制作Resource DLL。你可在主选单中依照New->Others->New->Resource DLL Wizard来开启它。接下来这个精灵程式会给您一些指示,并请您选择要制作的语系。
  
    首先,您在精灵中遇到的第一个问题是精灵会询问你要对哪个Project 制作多国语言版本。把你要制作的Project 打勾。然後,继续後面的步骤。这边有一点要注意的是BCB 多国语言环境似乎有点问题,如果您的Project 放在一些中文目录中,可能会找不到,所以建议您的Project 要放在纯英文的路径内。接着,就是要选择您要转换的语系了。C++ Builder 的精灵会列出所有的语系让您选择。您可以一次把要做的语系全部选出来。也可以一次只选一些,下次要加入其它语系时,请重复这个步骤就可以了。别担心旧的语系会被局戚AC++ Builder 已经帮您处理好了。选好你的语系後按下下一步,您就会看到这些语系所对的目录。例如:中文就是CHT,简体是CHS,日文是JPN等等。接着,下一个画面,BCB 会问您有没有其它的要加入的处理的档案。如果要加入的应该都是dfm 档或是rc档案。在接着下一步就是要产生语系了。C++ Builder 最後还会再列出一次要进行的语系给你看。

    没问题的话,就按Finish罗。在最後列出所有语系的地方,有一栏为Update Mode 。如果您是第一次对这个语系建立Resource DLL,那麽这个栏位就是Create New 。如果您之前已经建立过这个语系了,而且您又再次使用Resource DLL来建立他。没问题,精灵会帮您处理好,所以您会看到Update Mode 中所显示的是Update。如果,您不想要只是Update而已,而是要重新建立新的,在Update上面点一下,一个combo box 会出现让您选择。最後都没问题的话,您就会看到精灵跟您说他需要重新编译您的程式以方便建立各国语言。在此同时,精灵会要求您将Project存成Project Group。这是因为每个语系都是自己一个Project 。用成Project Group才能统一管理。对於这个Project Group的名称我的建议是在Project名称後面加上"_i18n"的字尾。

    当然,或许您会习惯在前面加上ML的前置词,代表Multiple Language。不过,我还是觉得用i18n好。存档成功且Project 也重新Compile成功。这时,精灵会顺便帮您叫出翻译管理员(Translation Manager)。在这个Translation Manager中,您需要使用其中的Workspace 画面来帮助您进行翻译的工作。Translation Manager的用法不难,大家看看就会了。重点是除了字串外,您还可透过翻译管理员调整元件大小,避免不同语系下,字串被元件破坏的窘境。您随时都可透过主选单的View->Translation Manager来叫出翻译管理员。只是每次翻译完,您都需要针对有修改过的语系重新编译。每个单独语系都会编译出自己的Resource DLL 。这些档案的名字就是Project的名字,加上以语系的名字作副档名。所以,如果您有一个名为Project1.exe的档案。那麽他对应的中文繁体语系档就是Project1.CHT。日文就是Project1.JPN。这些语系档案要与执行档放置於同一个目录下。至於我们前面所说的resourcestring,他会出现在各语系的Resource script 中。您也是透过翻译管理员来编辑他们。

    不过,在这里C++ Builder一直到6.0 update 2都有这麽个Bug 。这个Bug 会导致您的resourcestring在切换语系时,不会被载入。好的,要如何解决他呢?简单的很,请开启你的Project Mananger,将每个语系的Project加入一个名为XXX_DRC.rc的档案。其中,XXX就是你的Project名称。这个档案在每个语系自己的目录下都有一个,您需要为每个语系的Project 加入他。当然,别弄错目录,把不同的语系档案混在一起罗。如果您要设定这个Project在目前平台要使用何种语系,可利用Project->Languages->Set Active设定预设语系。实际上,您的程式是根据下面这个Registry的值来决定要使用何种语系Resource DLL:

    HKEY_CURRENT_USER\Software\Borland\Locales\[Exec file name]

    其中"Exec file name"就是你的执行档名(含路径),这个Registry的值是您希望的语系的名称。例如,如果您需要这个软体启动时是中文版,那麽这个Registry就应该填CHT 。其它以此类推。 由於,要显示哪个语系是透过上述的Registry所决定的,因此,您需要在安装程式中就正确的设定这个Registry的值。以便能够正确的显示正确的语系。 或阴z要问,难道没有办法自动判断系统语系,然後进行切换吗?有的!这就是我们下面所要介绍的,不过我们要介绍的是远比自动判断语系更厉害的,也就是动态切换语系。让您的使用者,可以动态的切换所要显示的语系。嗯!厉害吧! 好了,首先第一部要做的是把前面所提到C++ Builder 范例中的那个RichEdit目录找出来。接着,仔细找找,看下面是不是有个叫做reinit.pas的档案。有吧!没有的话,就去跟别人Copy吧。 把这个档案放到你的Project里面来。然後在您要让使用者动态切换的地方加上由这个档案所产生的include档案。例如:

    #include "reinit.hpp"

    OK! 第一次,你的系统里面当然没有这个档案罗!请利用Compile Unit的方式产生他。 接着,我们就是要利用这个档案所提供的函式来帮助我们达到动态切换语系的效果。首先,假设您希望的是能够自动判断系统语系然後进行切换,那麽找个合适的地方(通常是main function的开头。)加入下面的程式码:

    if(LoadNewResourceModule(GetSystemDefaultLCID()))  
    {        ReinitializeForms();    }

    这样,便可正确的显示语系罗。上面这几行,其实就是C++ Builder自己偷偷在用的。所以,如果你有提供Resource DLL,而且没有依照前面所说的在Registry中指定语系。那麽你的程式就会自己依照抓取系统语系了。正因如此,我们只需要把GetSystemDefaultLCID()换掉,换成特定的语系就可以罗。所以,现在要做的就是如何制作出给特定语系LCID 呢?首先,在C++ Builder的include目录中,找到winnt.h 这个档案。找到LANG_ 及SUBLANG_开头的定义巨集。我们以法文为例。要做出法文的LCID,其作法如下:

    LCID lcid = (SUBLANG_FRENCH << 10) | LANG_FRENCH ;

    这样就可以了,很明显LANG_ 是在定义国家的语言。那麽SUBLANG_呢?指的是地方语系。比如说,同样是中文,在LANG_CHINESE之下,就有这些SUBLANG:

#define SUBLANG_CHINESE_TRADITIONAL      0x01    // Chinese (Taiwan)     
#define SUBLANG_CHINESE_SIMPLIFIED       0x02    // Chinese (PR China)   
#define SUBLANG_CHINESE_HONGKONG         0x03    // Chinese (Hong Kong S.A.R., P.R.C.)   
#define SUBLANG_CHINESE_SINGAPORE        0x04    // Chinese (Singapore)   
#define SUBLANG_CHINESE_MACAU            0x05    // Chinese (Macau S.A.R.)

    全部使用上面的计算方式,就可组合出您要的LCID。然後再把他喂给LoadNewResourceModule(),就可载入正确的 Resource DLL了。前提是那个Resource DLL 档案要存在喔。到此为止,您应该已经能够掌握C++ Builder 中多国语言的作法罗。最後再提醒您一点,一旦您对於Form上面或是resourcestring有所新增,删除,或是其它外观上的变动。务必要用 Project->Languages->Update Resource DLLs来更新您的Resource DLL。并且重新编译出各语系的版本。千万不要让自己重复一直做这个工作,否则您会很累。

    多国语言一定要等所有的画面都确定之後,甚至是经过相当程度测试之後再进行。也就是说,英文的 Release 版本没出来前,别做多国语言化。否则,一定会浪费掉数倍的时间。无论任何理由都一定要坚持这点。否则,请直接叫公司给您一个专门做多国语言化的小组,然後将Project 的时间延长一倍。

    最後附带提醒一点!当您将英文的稿送去给别人翻译时,无论哪一国的语言,都请翻译人员坚守一个原则,翻译过後的字串长度,不可超过原来英文的长度。除非那个字串的翻译非常固定,例如像是Yes, No, OK, Cancel 等。翻译人员如果跟你说做不到,那麽就换个翻译。这点也很重要,因为单是『字译』,一个句子长度可能远超过原来的句子。这会对你的程式产生极大的困扰。如果,为了这个原因,你要针对各语系调整你的画面。那麽,请直接将Project 的时间再延长一倍,看看有没有可能做完。务必跟翻译人员坚持这点!请他用『意译』的方式调整句子的长度。我们这里所说的长度是画面上看到的长度(单位为像点),不是指一个句子有几个字。如果你是在帮公司开发程式,建议你尽可能在一开始的时候就把多国语言的问题考虑进去。否则等到程式越写越大,才想到要改成多国语言时,就会非常痛苦了。

TOP

看着有点累,
嫩不能转成简体
while (I'm_alive)
{
  printf("I Love Programming");
}

TOP

在BCB中制作多国语言程式  如果您写的软体......

TOP

用foxmail转的. :

TOP

《简繁大师》转的,采用IT包

在BCB中制作多国语言程序  如果您......
精诚致远

TOP

没有分段啊。。。。

看来台湾用BCB的人比较多, 现在Borland停止BCB开发了,不知道这些人现在用什么。

TOP

原文的地址是http://www.dev.idv.tw:8080/folde ... 05-02-15.7432095461  

    第一次发贴,本想给大家做点好事,结果...

    拷过来格式全没了,刚发了几分钟就看到winnick大哥的留言,摆弄了半天南极星也没转换成功,过了两天看到热心的 progholic、精致工作室 已经给转换了,我又把他们转换的重新排了版,贴在下面,本来想编辑原贴的,发现以不能编辑了。

    说道BCB,第一眼看到就由衷的喜欢,而且是越来越喜欢,可是看到Borland的日趋没落,看到BCB的没有后续版本,不免时时生出一种忧虑,不过我们的技术毕竟不应捆绑在一个开发工具上。
   
    在BCB中制作多国语言程式  如果您......

TOP

为了大家看着方便,请管理员把 #1 的内容换成 #7 的内容吧,本来想编辑#1的确发现

对不起,本站限定如果帖子发表的时间超过 43200 秒,

则除了管理人员以外,任何人没有权力进行编辑,请返回。

。。。。。。。。。。。。

TOP

感谢zgrysn 的奉献

TOP

已经转移到1楼了。同时感谢热心的精致和progholic。

TOP

 11 12
发新话题