翻訳 link

Ren'Py には、ビジュアルノベルを翻訳するための包括的なフレームワークがあります。これによって主に4種類のものを翻訳できます:

台詞

スクリプトのメインの台詞は、分割、連結、省略、行の並べ替えを伴う翻訳ができます。

メニューとインターフェイスの文字列

すべてのインターフェイスのテキストが翻訳できます。

画像とファイル

ある言語が選択されたときに、通常とは異なる画像やその他のファイルを含められます。

スタイル

言語に合わせてスタイルをカスタマイズできるため、ある言語が選択された時にゲームで使用されるフォントを自動的に切り替えられます。

Ren'Py の翻訳サポートは現在、正式に認可されている翻訳、つまりゲームの制作者が翻訳者に向けてゲームのスクリプトをリリースしている場合や、制作者自身が翻訳用の雛形を作成している場合に焦点を当てています。正式な認可を得ていない場合の翻訳では、これよりも制限があります。

主言語と副言語 link

Ren'Py は、それぞれのゲームが1つの主言語によって書かれていると想定します。このときの言語は None 言語と呼ばれますが、その言語が実際に何であっても構いません(例えば、ゲームが英語で書かれている場合は、英語が None 言語となります)。

副言語は、Python の識別子としても振る舞える名前によって関連付けられます(英字またはアンダースコアで始まり、英数字とアンダースコアが続きます)。

None 言語が選択されると、ほとんどの Ren'Py の翻訳関数は例えばアクセス性メニューにあるような Ren'Py 内部組み込みの文字列を除いて無効となります。それらの文字列はあなたのプロジェクトのコードにはありませんが、そのゲームのリリースバージョンにも含まれています。それらは game/tl/None/common.rpym ファイルにあり、 1) None 言語が英語でないときにそれらの文字列の翻訳を提供すること、 2) それらの文字列を制作者がかれらのゲーム用にカスタマイズできるようにすることだけを目的としています。

そのプロジェクトが作成されたときのランチャーの言語がこのファイルが最初に内部の文字列を翻訳する言語になるでしょう。

翻訳ファイルの生成 link

プロジェクトのスクリプトが利用できる場合、Ren'Py ランチャーでプロジェクトを開き「Generate Translations(飜訳の生成)」を選んで翻訳ファイルを生成できます。ランチャーは生成する言語の名前の入力を求めた後、翻訳ファイルの作成または更新を行います。

翻訳ファイルはゲームディレクトリーの中の「tl」サブディレクトリーの下に設置されます。例えばチュートリアルプロジェクトの piglatin の翻訳を作成した場合、翻訳ファイルは tutorial/game/tl/piglatin の下に設置されます。

ゲームのスクリプトファイル1つに対して翻訳ファイルが1つ作成されます。共通のコードで見つかった文字列の翻訳を含めるために、common.rpy ファイルも作成されます。

台詞の翻訳 link

Ren'Py はビジュアルノベルエンジンなので、ほとんどの翻訳は台詞と対応していると予想しています。Ren'Py には柔軟なフレームワークがあり、台詞の分割、結合、並べ替え、完全な省略を行えます。

翻訳ユニット link

翻訳の基本ユニットは、0以上の翻訳可能なステートメントを含むブロックであり、任意で say ステートメントが一つ続きます。翻訳可能なステートメントは voice ステートメントと nvl ステートメントです。例えば、次のゲームを見て下さい:

label start:
    e "Thank you for taking a look at the Ren'Py translation framework."

    show eileen happy

    e "We aim to provide a comprehensive framework for translating dialogue, strings, images, and styles."

    e "Pretty much everything your game needs!"

これは複数の翻訳ユニットに分割されます。それぞれのユニットには割り当てられた識別子があり、識別子はユニットに先行するラベルと、ユニット内のコードから生成されます(複数のユニットに同一の翻訳番号が割り当てられた場合は、それらを区別するために2つ目以降のユニットに通し番号が振られます)。

上記の例において、生成される1つ目のユニットには start_636ae3f5 という識別子が割り当てられ、次のステートメントを含んでいます:

