プラグインから英日翻訳辞書を作る

環境構築

プラグインから英日翻訳辞書を作ったときのまとめ。

英日翻訳辞書はないが翻訳済みプラグインはある、という場合にプラグインから英日翻訳辞書を作ってみました。

辞書生成PHPスクリプト

translator.php (php)

<?php
error_reporting(E_ALL);
mb_internal_encoding('UTF-8');
?>
<!doctype html>
<html lang="en">
<head>

<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<title>英日辞書生成</title>
<style>
    body { margin-bottom: 100px; }
    h1 { margin: 40px 0 20px 0; }
</style>
<body>

<div class="container">

<form action="./" method="post" enctype="multipart/form-data" class="form">
    <div class="row mb-3">
        <label for="contents" class="col-sm-2 col-form-label">英英辞書</label>
        <div class="col-sm-10">
            <input name="english" type="file" class="form-control-file">
        </div>
    </div>

    <div class="row mb-3">
        <label for="contents" class="col-sm-2 col-form-label">日日辞書</label>
        <div class="col-sm-10">
            <input name="japanese" type="file" class="form-control-file">
        </div>
    </div>

    <div class="row mb-3">
        <label for="contents" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <button type="submit" class="btn btn-primary">アップロード</button>
        </div>
    </div>
</form>

<?php

if ( $_FILES['english']['tmp_name'] && $_FILES['japanese']['tmp_name'] ) {
    try {
        parse_data();
    } catch (Exception $e) {
        echo '<p>' . $e->getMessage() . '</p>';
    }
}
?>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</script>

</body>
</html>
<?php
function parse_data()
{
    $fp = fopen($_FILES['english']['tmp_name'], 'r');

    if ( !$fp ) {
        throw new Exception('could not open english data.');
    }

    $rec_filters = [ 'BOOK', 'DIAL', 'INFO', 'QUST' ];
    $dataset = [];

    $is_in_string = false;
    $edid = null;
    $rec = null;
    $is_in_source = false;
    $source = null;

    $line = 0;

    while ( !feof($fp) ) {
        $line++;
        $buf = fgets($fp);

        if ( $is_in_string ) {
            if ( $is_in_source ) {
                $source .= $buf;
            } else {
                if ( strpos( $buf, '<EDID>' ) !== false ) {
                    if ( preg_match('/>([^<]+)</', $buf, $matches) ) {
                        $edid = $matches[1];
                    }
                } elseif ( strpos( $buf, '<REC' ) !== false ) {
                    $rec = trim($buf);
                } elseif ( strpos( $buf, '<Source>' ) !== false ) {
                    $is_in_source = true;
                    $source = ltrim($buf);
                    $source = str_replace('<Source>', '', $source);
                }
            }

            if ( $is_in_source ) {
                if ( strpos( $source, '</Source>' ) !== false ) {
                    $is_in_source = false;
                    $source = rtrim($source);
                    $source = str_replace('</Source>', '', $source);
                }
            }
        } else {
            if ( strpos( $buf, '<String' ) !== false ) {
                $is_in_string = true;
            }
        }

        if ( $is_in_string ) {
            if ( strpos( $buf, '</String>' ) !== false ) {
                $is_in_string = false;

                if ( !$edid ) {
                    throw new Exception('english line ' . $line . ' : edid not found.');
                }

                if ( !$rec ) {
                    throw new Exception('english line ' . $line . ' : rec not found.');
                }

                foreach ( $rec_filters as $valid_rec ) {
                    if ( strpos($rec, $valid_rec) !== false ) {
                        $dataset[$edid][$rec] = $source;
                        break;
                    }
                }

                $edid = null;
                $rec = null;
                $source = null;
            }
        }
    }

    fclose($fp);

    $fp = fopen($_FILES['japanese']['tmp_name'], 'r');

    if ( !$fp ) {
        throw new Exception('could not open japanese data.');
    }

    $is_in_string = false;
    $edid = null;
    $rec = null;
    $string_buf = null;
    $is_in_source = false;
    $source = null;
    $is_in_dest = false;
    $dest = null;

    $line = 0;

    echo '<form><textarea class="form-control" name="contents" rows="30">';

    try {
        while ( !feof($fp) ) {
            $line++;
            $buf = fgets($fp);

            if ( $is_in_string ) {
                if ( $is_in_source ) {
                    $source .= $buf;
                    $buf = null;
                } elseif ( $is_in_dest ) {
                    $dest .= $buf;
                    $buf = null;
                } else {
                    if ( strpos( $buf, '<EDID>' ) !== false ) {
                        if ( preg_match('/>([^<]+)</', $buf, $matches) ) {
                            $edid = $matches[1];
                        }
                    } elseif ( strpos( $buf, '<REC' ) !== false ) {
                        $rec = trim($buf);
                    } elseif ( strpos( $buf, '<Source>' ) !== false ) {
                        $is_in_source = true;
                        $source = ltrim($buf);
                        $source = str_replace('<Source>', '', $source);
                        $buf = null;
                    } elseif ( strpos( $buf, '<Dest>' ) !== false ) {
                        $is_in_dest = true;
                        $dest = ltrim($buf);
                        $dest = str_replace('<Dest>', '', $dest);
                        $buf = null;
                    }
                }

                if ( $is_in_source ) {
                    if ( strpos( $source, '</Source>' ) !== false ) {
                        if ( !$edid ) {
                            throw new Exception('english line ' . $line . ' : edid not found.');
                        }

                        if ( !$rec ) {
                            throw new Exception('english line ' . $line . ' : rec not found.');
                        }

                        $source = rtrim($source);
                        $source = str_replace('</Source>', '', $source);

                        $string_buf .= ' <Source>';

                        ob_start();

                        if ( isset( $dataset[$edid][$rec] ) ) {
                            echo htmlspecialchars($dataset[$edid][$rec]);
                        } else {
                            echo htmlspecialchars($source);
                        }

                        $string_buf .= ob_get_clean();
                        $string_buf .= '</Source>';
                        $string_buf .= PHP_EOL;

                        $is_in_source = false;
                    }
                } elseif ( $is_in_dest ) {
                    if ( strpos( $dest, '</Dest>' ) !== false ) {
                        $dest = rtrim($dest);
                        $dest = str_replace('</Dest>', '', $dest);

                        $string_buf .= ' <Dest>';

                        ob_start();
                        echo htmlspecialchars($dest);
                        $string_buf .= ob_get_clean();

                        $string_buf .= '</Dest>';
                        $string_buf .= PHP_EOL;

                        $is_in_dest = false;
                    }
                }

                if ( $buf ) {
                    $string_buf .= $buf;
                }
            } else {
                if ( strpos( $buf, '<String' ) !== false ) {
                    $is_in_string = true;
                    $string_buf = $buf;
                    $buf = null;
                }

                if ( $buf ) {
                    echo $buf;
                }
            }

            if ( $is_in_string ) {
                if ( strpos( $buf, '</String>' ) !== false ) {
                    if ( !$edid ) {
                        throw new Exception('english line ' . $line . ' : edid not found.');
                    }

                    if ( !$rec ) {
                        throw new Exception('english line ' . $line . ' : rec not found.');
                    }

                    foreach ( $rec_filters as $valid_rec ) {
                        if ( strpos($rec, $valid_rec) !== false ) {
                            echo $string_buf;
                            break;
                        }
                    }

                    $is_in_string = false;
                    $string_buf = null;
                    $edid = null;
                    $rec = null;
                    $source = null;
                    $dest = null;
                }
            }
        }
    } catch (Exception $e) {
        echo '</textarea></form>';
        throw $e;
    }

    echo '</textarea></form>';

    fclose($fp);
}

$rec_filtersに使いたいシグネチャを追加します。

英英辞書を作る

xTranslatorでオリジナルのプラグインを開きます。

翻訳をすべてリセットして、すべて確定済みにして、XMLをエクスポートします。

ファイル名は modname_english_english.xml がいいでしょう。

日日辞書を作る

xTranslatorで翻訳済みのプラグインを開きます。

翻訳をすべてリセットして、すべて確定済みにして、XMLをエクスポートします。

ファイル名は modname_japanese_japanese.xml がいいでしょう。

英日辞書を作る

PHPスクリプトをサーバに設置してページを開き、英英辞書と日日辞書をアップロードすると、テキストエリアの中に英日辞書が生成されます。

テキストをすべてコピーし、テキストエディタにペーストして、ファイルを保存します。

ファイル名は modname_english_japanese.xml がいいでしょう。

翻訳済みプラグインを作る

xTranslatorでオリジナルのプラグインを開きます。英日辞書をインポートします。

FormIDが一致だと、翻訳される箇所がもっとも多くなりますが、FormIDはそのままで文章が大きくかわった部分に間違った翻訳が適用されてしまう可能性が高くなります。

原文が一致だと、誤翻訳が減りますが、原文が1文字でも変更された部分は翻訳されません。

FormIDと原文が一致だと、最も安全ですが、翻訳されない箇所も多くなります。

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