Eltirosto / Degrees-of-Lewdity-Chinese-Localization

Degrees of Lewdity 游戏的授权中文社区本地化版本
https://eltirosto.github.io/Degrees-of-Lewdity-Chinese-Localization/
Other
3.89k stars 194 forks source link

关于未来的汉化发布方式 #32

Closed Lyoko-Jeremie closed 1 year ago

Lyoko-Jeremie commented 1 year ago

说说你遇到的问题?

在游玩过程中有发现存在同一句子同一单词,前一对话翻译成了中文后一对话就变成英文,或者反过来,这样的翻译闪烁问题。
在家里的sex玩具箱页面特别容易触发这个现象。

我想请问一下,汉化是使用内存注入并替换输出字符串形式的动态汉化,还是直接修改原始剧本脚本(.twee脚本)的静态汉化,还是官方原版游戏框架中提供了原生的i18n系统呢?

Eltirosto commented 1 year ago

我们直接修改 .twee 和 .js 原文件中的文本后使用源仓库自带的编译脚本编译为 html 文件。

出现这种情况十分正常,因为游戏基于 Twine/Twee3 引擎,使用的编码格式是 Sugarcube2,因此在游戏源代码中常常会出现普通的文本字符串与变量、逻辑语句混杂交织的情况,对于任何形式的 i18n 均不友好。

例如挑一句源代码中的文本如下: a hidden pocket on the inside of <<nnpc_his "Kylar">> <<if $NPCName[$NPCNameList.indexOf("Kylar")].pronoun is "m">>pant leg<<else>>skirt<</if>> 其对应的汉化文本为: <<nnpc_his "Kylar">>的<<if $NPCName[$NPCNameList.indexOf("Kylar")].pronoun is "m">>裤子<<else>>裙子<</if>>内的隐藏口袋里掏了出来。 其中的变量 <<nnpc_his "Kylar">> 的定义在此处不得而知,需要在其他地方独立翻译。包括这一种情况在内的有各种复杂情况,包括但不限于:

截止目前形如此的需汉化文本有超过 111,719 条,因此在汉化过程中会出现大量的语义混杂、中英交织,或是非字符串被错误地汉化进而导致的报错问题,直至现在仍在完善过程中。因此需要大量玩家反馈游玩过程中可能出现的各种问题,进而修复完善汉化。

Lyoko-Jeremie commented 1 year ago

感觉,既然已经在做大手术了,或许可以直接给解析引擎SugarCube2打补丁,在Parser上加个i18n扩展

简单研究了一下代码

sugarcube 2 是在 markup/parserlib.js 的 L113 把用来解析<<xxxxx>> <</xxxxx>>标签的解析器注入到Wikifier这个解析和生成器里面的