e "Thank you for taking a look at the Ren'Py translation framework."

2つ目のユニットには start_bd1ad9e1m という識別子が与えられ、次を含みます:

e "We aim to provide a comprehensive framework for translating dialogue, strings, images, and styles."

3つ目のユニットには start_9e949aac という識別子が与えられ、次を含みます:

e "Pretty much everything your game needs!"

これらのユニットは、Ren'Py がゲームを読み込んだ時に自動的に生成されます。

Translate ステートメント link

ある言語の翻訳を生成するとき、Ren'Py はそれぞれの翻訳ユニットに対応した translate ステートメントを生成します。上記のコードを翻訳するとき、Ren'Py は次のコードを生成します

# game/script.rpy:95
translate piglatin start_636ae3f5:

    # e "Thank you for taking a look at the Ren'Py translation framework."
    e ""

# game/script.rpy:99
translate piglatin start_bd1ad9e1:

    # e "We aim to provide a comprehensive framework for translating dialogue, strings, images, and styles."
    e ""

# game/script.rpy:101
translate piglatin start_9e949aac:

    # e "Pretty much everything your game needs!"
    e ""

生成されたコードを編集して翻訳できます。翻訳が完了すると次のようになります

# game/script.rpy:95
translate piglatin start_636ae3f5:
    # e "Thank you for taking a look at the Ren'Py translation framework."
    e "Ankthay ouyay orfay akingtay away ooklay atway ethay En'Pyray anslationtray ameworkfray."

# game/script.rpy:99
translate piglatin start_bd1ad9e1:

    # e "We aim to provide a comprehensive framework for translating dialogue, strings, images, and styles."
    e "Eway aimway otay ovidepray away omprehensivecay ameworkfray orfay anslatingtray ialogueday, ingsstray, imagesway, andway ylesstay."

# game/script.rpy:101
translate piglatin start_9e949aac:

    # e "Pretty much everything your game needs!"
    e "Ettypray uchmay everythingway ouryay amegay eedsnay!"

メインスクリプトの中にブロックが見つかると、Ren'Py はそのブロックに対応する translate ステートメントが存在するかどうかを確認します。存在する場合は翻訳前のブロックの代わりに translate ステートメントを実行し、ユーザーに翻訳結果を表示します。

より複雑な翻訳 link

translate ステートメントでは、原文に対して1対1の翻訳にする必要はありません。例えば、長い行は分割できます:

# game/script.rpy:99
translate piglatin start_bd1ad9e1:
    # e "We aim to provide a comprehensive framework for translating dialogue, strings, images, and styles."
    e "Eway aimway otay ovidepray away omprehensivecay ameworkfray..."
    e "...orfay anslatingtray ialogueday, ingsstray, imagesway, andway ylesstay."

または、pass ステートメントに置き換えて削除できます:

# game/script.rpy:101
translate piglatin start_9e949aac:

    # e "Pretty much everything your game needs!"
    pass

条件文や Python のコードなどの、台詞以外のステートメントも実行できます。例えば次のコード

e "You scored [points] points!"

これを次のように翻訳できます:

# game/script.rpy:103
translate piglatin start_36562aba:

    # e "You scored [points] points!"
    $ latin_points = to_roman_numerals(points)
    e "Ouyay oredscay [latin_points] ointspay!"

ヒント link

翻訳された台詞の変更、特にあるラベルの中の複数の場所でその台詞が繰り返される場合には注意して下さい。

元の言語の台詞のある行を変更しても、その行の再翻訳の要求をしたくないときがあります。例えば英語のタイプミスの修正がロシア語への翻訳プロセスで影響するのは望ましくないです。

これは id 節をsay ステートメントの一部に含め、このステートメントに使用する翻訳 ID を指定して行えます。例

label start:
    e "This used to have a typo." id start_61b861a2

ラベルの追加によっても翻訳の過程で混乱が発生します。これを防ぐには、ラベルに hide 節を与えて翻訳の生成時に無視されるようにします。:

label ignored_by_translation hide:
    "..."

