给大家分享我的I18解决方案
最近在做多语言相关,本来是想打算用官方的I18插件来做.但是发现不满足需求,所以自己写了套I18的处理方案.
官方I18插件存在的问题:
1 不分包.官方的做法是把每种语言的资源都绑定上去,那么一种语言就会多一套资源.运行加载的时候就会把所有语言的资源都加载起来.如果资源多,那么加载量就会很大.运行过程中其实只需要一种语言资源,其他语言用不到,没必要都加载起来.
2 没有处理代码指定的资源.有些时候会动态切换资源,比如编辑器中绑定一堆SpriteFrame数组,运行的时候根据需求更换SpriteFrame. 由于SpriteFrame已经绑定好了,如果要做多语言,需要额外代码处理.
我的需求:
1 每种语言做一个语言bundle,运行时按照需要的语言加载bundle
2 代码指定SpriteFrame不需要额外处理也能达到多语言切换效果
3 不仅仅是Label/RichTxt Sprite, 还需要支持字体,Spine, 声音 总之所有跟多语言相关的都需要支持
我的解决办法:
1 一种语言一个bundle
2 所有语言的资源路径和名字一致(所有多语言名字唯一,方便工具自动化)
3 需要用到多语言的地方绑定一个组件,组件上记录资源路径
4 加载场景 预制体的时候 一并加载需要用到的多语言资源
我的方案
以下是我的方案:以中文/英文为例
目录:
中文为默认语言放到 assets/resources/CN 不为bundle
英文放到 assets/EN 并且为bundle
核心组件:
I18Cmpt: I18组件,记录资源路径,切换语言后自动刷新(目前支持Label,RichTxt,Sprite,Spine)
I18Font: I18字体,记录资源路径,切换语言后自动更换字体
I18PreUrl: I18预加载URL,主要记录某个Node会用到的所有资源路径(排除I18Cmpt上的路径)
I18Mgr: 负责管理多语言资源,切换语言,预加载/加载资源
TxtMgr 文本管理

核心接口
I18Mgr.ts
changeBundle:切换语言
preloadScene:预加载
loadScene:加载场景
getRes:根据url获得当前语言的资源
I18SpriteTool.ts
changeI18SpriteFrame:更改spriteFrame
changeSpriteFrame:更改spriteFrame
TxtMgr.ts
getTxt:根据key获得文本,支持通配符
具体操作
1 I18Cmpt组件
给所有需要用到多语言的地方绑定I18Cmpt
比如Label/RichText Sprite Spine
Label记录文本的key,其他资源记录路径

2 字体 I18Font
操作同上
3 给所有的scene和prefab的第一个node添加I18PreUrl(预加载时用),如果资源没有预加载,那么在切换语言的时候或者显示的时候,I18Cmpt需要等待资源加载完成后刷新,在这期间会存在闪烁现象.

4 所有加载场景的地方使用I18Mgr的preloadScene和loadScene进行替换
5 所有代码指定SpriteFrame的地方使用I18SpriteTool.changeI18SpriteFrame进行替换
效果展示
[上传不了视频,就不展示了,大家项目自己运行吧]
理论存在 实践开始 !!!
我不会傻傻的手动去执行上面的绑定操作的(项目已经上线,增发多语言版本)!!!
我自己写了个工具集合

