-
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
项目架构分析及i18n注入点分析 #1
Comments
根据以上的初步分析我们可以知道,(方法B) 的实现难度最低,并且根据以上分析结果就可以实现动态翻译。 |
典型地,对于一个 sugarcube-2_Vrelnir/src/macros/macrolib.js Lines 711 to 766 in 554ac30
对于 (方法A) 的实现需要给标签添加 因此,对于 (方法A) 的实现存在肉眼可见的复杂度。 |
Lyoko-Jeremie/sugarcube-2-i18n@d0ee044 现在已经实现TypeB(暂未实现翻译数据加载),并进行了简单测试,测试结果如下 ![]() ![]() ![]() TypeBOutputText 挂钩在最终文本输出处,直接替换输出到html上的txt节点内的文本,适合对独立且上下文无关的句子以及其他方法不便于替换的独立单词进行替换,例如简单按钮,独立句子,特别适用于由js生成的人名地名。 TypeBInputStoryScript 挂钩在 Wikifier 构造函数处,直接接触输入的原始剧本文件,剧本数据是以标签层级的方式输入,所以会被按照以下的输入顺序调用并执行替换测试。
故此处适合大段大段替换原始剧本,并适用于在句子中存在标签且需要调整标签前后上下文句子的语序的情况,典型例子如下图 ![]() |
passage分析: 编译之后没有文件信息了,放在HTML里面的是以passage为单位的数据,一个passage一个内容,读取脚本数据的时候也是以passage为单位的 所有数据放在 passage有几个关键数据:
然后每一幕是一个passage,在passage之间跳转的时候是以passage 的name为单位跳转的。 sugarcube-2_Vrelnir/src/story.js Lines 196 to 243 in 57c65d8
对于链接和按钮的点击跳转事件,在macrolib的button/link宏中 sugarcube-2_Vrelnir/src/macros/macrolib.js Lines 1217 to 1301 in 57c65d8
点击处理函数 sugarcube-2_Vrelnir/src/macros/macrolib.js Lines 1291 to 1298 in 57c65d8
点击后会对button/link标签内的内容( 把文件转换成passage这个工作是那个golang写的tweego干活的,不太想动那里的代码 如果想要替换的话,也可以整个整个地把passage替换掉, |
ref
在以上issue讨论中描述了如下两种i18n改造方式,以下复述文本:
所以应该可以在这里做 获取标签的原始文本内容 或 把汉化之后的文本替换/注入到输出结果 的工作。
大概想了一下,有两个在这个地方实现汉化注入的方法,
1:(方法A)
学习Angular的 @angular/localize ,在原始项目的 <<>> 标签上面添加i18n注解,这个是为了给标签生成固定id,然后导出angular那样格式的.xlf翻译文件,翻译之后生成angular式的节点到翻译的json字典,然后在运行时加载回去替换。
优点是翻译效果好,结果固定。
缺点就是需要给原始游戏添加i18n注解,但这个注解加完以后可以PR给原始游戏,相信作者会很开心。对付游戏JS脚本生成的动态内容以及变量,可以组合用翻译工厂 (类似Angular这种或者这种 ) 来解决
2:(方法B)
代码跑起来,在这里挂一个记录器,记录所有跑过这里的文本语句,然后生成原文字典cvs,翻译之后生成语句和翻译的查找表类似于KinkiestDungeon这种,然后在运行时加载回这个地方做替换。
这个思路就有点像GalGame啃生肉用的VNR,只不过VNR的思路是给游戏输出字符串的win api函数挂钩来提取原始文本输出到翻译机再以外挂字幕的方式显示,这里的方法要再进一步,把翻译的结果字典又输回游戏的渲染引擎(Wikifier)。
优点就是完全不需要触碰游戏原始剧本文件,跟踪上游更方便。
缺点就是匹配准确的要求高,上游即使改动一个空格这里也会出现匹配不上的情况,并且要跑过的地方才能抓到内容,要全覆盖比较麻烦。
根据以上思路对项目架构进行分析,得到的初步情况如下:
1:
此处使用正则表达式
来匹配诸如
<<if nnn>> xxx <</if>
<<if nnn>> xxx <<endif>
<<if nnn>> aaa <<if nnn>> xxx <</if> bbb <<endif>
这样的结构,并提取其中的if
和nnn
sugarcube-2_Vrelnir/src/markup/parserlib.js
Lines 113 to 122 in 554ac30
2:
此处的
Wikifier
是整个项目的核心解析构造器,这个wikifier.js
文件完成了内容输入、调用parserlib.js
注册的解析器解析标签、根据标签内容调用macrolib.js
注册的标签类型实际执行标签对应操作、并最终输出应输出到html的文本(html)内容。sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 28 to 62 in 554ac30
在以下位置的
outputText
函数中创建TextNode并插入到html中,在此处可查看到纯文本字符串输出sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 224 to 226 in 554ac30
如上图所示,故可在此处实现注入方法(方法B)的
记录所有跑过这里的文本语句,然后生成原文字典cvs,翻译之后生成语句和翻译的查找表,然后在运行时加载回这个地方做替换
的实现但此处的缺陷是,此处输出文本非常零散,对于一句话中间被标签分割的输出,会出现拆成两句的情况,如下图
同样如此图所示,我们可以在 class Wikifier 的 constructor 的输入参数上获得每一个原始脚本文件输入
sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 28 to 31 in 554ac30
在此处可实现对原始脚本的整句替换,替换后再输入到 Wikifier 解析器解析并执行。
此处有一个可以注意的地方,
sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 18 to 28 in 554ac30
这里有一个记录 Wikifier 嵌套调用深度的全局变量
_callDepth
sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 87 to 104 in 554ac30
sugarcube-2_Vrelnir/src/markup/wikifier.js
Lines 123 to 141 in 554ac30
其会随着对函数
subWikify
进行递归调用时记录subWikify的递归调用深度(次数),此处的关系是此处就意味着,Wikifier constructor() 的输入会是脚本文件的原始输入,且其会递归地深入每一对
<<M>><</M>>
标签,因此我们可以在此处整段整段地替换原始脚本,但在构造替换模式时需要注意其地递归特性。The text was updated successfully, but these errors were encountered: