问题来源于游戏汉化,游戏剧本文件资源拆包后的样子如下:
CMD-x05
SoundBgmPlay int 2
ShowBackground string "ev901a0.iph" int 10
CMD-x05
SetLine string " 戦いは終わった。"
ShowLines
SetLine string " 当事者達には長い戦いだったかもしれないが、未"
SetLine string " 来の歴史書には数行で記される戦い。"
ShowLines
SetLine string " ヴィスト王国が他国に侵攻し、抵抗した周辺諸国"
SetLine string " は団結してこれに抵抗。"
SetLine string " そしてヴィスト王国が滅ぼされた。"
ShowLines
SetLine string " ただ、それだけの戦い。"
ShowLines
SetLine string " しかし、その戦いには数多の人物が関わった。"
ShowLines
SetLine string " この時代を、そして次の時代を作る者達が。"
ShowLines
SetLine string " この戦いを乗り越えた者達は、それぞれに未来を"
SetLine string " 歩み始める。"
ShowLines
JumpConditional f`short 220 bool false *label99
JumpConditional f`short 210 bool false *label99
CMD-x38 int 2 null
CMD-x26 f`short 332
_label99
JumpConditional f`short 208 bool false *label120
CMD-x38 int 3 null
CMD-x26 f`short 333
_label120
JumpConditional f`short 221 bool false *label141
CMD-x38 int 4 null
CMD-x26 f`short 334
_label141
JumpConditional f`short 210 bool false *label198
JumpConditional f`short 222 bool false *label182
CMD-x38 int 10 null
CMD-x26 f`short 335
CMD-x02 *label198
Jump *label198
_label182
CMD-x38 int 11 null
CMD-x26 f`short 335
CMD-x02 *label198
_label198
JumpConditional f`short 223 bool false *label255
JumpConditional f`short 224 bool false *label239
CMD-x38 int 5 null
CMD-x26 f`short 336
CMD-x02 *label255
Jump *label255
_label239
CMD-x38 int 6 null
CMD-x26 f`short 336
CMD-x02 *label255
_label255
JumpConditional f`short 201 bool false *label351
JumpConditional f`short 202 bool false *label351
JumpConditional f`short 222 bool false *label351
JumpConditional f`short 223 bool false *label351
JumpConditional f`short 225 bool false *label351
JumpConditional f`short 226 bool false *label351
JumpConditional f`short 227 bool false *label351
JumpConditional f`short 228 bool false *label351
CMD-x38 int 1 null
CMD-x26 f`short 331
CMD-x02 *label415
_label351
JumpConditional f`short 335 bool true *label403
JumpConditional f`short 336 bool true *label387
CMD-x38 int 7 null
CMD-x26 f`short 337
CMD-x02 *label415
_label387
CMD-x38 int 8 null
CMD-x26 f`short 337
CMD-x02 *label415
_label403
CMD-x38 int 9 null
CMD-x02 *label415
_label415
CMD-x06
CMD-x06
可以看到,其中带有许多游戏的命令,我们不可能将这样的文本交给翻译,于是我们将文字转化成易读的形式:
m 0 戦いは終わった。
m 1 当事者達には長い戦いだったかもしれないが、未
m 2 来の歴史書には数行で記される戦い。
m 3 ヴィスト王国が他国に侵攻し、抵抗した周辺諸国
m 4 は団結してこれに抵抗。
m 5 そしてヴィスト王国が滅ぼされた。
m 6 ただ、それだけの戦い。
m 7 しかし、その戦いには数多の人物が関わった。
m 8 この時代を、そして次の時代を作る者達が。
m 9 この戦いを乗り越えた者達は、それぞれに未来を
m 10 歩み始める。
翻译拿到了上面的文字后进行翻译,翻译后的结果如下:
m 0 战争结束了。
m 1 虽然当事者们或许进行了很长时间的战斗,
m 2 但战斗在未来的历史书中仅留下了数行。
m 3 威斯特王国侵略了其他国家,周边诸国
m 4 团结起来与之对抗。
m 5 然后威斯特王国被灭亡了。
m 6 仅仅,是这样的战斗罢了。
m 7 不过,这场战斗牵连了众多的人物。
m 8 开创了这个时代,以及下个时代的人们。
m 9 还有跨越了这场战争的人们,开始走向
m 10 各自的未来。
m 11
现在的问题是,要想把翻译好的文字封回游戏,必须将翻译好的文字嵌入到最开始的那种代码当中,问如何实现文字替换?
最直接的想法是一次性的读取整个原始代码,然后将翻译内容一行一行替换掉,但这样有个问题,那就是可能会误操作掉其他部分。比如说m0后面是123,m5后面是12345,那么在替换m0的时候就会把m5后面的文字也替换掉,这样就使得想要替换m5的时候找不到原始文本。
如果非要按照上面的思路来,那么有一个补救方法,那就是将日文文本按照长度排序,由长到短依次替换,这样就不会出现误替换的现象了。
那么有没有其他方法呢?当然有。注意到剧本文本只出现在“SetLine string”之后,所以只要保证第n次替换只替换第n个“SetLine string”之后的文本即可。
C#的实现如下,程序不难,但仍有可参考的地方,故记录下来以作备忘:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace stringReplace
{
class Program
{
static void Main(string[] args)
{
//String orgCode = System.IO.File.ReadAllText("D:/Test/代码/ending00.txt");
StreamReader orgCodeStream = File.OpenText("D:/Test/代码/ending00.txt");
StreamReader jpStream = File.OpenText("D:/Test/日文/ending00.txt");
StreamReader chsStream = File.OpenText("D:/Test/中文/ending00.txt");
String jp = null;
String chs = null;
String newCode = null;
String temp = null;
while (true)
{
jp = jpStream.ReadLine();
chs = chsStream.ReadLine();
if (String.IsNullOrEmpty(jp) || String.IsNullOrEmpty(chs)) break;
while (true)
{
temp = orgCodeStream.ReadLine();
if (temp.Equals(null)) System.Console.WriteLine("Error1");
if (temp.IndexOf("SetLine string") != -1) break;
else if (!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);
else newCode = String.Concat(newCode, temp);
}
temp=temp.Replace(jp.Substring(jp.IndexOf(" ")+2), chs.Substring(chs.IndexOf(" ")+2));
if(!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);
else newCode = String.Concat(newCode, temp);
}
temp = orgCodeStream.ReadLine();
while (!String.IsNullOrEmpty(temp))
{
if (!String.IsNullOrEmpty(newCode)) newCode = String.Concat(newCode, "\r\n", temp);
else newCode = String.Concat(newCode, temp);
temp = orgCodeStream.ReadLine();
}
newCode = String.Concat(newCode, "\r\n");
StreamWriter sw = new StreamWriter("D:/1.txt");
sw.Write(newCode);
sw.Flush();
sw.Close();
jpStream.Close();
chsStream.Close();
orgCodeStream.Close();
}
}
}