Divinity Original Sin 2 再翻訳


プロジェクト開始の動機

Divinity Original Sin 2(以下、DOS2)は公式で日本語化されているが、その翻訳の品質に不十分な点がある。最近はLLMによる日本語翻訳の品質も上がってきているので、LLMを用いて翻訳をやり直すことが出来ないかと考えた。というわけで、Claude Codeを相棒にして、DOS2の再翻訳プロジェクトをスタートした。

英語テキストの管理方法

まず最初に、DOS2において、英語テキストがゲームファイルとしてどこに保管されているか明らかにする。

以下、説明の都合上、 <GAME> をDOS2までのpathとする。(そのまま表記すれば C:\Program Files (x86)\Steam\steamapps\common\Divinity Original Sin 2 こんな感じになっているはず。)

まず、ゲームにおけるテキストは、 <GAME>\DefEd\Data\Localization\English.pak で管理されていることが分かった。 .pak という拡張子は、Larian製ゲームのエンジンが使うアーカイブ形式のファイル拡張子である。 .zip のようなものだと考えればいいだろう。

English.pak を解凍すると、以下のような構造になっている:

Localization/
└─ English/
   ├─ english.xml            13,520,502 B  ← ★本体。英語原文 92,327件
   ├─ english_to_F.xml               29 B  ← 空(中身は宣言行だけ)
   ├─ language.lsx                  573 B  ← 言語定義
   ├─ Gender/Female/
   │   ├─ english.xml                29 B  ← 空
   │   └─ english_to_F.xml           29 B  ← 空
   └─ Subtitles/                             245ファイル(すべて .lsx)
       ├─ CS_Epilogue_hxxx.lsx               203個(エピローグの各場面)
       └─ その他 42個
           CS_Intro.lsx / CS_Drowning.lsx / CS_BackToRC.lsx など 9個
           Ending_1A_Part1A.lsx 〜 Ending_4C_Part2B.lsx  25個
           Origin_Intro_{Fane,Ifan,Lohse,Beast,Sebille,RedPrince}.lsx 6個
           EndMovie.lsx / Windego_Cutscene_Line_19.lsx

英語原文は english.xml で管理されていることが分かった。

中身は以下のようになっている:

<contentList>
    <content contentuid="h00002e6cg3610g4788g8e0eg7615ac443b6e">We agreed to help Hannag against the Magisters.</content>
    <content contentuid="h0001d8b9g13d6g4605g85e9g708fe1e537c8">Custom</content>
    ...
</contentList>

つまり、ゲーム内で取り扱われるテキストには、全て独自のID= contentuid が割り振られている。

ちなみに、語数で言えば約115万語であり、ハリーポッター全7巻(約108万語)とほぼ同じ量となる!

.pak を解凍する方法

コンピュータ上のどんなデータも、それをバイト列として読み取ることが出来る。もちろん、そのバイト列から意味を取り出すことが出来るかは別であるが。

Claudeが解析した結果、 .pak のバイト列には以下の図のような構造があることが分かった。

.pak ファイルの構造

目的のファイル(Target File)を .pak ファイルから取り出す過程は以下のようになる:

  1. 末尾の4バイトに注目する。ここはASCIIコードでLSPKという文字列になっている。これはLarian Studio Packageの略である。
  2. 次の4バイトに注目する。ここはheaderのサイズを表している。
  3. headerサイズが分かったので、末尾から headerSize だけ遡ってheaderを読み込むことが出来る。
  4. headerから fileListOffset を読み取る。
  5. 先頭から fileListOffset だけ進んだ位置で、目次(Table of Contents)の始まりが確定するので、目次が読み込める。
  6. 目次には .pak に格納されているファイル数 numFiles の他に、ファイル毎に固定長(280バイト)のブロックが入っている。
  7. 各ブロックはファイル名の他に、ファイルバイト列の先頭を見つけるための offset 、末尾を知るための sizeOnDisk 、そしてファイルの圧縮形式を表すフラグ Flags が含まれている。
  8. 先頭から offset だけ進んだ位置で目的のファイルが見つかる。これはLZ4圧縮されているので、後は解凍するだけ。

テキストがゲーム画面に出力される仕組み

基礎知識

ビット・バイト・16進数…

まず、人間が扱っているデータをどうやってデジタル化するかという問題意識があった。そこで、人間が扱う標準的な文字に番号を割り当てて、あらゆる文章を数字の列として取り扱う方法が考えられた。有名なのはASCIIコード。

コンピュータが究極的にはスイッチのON/OFFでデータを保持しているから、ビット=2進数1桁が自然な単位となる。しかし1ビットでは2種類の情報しか扱えないので、当然文字は無理だ。というわけで幾つかのビットをまとめて一つの文字に対応させるという規則が考えられる。何個をひとまとまりにするかについて、コンピュータの黎明期には色々案が出たらしいが、結局は8個がスタンダードになった。

数学的に言えば8は2の冪で書けるので、ビットと相性が良い。それに8ビットあれば、256種類の情報が区別出来るので、人間が扱う文字全てを含めてもまだ余裕がある。ということで、これが1バイトという単位になった。

コンピュータ上に存在するあらゆるデータは究極的にはバイトの列である。しかし、実際に読み取る際には1バイト=8ビットが単位となっている。(コンピュータ上で1バイト単位で住所が割り当てられるシステムとなっている。)

8ビットは2進数で8桁となる。人間が読むには桁数が大きすぎる。というわけで、データを人間が読む時にはこれを16進数化するのが一般的である。なぜ16進数かと言えば、それは8ビットがちょうど2桁で表現できるので、区切りが良いからだ。実際、16は8の次の2冪である。

.xml について

人間が取り扱う文書について考えてみる。最も簡単に見れば、これは文字の羅列なのであるが、人間同士が理解するためには、そこに構造が付与されるのが普通である。例えば題名とか見出しとか、パラグラフといった構造を文書に付与することによって、人間はその文書を効率的に読み取ることができる。本の場合、そういった構造を付与するためには、文字サイズを大きくしたり、インデントしたりして視覚的な差異を生み出すことになる。これを単に文字の羅列として見るのは、こういった構造化の情報を忘れ去ることと言えるだろう。

HTMLは人間が取り扱う文書について、その構造までを表現するための技術である。ここでは本で行っているような視覚的な差異に頼るのではなく、文書の中に構造を示すための記号(タグ)を埋め込む=マークアップする。

こうして、情報をやり取りする際に、その中身を適切に構造化することで理解しやすくするというのは、人間の自然な習慣である。そこで、文書の構造を超えて、より広範な構造化が行えるように母体として作られたのがXMLというマークアップ言語である。

XMLはExtensible Markup Languageの略である。

例えば天気の情報についてやりとりするなら、気温、湿度、日付といった数字を単に羅列するのではなく、それぞれ特定のタグでくくることで、構造化した方がずっと分かりやすい。ここでXMLの出番となる。XMLは自由にタグを作ることが出来るので、予めその規則さえ共有しておけば、構造化した情報のやり取りをスムーズに行うことが可能となる。


「その他」に戻るメニューに戻る

最終更新: 2026-09-08