工具配置:run.js
_artPath 美术资源绝对路径
_projectAssetsPath 项目assets绝对路径
_defaultLanguageDir 默认语言目录,相对路径
_languageDir 目标语言目录
_allLanguageDir 项目中所有语言目录(排除默认语言)
_i18CmptType I18组件的type(项目中具体值)
_i18PrelaodType 项目中I18Pre组件的type(项目中具体值)
[Label自动添加I18Cmpt]
命令:node run.js AddI18Label
执行过程:
1 读取txt文本
2 修改编辑器中带中文的Label
如果有i18组件,则检查i18上key对应的文本内容,并更新Label上的string
如果没有i18组件,则自动添加
如果txt没有对应文本,则自动生成 key:文本 key自增
将文本的key记录到i18组件上
3 写出txt文本
如果旧的 key:文本 没用使用过,则不会被保存
注意事项
仅对中文生效
会更新Label上的string内容
也会根据使用情况调整key
因为涉及到其他语言,仅在第一次运行
[自动导入多语言资源]
比如项目中默认是中文,现在要添加英文.现在美术给了一部分英文资源.那么根据英文资源自动导入.找到项目中使用的中文的资源,放到中文目录. 英文资源放入英文bundle
命令:node run.js ImportTexture
执行过程:
1 读取美术多语言资源,得到文件列表
2 通过1得到列表,找到项目中对应的文件uuid
3 修改项目中使用到多语言资源的场景和prefab
如果没有i18组件,则自动添加
将资源路径记录到i18组件
4 移动文件
将美术资源放入到项目中多语言目录
将项目中的资源移动到默认语言目录
注意事项
运行前项目先备份
多语言资源名字要和默认语言资源名字一致
执行后打开creator刷新保存项目
注意检查场景文件和预制体修改日志
----------modify scene and prefab in project----------
可能存在多语言美术资源,但项目中没有
这种情况未处理,注意检查输出
----------no deal art res----------
所有资源名要唯一
目前工具不支持 同名文件
[转换图片格式]
图片类型由texture转换为sprite-frame
图片放入到文件夹后,类型默认是texture,不转换成sprite-frame的话,加载不了.(坑!!!)
命令:node run.js Texture2Sprite “D:/Test/assets/EN/”
执行过程:
1 读取多语言目录
2 查找.png.meta 修改类型
注意事项
[导入多语言资源]后不可立即执行[转换图片格式]
[导入多语言资源]执行后,需要打开Creator生成meta,然后可执行此功能
[添加I18PreUrl]
命令:node run.js AddI18Pre “D:/Test/assets/” “D:/Test/assets/resources/CN/”
执行过程:
1 找到所有的scene和prefab文件
2 找到CN所有资源的url
3 查找scene和prefab中使用到CN资源的uuid
如果i18Cmpt已经使用,则排除
4 给scene和prefab的第一个Node添加I18Pre组件
注意事项:
运行前项目先备份
运行后打开Creator保存
修改日志
-------modify file list-------
骚操作 [手动狗头]
原本项目中默认语言是中文,发印尼,印尼主要是印尼语,几乎用不到中文.
所以我就想要不干脆把默认语言整成印尼语,中文作为语言包.
于是乎我就写了一个更改资源引用的工具.
命令:node run.js ChangeBundle “D:/Test/assets/” “D:/Test/assets/resources/CN/” “D:/Test/assets/EN/”
执行过程:
1 读取默认bundle里的资源UUID
2 读取目标bundle里的资源UUID
3 读取项目中对默认bundle里资源的引用
4 将项目中对默认bundle里的资源引用指向目标bundle的资源
5 将Label/RichTxt的内容重新指向目标bundle的文本(仅对中文生效)
6 更改默认bundle和目标bundle的bundle属性
7 交换默认bundle和目标bundle的位置
注意事项:
运行前项目先备份
默认bundle可以是一个文件夹,也可以是一个bundle
默认bundle和目标bundle的资源名字要相同
默认bundle和目标bundle的资源要一一对应,目标bundle资源不可少于默认bundle
更改中文Label内容
替换资源后,Sprite的SizeMode会改为RAW
游戏运行时,I18Cmpt相关脚本更改spriteFrame时会改为TRIMMED
本工具运行后,记得更改I18Mgr的默认语言
工具集其他工具
检查README.txt
示例项目:
I18.zip (304.1 KB)
工具:
I18Tools.zip (160.3 KB) FileTools.zip (12.4 KB)












