Skip to content
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

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

Closed
Lyoko-Jeremie opened this issue Sep 4, 2023 · 15 comments
Closed

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

Lyoko-Jeremie opened this issue Sep 4, 2023 · 15 comments
Labels
🧐enhancement 对汉化内容的建议 😵question 非问题反馈和汉化改进

Comments

@Lyoko-Jeremie
Copy link

说说你遇到的问题?

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

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

@Lyoko-Jeremie Lyoko-Jeremie added the 😵question 非问题反馈和汉化改进 label Sep 4, 2023
@Eltirosto
Copy link
Owner

我们直接修改 .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 条,因此在汉化过程中会出现大量的语义混杂、中英交织,或是非字符串被错误地汉化进而导致的报错问题,直至现在仍在完善过程中。因此需要大量玩家反馈游玩过程中可能出现的各种问题,进而修复完善汉化。

@Eltirosto Eltirosto pinned this issue Sep 4, 2023
@Lyoko-Jeremie
Copy link
Author

Lyoko-Jeremie commented Sep 4, 2023

感觉,既然已经在做大手术了,或许可以直接给解析引擎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

@Eltirosto Eltirosto added the 🧐enhancement 对汉化内容的建议 label Sep 4, 2023
@Lyoko-Jeremie
Copy link
Author

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

@Eltirosto Eltirosto reopened this Sep 7, 2023
@LittleNightmare
Copy link

LittleNightmare commented Sep 9, 2023

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

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

@Lyoko-Jeremie
Copy link
Author

Lyoko-Jeremie commented Sep 10, 2023

@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
Copy link
Author

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

@Lyoko-Jeremie
Copy link
Author

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

@Pi1viayarn
Copy link

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

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

Lyoko-Jeremie added a commit to Lyoko-Jeremie/sugarcube-2_Vrelnir that referenced this issue Sep 10, 2023
@Lyoko-Jeremie
Copy link
Author

@Pi1viayarn 3Q~~

@Lyoko-Jeremie
Copy link
Author

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

@Lyoko-Jeremie
Copy link
Author

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

@Lyoko-Jeremie
Copy link
Author

汉化方法2实现demo了 Lyoko-Jeremie/sugarcube-2_Vrelnir#1 (comment) 🤣

2023-09-12 08_39_30-Degrees of Lewdity — Firefox Developer Edition

@NumberSir NumberSir changed the title 发现翻译闪烁问题,想咨询一下汉化的方式 关于未来的汉化发布方式 Oct 7, 2023
@NumberSir
Copy link
Collaborator

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

@SexyAkko
Copy link

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

@NumberSir
Copy link
Collaborator

NumberSir commented Oct 10, 2023

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

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

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

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🧐enhancement 对汉化内容的建议 😵question 非问题反馈和汉化改进
Projects
None yet
Development

No branches or pull requests

6 participants