https://gitgud.io/Vrelnir/sugarcube-2/-/blob/master/src/markup/parserlib.js?ref_type=heads#L113

    Wikifier.Parser.add({
        name      : 'macro',
        profiles  : ['core'],
        match     : '<<',
        lookahead : new RegExp(`<<(/?${Patterns.macroName})(?:\\s*)((?:(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/)|(?://.*\\n)|(?:\`(?:\\\\.|[^\`\\\\])*\`)|(?:"(?:\\\\.|[^"\\\\])*")|(?:'(?:\\\\.|[^'\\\\])*')|(?:\\[(?:[<>]?[Ii][Mm][Gg])?\\[[^\\r\\n]*?\\]\\]+)|[^>]|(?:>(?!>)))*)>>`, 'gm'),
        working   : { source : '', name : '', arguments : '', index : 0 }, // the working parse object
        context   : null, // last execution context object (top-level macros, hierarchically, have a null context)

这个地方做了括号匹配和标签提取,以及标签内内容的提取。

所以应该可以在这里做 获取标签的原始文本内容把汉化之后的文本替换/注入到输出结果 的工作。


大概想了一下,有两个在这个地方实现汉化注入的方法,

1:

学习Angular的 @angular/localize ,在原始项目的 <<>> 标签上面添加i18n注解,这个是为了给标签生成固定id,然后导出angular那样格式的.xlf翻译文件,翻译之后生成angular式的节点到翻译的json字典,然后在运行时加载回去替换。
优点是翻译效果好,结果固定。 缺点就是需要给原始游戏添加i18n注解,但这个注解加完以后可以PR给原始游戏,相信作者会很开心。对付游戏JS脚本生成的动态内容以及变量,可以组合用翻译工厂 (类似Angular这种或者这种 ) 来解决

2:

代码跑起来,在这里挂一个记录器,记录所有跑过这里的文本语句,然后生成原文字典cvs,翻译之后生成语句和翻译的查找表类似于KinkiestDungeon这种,然后在运行时加载回这个地方做替换。
这个思路就有点像GalGame啃生肉用的VNR,只不过VNR的思路是给游戏输出字符串的win api函数挂钩来提取原始文本输出到翻译机再以外挂字幕的方式显示,这里的方法要再进一步,把翻译的结果字典又输回游戏的渲染引擎(Wikifier)。
优点就是完全不需要触碰游戏原始剧本文件,跟踪上游更方便。 缺点就是匹配准确的要求高,上游即使改动一个空格这里也会出现匹配不上的情况,并且要跑过的地方才能抓到内容,要全覆盖比较麻烦。


sugarcube2 编译结果放在游戏项目的这个地方,所以打了补丁之后替换它就好

devTools/tweego/storyFormats/sugarcube-2/format.js

游戏应该用的是作者的这个打了补丁的版本的sugarcube2

Lyoko-Jeremie commented 1 year ago

刚才想测一下,发现这个 https://gitgud.io/Vrelnir/sugarcube-2 不是最新版的代码,得问问作者请他push最新的sugarcube-2更改上来

LittleNightmare commented 1 year ago

@Lyoko-Jeremie 可以考虑看这个https://github.com/tmedwards/sugarcube-2 的develop分支

没接触过相关,不确定对不对

Lyoko-Jeremie commented 1 year ago

@LittleNightmare 研究了一下git log,不像是

把两个project放在一起可以看到 Vrelnir 这个版本有个DoL特定的patch,但没看到 tmedwards 这个版本上有这个patch , 所以感觉这应该 ~是为另一个游戏做的特化版本,或者就~ 是sugarcube-2的后续开发。 (EDIT:看了下作者,tmedwards这边好像是sugarcube-2的官方,Vrelnir这边是在DoL开发过程中为了方便给sugarcube-2打了补丁)

图片

把tmedwards这个版本放进去跑起来也是:

Screenshot 2023-09-10 at 14-07-52 Degrees of Lewdity


另外我可以确定正确版本应该是 Vrelnir 的版本,因为之前我放进去之后的第一个报错是有关 maxSessionStates 缺失的,刚好就是这个还没合并的 PR#3 里面添加进来的。 ~但是我在我本地手动Patch这个PR之后报错提示还缺少其他东西,所以我可以肯定是作者本地已经合并了这个PR,然后在其上还做了其他开发加了点最新版游戏必须的功能,但是没有把最新修改推上来。~

Lyoko-Jeremie commented 1 year ago

我的错,刚才研究了一下,打了这个 PR#3 之后得清理掉本地所有数据才能用,不然读取旧数据会报JSON解析失败,可能是IndexBD里面的数据格式变了。现在可以打开进入游戏了,但不确定其他地方会不会有问题,后边我研究一下这个sugarcube-2怎么运行的。

Lyoko-Jeremie commented 1 year ago

打过 PR#3 能跑的版本 https://github.com/Lyoko-Jeremie/sugarcube-2_Vrelnir

Pi1viayarn commented 1 year ago

打过 PR#3 能跑的版本 https://github.com/Lyoko-Jeremie/sugarcube-2_Vrelnir

构建对比了下,游戏用的版本打了PR#3,并把PR#2还原了

Lyoko-Jeremie commented 1 year ago

@Pi1viayarn 3Q~~

Lyoko-Jeremie commented 1 year ago

@Eltirosto 测试了一下,这个框架好像挺复杂的,先给我点时间找到能用的注入点弄个demo出来

Lyoko-Jeremie commented 1 year ago

初步分析写在 这里了 , 上面的 汉化方法2 应该是可以实现了。

Lyoko-Jeremie commented 1 year ago

汉化方法2实现demo了 https://github.com/Lyoko-Jeremie/sugarcube-2_Vrelnir/issues/1#issuecomment-1714805847 🤣

2023-09-12 08_39_30-Degrees of Lewdity — Firefox Developer Edition
NumberSir commented 1 year ago

未来汉化发布方式将独立于原版游戏,采取 I18N 模组的方式发布

SexyAkko commented 1 year ago

想问一下,这类翻译的使用方式,之前没有接触过,能不能补贴一下使用方式之类的?

NumberSir commented 1 year ago

想问一下,这类翻译的使用方式,之前没有接触过,能不能补贴一下使用方式之类的?

截至 0.4.2.7-chs-alpha4.0.0 的汉化方式(下称“旧版汉化方式”)仍然是修改硬编码,直接下载发布版中的 zip 压缩文件解压即玩。

未来的新版汉化方式将基于 ModLoader,(基本用法请查看 ReadMe,基本原理是向原游戏的 HTML 文件中注入 js 实现加载模组的功能)仅放出含汉化词典的 I18N 模组,在不修改游戏本地英文原文的情况下在运行过程中动态汉化,类比 Minecraft 的 I18N 模组

未来可能的发布汉化版方式可能会是:

  1. 玩家自行在官方英文版发布地址下载英文版
  2. 本仓库以安装包的形式发布 ModLoader 和内置汉化词典的 I18N 模组
  3. 玩家自行安装 ModLoader 和汉化模组