江枫

多语言方案

1.多语言简述

   多语言,顾名思义就是我们开发的游戏需要支持多种语言,以便给各种其他国家的玩家游玩。
   但开发过程中使用到的与语言相关的内容还挺多的:文本、图片、特效、动画等甚至使用的模型中都可能带有语言相关的文本信息。

2.多语言方案(文本)

 1.传统方案

   使用键值对存储需要多语言化的文本。例:

Key值 中文 英文
KeyA A键 KeyCode A
KeyB B键 KeyCode B

   然后在代码中需要使用文本时就要使用对应的Key值进行获取文本,策划的文本填写在表内,程序的文本可以定义一个常量文件进行存储。
   优点:

  • 所有文本集中在一张表内,策划使用的文本与程序使用的文本拆分。
  • 没有一词多义问题

   缺点:

  • 策划配置时需要在表内填写对应的key,而不是中文
  • 需要较为严格的制定规范,否则如果直接在代码或配置内使用文本会导致该部分内容多语言失效
 2.奇怪的新方案

   因为我们的项目已经上线运营很久了,在项目整个开发过程中没有考虑过多语言的问题。所以现在想做多语言的话就是把表复制一份,然后把里面的文本改成翻译后的结果。代码硬编码的文本也要全改。改了一遍下来发现太痛了,还是做一套通用的多语言方案吧。

   1.中文做Key

   首先我们的文本已经写在逻辑和配表内了,如果使用传统方案再提一遍感觉也很痛,而且这样会有大量的重复文本问题。但是多语言本质上还是一个字典集查找的过程,还是需要一些键值对来建立文本翻译索引。那么key既然可以是英文,那为什么不可以是中文呢?所以我们的目标就是把原本的翻译表改成:

Key值 英文
中文 English
中文 English
   2.如何生成这种翻译表

  首先我们需要定位中文文本都会存在于哪些地方:代码、预制体、自定义的资源文件
  接下来我们要想办法把这些地方的中文都提取出来:

  经过上面的代码处理,就可以最终获得一张项目内使用到的文本信息的总表。不过,有了翻译表我们的多语言工作就结束了吗?远远没有!

   3.如何使用翻译表以及文本何时更新?

  为了使用翻译表,我们可以提供一个多语言管理器,如LanguageManager。当代码逻辑需要设置文本时,通过LanguageManager查找应该使用的文本(当然LanguageManager需要纪录当前用的是什么语言啦)。
  但是那些一开始就写在预制体上的静态文本怎么办?他们应该什么时候更新自己的值?当语言切换的时候文本该怎么知道自己需要更新值?
  为了让静态文本初始化与语言切换时可以更新,我为对应的text组件制作了一个多语言组件,这个组件的主要功能就是初始化时更新自己的值,以及监听语言变化事件。为了在更新时组件自己就可以完成更新的操作,所以组件上会缓存下来当前的key(中文)。

   4.字符串拼接问题怎么办?

  我们游戏主逻辑使用lua,lua的字符串拼接有两种方式:一种是string.format,内部使用%s%d等占位符进行占位填坑。另一种是使用..连接两段字符串文本。
  但是在进行翻译的时候,国内外的语序很大概率有所不同,比如日期的表达上中文是年月日,国外可能是日月年。在拼接时中文:%s年%s月%s日。如果直接替换为国外文本:%sday%smonth%syear时,就会发现语序不对拉!
  所以我们需要使用C#风格的字符串拼接也就是用{0}{1}{2}这种挖坑的形式实现字符串拼接。

   5.一词多义怎么办?

  既然使用了中文做key,那么中文博大精深,相同词语含有不同语义就在所难免,所以我们还需要额外处理一词多义的问题。
  但是我们一词多义的需求不多,暂时使用一张额外的双key表来缓存一词多义的问题。
  如果是配表中使用一词多义,还可以在表中填写对应的表名,行列来定位要对哪个文本进行一词多义。然后对lua表建立元表来保证查询方式不变的前提下可以查找一词多义文本

主Key 副Key 英文 sheet row col
中文Key Key2 English

   6.额外的格式问题

  此外,还有一些奇怪的问题,比如Unity在存储预制体内的回车时,使用的是\n(Unicode:\u000A)。而我们如果使用的是Windows平台,Excel内的文本回车在导出成资源文件时会变成\r\n(Unicode:“\u000D\u000A”
)。所以我们在写入文本与格式转换匹配时还需要额外小心这种格式问题。

3.多语言方案(图片)

  图片的多语言处理与文本大体类似,只不过我们不需要额外的翻译表了,只需要确定好每种语言的后缀,如:

原本图片为:AAA.png
英文图片为:AAA_en.png

  则我们就可以通过资源的后缀进行加载不同的图片了。此外,如果图片需要打图集的话要区分好图片的划分策略。比如是否打一个基础图集(包含非多语言项,与默认语言项),此外再打多语言图集(只包含对应语言图片)。还是将一个语言用到的所有图片都打进一个图集(每种语言对应一张图集,不同语言图集内包含了同一份基础图集)。

4.多语言方案(动画)

  动画可以通过动态切换overrideController内的AnimatorClip来实现。

文章大纲