翻訳ブロックが Python のコードを含む場合、コードはブロックの外側に影響を及ぼすべきではありません。何故ならば、言語を変更するときに翻訳ブロックは再度開始されますが、これによって副作用が何度も発生してしまうからです。

画像とファイルの翻訳 link

ゲームを翻訳するとき、ファイルを翻訳版に置き換える必要があるかもしれません。例えば画像にテキストが含まれている場合、意味が分かるようにテキスト部分が別の言語で書かれた画像に置き換えるでしょう。

このような場合に Ren'Py は画像を翻訳ディレクトリーの中から探します。例えば「piglatin」言語において「library.png」を読み込むとき、Ren'Py は game/tl/piglatin/library.pnggame/library.png よりも優先して使います。

そのファイルが game ディレクトリー下のディレクトリーにあるなら、そのディレクトリをその言語直下にも配置するべきです。例えば game/gui/main_menu.pnggame/tl/piglatin/gui/main_menu.png を作成して翻訳できます。

スタイルの翻訳 link

ゲームの翻訳時に、スタイルの変更 (特にフォント関係のスタイル) が必要になるでしょう。Ren'Py ではこれに対し translate style ブロックと translate python ブロックで対応しています。これらのブロックには、言語関係の変数やスタイルを変更するためのコードを含められます。例えば

translate piglatin style default:
    font "stonecutter.ttf"

通常、ダイアログで使用するフォントは gui.text_font で設定されます。例外画面、アクセシビリティーメニュー、 gui メニューのようなシステムテキストに使用するフォントは gui.system_font で設定できます。システムフォントはASCIIと翻訳された言語の両方を表現できなければなりません。これらのフォント共に次のようにして設定できます。

translate piglatin python:

gui.text_font = "stonecutter.ttf" gui.system_font = "Noto Sans.ttf"

ある言語が実行された時 (ゲームの開始時、もしくは言語が変更された後)、Ren'Py は init フェーズの終了時までスタイルの内容をリセットします。次にすべての translate python ブロックとスタイルブロック、現在の言語と関連づけられた translate style ブロックを実行します。ファイル内で先に現れるブロックが先に実行されます。最後にスタイルを再構築して変更を反映します。

スタイルの翻訳はどのような .rpy ファイルにも追加できます。

翻訳ファイルの遅延読み込み link

巨大なゲームでは全ての翻訳の読み込みには時間がかかります。これらのゲームをスピードアップするために Ren'Py では遅延翻訳をサポートしています。遅延翻訳を有効化するには

define config.defer_tl_scripts = True

options.rpy ファイルや翻訳スクリプト前に読み込まれる全てのファイルに次を追加してください。

True ならこの変数は tl/language の名前のディレクトリにあるスクリプトファイルを Ren'Py が初期化時に読み込まないようにさせます。代わりにその言語が最初に有効化されたときやゲームの開始時、 Ren'Py がその言語に変更したときに読み込まれます。

tl/language ディレクトリーが初期化時に読み込まれないため、これらのファイルには init ブロックや python ブロック, screen, image, transform, 等々のステートメントのような初期化時に実行されるステートメントを含めるべきではありません。ファイルはすべて translatetranslate python, translate style ブロックで構成されるべきです。

既定の言語 link

既定の言語は次の方法によって選択します:

  • RENPY_LANGUAGE 環境変数が設定されていれば、その言語が使用されます。

  • config.language が設定されていれば、その言語が使用され、次の全てを上書きします。

  • 過去にゲームで言語を選択したことがあれば、その言語が使用されます。

  • ゲームが最初に開始された時は config.enable_language_autodetect が True になり、 Ren'Py は config.locale_to_language_function を使用して言語の自動検出を試みます。

  • ゲームの最初の開始時には、 config.default_language が使用されます。

  • これら以外の場合は、None 言語が使用されます。

翻訳に関連したアクション、関数、変数 link

言語を切り替える主な方法は、Language アクションの使用です。

Language(language) link

ゲームの言語を language に変更します。

language

翻訳先の言語の文字列、または None のときはゲームスクリプトの既定の言語を使います。

Language アクションを使うと、次のようなコードを使って設定画面に言語設定を追加できます

frame:
    style_prefix "pref"
    has vbox

    label _("Language")
    textbutton "English" action Language(None)
    textbutton "Igpay Atinlay" action Language("piglatin")

翻訳関連の関数は2つあります:

renpy.change_language(language, force=False) link

現在の言語を language に変更します。この値は文字列、または既定の言語の場合は None にできます。

renpy.get_translation_identifier() link

現在のステートメントに対する翻訳識別子を返します。

renpy.known_languages() link

既知の言語のセットを返します。これには既定の言語 None は含まれません。

さらに、文字列の翻訳に関連した 4 つの関数があります:

_(s) link

(単一のアンダースコア) s を変更せずに返します。Ren'Py はこの関数で囲まれた文字列をスキャンし、翻訳可能な文字列のリストにそれを追加します。文字列は表示されるまで翻訳されません。

__(s) link

(2重アンダースコア) s を現在の言語に直ちに翻訳して返します。この関数で囲まれた文字列は、翻訳可能な文字列のリストに追加されます。翻訳後の文字列が表示される時に、文字列翻訳にマッチすると文字列が2重に翻訳されてしまうことに注意してください。

_p(s) link

文字列を再フォーマットしてから、翻訳可能としてフラグをつけます。文字列はテキスト displayable で表示されるときに翻訳されます。これは次の形式で、文字列で使用する複数行を定義することを意図しています。

define gui.about = _p("""
    These two lines will be combined together
    to form a long line.

    This line will be separate.
    """)

再フォーマットは、各行の最初と最後のホワイトスペースを除去してテキストを1つの行にします。このとき空白行は最後に除去され、空白行があるときは、空白行に分離パラグラフが挿入されます。 {p} タグは行を改行し、空白行は追加しません。

これは文字列の翻訳において、次のように使用できます。

old "These two lines will be combined together to form a long line.\n\nThis line will be separate."
new _p("""
    These two lines will be combined together
    to form a long line. Bork bork bork.

    This line will be separate. Bork bork bork.
    """)
renpy.translate_string(s, language=<renpy.object.Sentinel object at 0x7f6601ab2ec0>) link

slanguage に直ちに翻訳して返します。 language が未指定なら、 preferences で設定された言語を使用します。この関数で囲まれた文字列は、 翻訳可能文字列のリストに追加されません。翻訳後の文字列が表示される時に文字列翻訳にマッチすると二重翻訳されるので注意してください。

言語関連の変数は2つあります。1つは config.default_language であり、ゲームのデフォルト言語を変更します。

_preferences.language link

現在の言語の名前、または既定の言語が使われている場合は Noneです。これは読み込み専用の変数として扱わなければなりません。言語を変更するには renpy.change_language() を使用して下さい。

正式な認可を受けていない場合の翻訳 link

注釈

正式に認可されていない翻訳を作成する前に、ゲーム制作者の許諾を得ることが最善です。

Ren'Py はゲーム制作者からの十分な支援が無い場合の翻訳の作成に、少しだけ対応しています。これはゲームのすべての文字列から自動的に文字列翻訳ファイルを作成する機能です。未翻訳の台詞に対して文字列翻訳を行う方法により、ゲームの翻訳が可能となります。

文字列翻訳ファイルの作成は、次の手順で行います:

  • RENPY_LANGUAGE 環境変数を翻訳先にしたい言語に設定します。

  • RENPY_UPDATE_STRINGS 環境変数を空でない値に設定します。

  • すべてのテキストが表示されるまでゲームを動かします。

これにより game/tl/language/strings.rpy ファイルが更新され、すべてのテキストが含まれた翻訳の雛形となります。

ゲームに言語切り替え機能が含まれていない場合は、 init python ブロックで config.language にその言語を設定するのが適切でしょう。

define config.language = None link

None でなければゲームの起動時にその言語に設定し、ユーザーのそれまでの選択を上書きします。

台詞の文字列翻訳を使った場合、認可を受けていない翻訳者は画像やスタイルの翻訳に対して上記で説明した方法は使えません。