UE5ローカライズ支援!POファイルとCSVを相互変換できる無料Pythonスクリプト配布【言語切替】

※本サイトはアフィリエイト広告を利用しています。

Unreal Engine 5 (UE5) を使ったゲーム開発者やローカライズ担当者向けに、POファイルとCSVファイルを簡単に相互変換できる便利なPythonスクリプトを無料配布します。

このツールを使えば、ExcelやGoogleスプレッドシートなどの表計算ソフトで翻訳作業ができるようになるため、生成AIへの依頼や複数人での作業等が格段にスムーズになります。

🎁 ツールをダウンロード

このツールはPythonスクリプトとして提供しています。以下のコードをコピーして、任意のファイル名(例:po_converter.py)で保存してください。

import polib
import csv
import sys
import tkinter as tk
from tkinter import filedialog, messagebox
import os

def po_to_csv(po_file_path, csv_file_path):
    """
    POファイルを読み込み、指定されたヘッダでCSVに変換します。
    """
    try:
        po = polib.pofile(po_file_path)
    except Exception as e:
        messagebox.showerror("エラー", f"POファイルの読み込み中にエラーが発生しました: {e}")
        return

    try:
        with open(csv_file_path, 'w', newline='', encoding='utf-8') as csvfile:
            fieldnames = ['msgctxt', 'msgid', 'msgstr']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames, quotechar='"', quoting=csv.QUOTE_MINIMAL)
            writer.writeheader()

            for entry in po:
                if entry.msgid == "":
                    continue
                row = {
                    'msgctxt': entry.msgctxt,
                    'msgid': entry.msgid,
                    'msgstr': entry.msgstr
                }
                writer.writerow(row)
        messagebox.showinfo("完了", f"'{po_file_path}'から'{csv_file_path}'への変換が完了しました。")
    except Exception as e:
        messagebox.showerror("エラー", f"CSVファイルの書き込み中にエラーが発生しました: {e}")

def csv_to_po(csv_file_path, po_file_path):
    """
    CSVファイルを読み込み、Unreal Engine 5のPOファイル形式に合わせて変換します。
    """
    po = polib.POFile()
    po.wrapwidth = 999999999

    try:
        with open(csv_file_path, 'r', encoding='utf-8', newline='') as csvfile:
            reader = csv.DictReader(csvfile, quotechar='"')
            for row in reader:
                if not row['msgid']:
                    continue
                entry = polib.POEntry(
                    msgid=row['msgid'],
                    msgstr=row['msgstr'],
                    msgctxt=row['msgctxt'] if 'msgctxt' in row and row['msgctxt'] else ''
                )
                po.append(entry)
    except FileNotFoundError:
        messagebox.showerror("エラー", f"指定されたCSVファイルが見つかりません: {csv_file_path}")
        return
    except KeyError as e:
        messagebox.showerror("エラー", f"CSVファイルのヘッダが不正です。\n必要なヘッダは 'msgctxt', 'msgid', 'msgstr' です。\n不足しているヘッダ: {e}")
        return
    except Exception as e:
        messagebox.showerror("エラー", f"CSVファイルの読み込み中にエラーが発生しました: {e}")
        return

    try:
        po.save(po_file_path)
        messagebox.showinfo("完了", f"'{csv_file_path}'から'{po_file_path}'への変換が完了しました。")
    except Exception as e:
        messagebox.showerror("エラー", f"POファイルの保存中にエラーが発生しました: {e}")

def convert_po_to_csv_action():
    input_file = filedialog.askopenfilename(
        title="POファイルを選択してください",
        filetypes=[("PO files", "*.po")]
    )
    if not input_file:
        return
    
    base_name = os.path.splitext(os.path.basename(input_file))[0]
    
    output_file = filedialog.asksaveasfilename(
        title="CSVファイルの保存先を指定してください",
        defaultextension=".csv",
        filetypes=[("CSV files", "*.csv")],
        initialfile=base_name + '.csv'
    )
    if output_file:
        po_to_csv(input_file, output_file)

def convert_csv_to_po_action():
    input_file = filedialog.askopenfilename(
        title="CSVファイルを選択してください",
        filetypes=[("CSV files", "*.csv")]
    )
    if not input_file:
        return
        
    base_name = os.path.splitext(os.path.basename(input_file))[0]

    output_file = filedialog.asksaveasfilename(
        title="POファイルの保存先を指定してください",
        defaultextension=".po",
        filetypes=[("PO files", "*.po")],
        initialfile=base_name + '.po'
    )
    if output_file:
        csv_to_po(input_file, output_file)

def create_main_window():
    root = tk.Tk()
    root.title("PO/CSV 変換ツール")

    btn_po_to_csv = tk.Button(root, text="PO -> CSV", command=convert_po_to_csv_action, width=20)
    btn_po_to_csv.pack(pady=10, padx=20)

    btn_csv_to_po = tk.Button(root, text="CSV -> PO", command=convert_csv_to_po_action, width=20)
    btn_csv_to_po.pack(pady=10, padx=20)

    root.mainloop()

if __name__ == '__main__':
    create_main_window()

📝 使い方

このツールを使うための準備と、具体的な手順を説明します。

ステップ1:必要なものを準備しよう

PythonがPCにインストールされていない場合は、まずPythonをインストールしましょう。

  • Windowsの場合は、公式サイトからインストーラーをダウンロードし、「Add Python to PATH」にチェックを入れてインストールしてください。
  • macOSやLinuxの場合は、すでにインストールされていることが多いです。ターミナルでpython3 --versionと入力して確認できます。

次に、このスクリプトが使う polibライブラリをインストール します。 コマンドライン(Windowsの場合はPowerShellやコマンドプロンプト、macOS/Linuxの場合はターミナル)を開いて、以下のコマンドを実行してください。

pip install polib

これで準備は完了です。

ステップ2:ツールの使い方

  1. UE5のツール/ローカライゼーションダッシュボードでExportTextします
  2. 保存したPythonスクリプトファイル(po_converter.pyなど)をダブルクリックするか、コマンドラインでpython po_converter.pyと入力して実行します。
  3. 小さなウィンドウが表示されます。変換したい方向のボタンをクリックしてください。
    • PO -> CSV: UE5からエクスポートしたPOファイルを選択し、CSVファイルの保存先を指定します。
    • CSV -> PO: 翻訳済みのCSVファイルを選択し、POファイルの保存先を指定します。
  4. 変換が完了すると、ダイアログボックスで成功のメッセージが表示されます。
  5. ExcelやGoogle Spread Sheet(GoogleドライブにおいてSpreadSheetで開く)で編集できます
  6. UE5のローカライゼーションダッシュボードでImportTextします

💡 このツールの特徴

  • GUIで簡単操作:コマンドラインでの面倒なファイルパス入力は不要です。
  • UE5の仕様に対応:Unreal Engine 5のローカライズ機能でエクスポートされるPOファイルの形式(文字列が1行で書かれる)にしています。
  • ファイル名が自動で連動:入力ファイル名から出力ファイル名を自動で生成するため、ファイル名の付け間違いを防ぎます。
  • 無料&オープンソース:誰でも無料で利用でき、自由に改変・再配布が可能です。
よっしー
よっしー

ほぼAIで作ったので、気に入らない点があったらAIに改造を頼んでみてください


🤖 AI翻訳との組み合わせ

DeepLの翻訳精度がかなり良いと思いますが、{PlayerName}, {Item}, %d, %s, \n などのプレースホルダーは翻訳せずそのまま残してほしいといった細かい指示ができないので、ChatGPTやGemini、Grokなどの生成AIに頼むほうが楽かなと思います。

よっしー
よっしー

また、ファイルを直接変換依頼するよりも、ある程度の量を変換するほうが精度的にも安定しそうなので、あえて半自動としました。もう少しAIが進化するとこのツールも不要になるでしょうね

というわけで、そこそこうまく変換してくれるであろうプロンプトを用意しましたのでご参考にしてください。

  1. 下記のプロンプトをChatGPTやGeminiに貼り付け
  2. ターゲット言語「日本語」を翻訳してほしい言語に書き換え
  3. 変換したCSVファイルからmsgid列をコピーし、プロンプト下部の「入力欄」に付け加え
  4. 実行
  5. 結果をCSVファイルのmsgstr列に「値を貼り付け」
あなたはプロのゲーム翻訳者です。以下ルールと例をもとにテキストを翻訳してください。

ルール:
- ターゲット言語:日本語
- 入力は 原文 のみです。
- 出力は 翻訳文 のみにしてください。
- {PlayerName}, {Item}, %d, %s, \n などのプレースホルダーは翻訳せずそのまま残してください。
- 翻訳はゲームのUI/テキスト向けに簡潔で自然な表現にしてください。

---

入力例:
Hello, {PlayerName}!
Retry
Collect %d coins

出力例(ターゲット言語=日本語):
こんにちは、{PlayerName}!
リトライ
%d 枚のコインを集めろ

---
入力:

使用例(ターゲット言語をドイツ語に)

よっしー
よっしー

さらに、いったん翻訳してもらった結果の逆変換やレビューを依頼するのもよいと思います

おわりに

よっしー
よっしー

このツールが、あなたのプロジェクトのローカライズ作業を助けることができれば幸いです!もし不明な点があれば、お気軽にコメント・X等でご質問ください。

コメント

タイトルとURLをコピーしました