0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてアドベントカレンダーに参加してみた

私は、2021年からHuman Beatbox世界大会 "Grand Beatbox Battle" の非公式サイトである「GBBINFO-JPN」をひとりで運用している大学4年生です。
日頃からお世話になっているCoderabbitのアドベントカレンダーを見つけたので、初めて参加してみます。

GBBINFO-JPNというWebサイト自体は、ほとんどのアクセスが日本からではあるものの、昨今の韓国のBeatbox人気も相まって、海外からのアクセスも常に一定数ある状態で、多言語対応の需要が常にあります。
そこで、GBBINFO-JPNでは、日本語を含む20言語の翻訳を提供しています。

  • 現時点での対応言語一覧
locale_names = ['日本語', '한국어', 'English', 'Беларуская', 'Dansk', 'Deutsch', 'Español', 'Eesti', 'Français', 'Gaeilge', 'हिन्दी', 'Magyar', 'Italiano', 'Bahasa MY', 'Norsk', 'Polski', 'Português', 'தமிழ்', '简体中文', '繁體中文']

今回は、「GBBINFO-JPN」の「多言語対応」に焦点をあてて、各種AIツール活用事例をご紹介します。

「GBBINFO-JPN」に関するqiita記事はこちら:

GBBINFO-JPNの構成

開発を始めた当時Pythonしか知らなかったこともあり、Pythonのみの構成となっています。

  • フロント:Jinja2 + Flask
    • たまにバニラJSも書く
  • バック:Flask
  • 多言語対応:Flask-Babel

今回の事例はFlask-Babelによるものですが、Django (標準のi18n機能)FastAPI-Babelもほとんど同じやり方ですし、翻訳を静的ファイルに記述する開発形式であればどんな構成でも応用可能です。

Flask-Babel 翻訳作業

Django/Flaskリポジトリがすでにあり、Flask-Babelがインストールしてある前提です。
翻訳作業はいたって簡単です。

初期設定1

まず、htmlテンプレートファイルに少しコードを書き加えます。
これぐらいならAIに言えばすぐやってくれます。GitHub Copilot無料枠のモデルで十分です。

<h1>{{ gettext("こんにちは") }}</h1>

<p>{{ gettext("このページは {language} に対応しています")}}</p>

{language}jinja2の変数です。Flaskから渡せます。

初期設定2

Pythonのmain.py (ルートを設定しているファイル) において、以下のコードを追加します。

from flask import Flask, session, request
from flask_babel import Babel, _

app = Flask(__name__)

#############################################################################
# 追加
babel = Babel(app)

# 対応言語はお好みで
SUPPORTED_LOCALES = ["ja", "en", ...]

# ユーザーに合わせた言語設定
@babel.localeselector
def locale_selector():
    session["language"] = request.accept_languages.best_match(SUPPORTED_LOCALES)
    return session["language"]

Python上の細かい設定は今回の趣旨にあわないので省略

翻訳作業

作業1

  1. 翻訳対象のテキストを抽出し、テンプレートファイルを生成するコマンド
  2. 指定した言語の翻訳ファイル (.po) を初期化

コマンドプロンプトで実行します。

# 1
pybabel extract -F babel.cfg -o messages.pot .

# 2
pybabel init -i messages.pot -d translations -l <言語コード>

# 2 実際の例 (en = 英語)
pybabel init -i messages.pot -d translations -l en

作業2

作業1を行うと、messages.poというファイルが出てきます。

msgid "こんにちは"
msgstr ""

#, python-brace-format
msgid "このページは {language} に対応しています"
msgstr ""

ここに手作業で翻訳してもいいですし、polibというPythonライブラリと翻訳APIを合わせれば完全自動化も可能です。

import polib
from my_function import translate  
# translate関数については、
# Deepl APIやGoogle Translate APIと合わせるなど、
# 自由に関数を作ってください。

path = "PATH_TO_PO_FILE"
po = polib.pofile(path)  # ファイルを読み込む
untranslated_entries = po.untranslated_entries()

for entry in untranslated_entries:  # 翻訳実行
    original_text = entry.msgid
    translated_text = translate(original_text)
    entry.msgstr = translated_text

po.save(path)  # 保存

翻訳が終わると以下のようになります。

msgid "こんにちは"
msgstr "Hello"

#, python-brace-format
msgid "このページは {language} に対応しています"
msgstr "This page is available in {language}"

作業3

翻訳が終わったら、コンパイルを行います。

pybabel compile -d translations

たったこれだけです。多言語対応って意外と簡単です。

翻訳自動化

ここからが本題です。

まず、翻訳そのものはコードで自動化はできるものの、現在私はGitHub Copilotで行っています。
カスタムプロンプトで翻訳の流れを書いて、実行するだけですぐにやってくれます。

---
agent: agent
description: 指示に従って、pythonを実行し、翻訳を行うためのガイドラインを提供します。
---

## 手順
1. `python tools\translate.py`を実行 (未翻訳のワードがすべてtranslation_targets.mdに出てくる)
2. `tools/translation_targets.md` を読む
  - 翻訳対象が無い場合、ここで終了
3. 各 PO ファイルについて、以下を順に処理する:
  - `msgid` を変更せず、`msgstr` が空のエントリに翻訳を追加する。
  - `#, fuzzy` が付与されているエントリは、文脈を確認して適切な翻訳に置き換え、`fuzzy` フラグを削除する。
4. `python tools\translate.py`を実行 (未翻訳のワードがすべて翻訳されたことを確認)

なお、翻訳対象文は `tools/translation_targets.md` の文字列を使って検索して特定すること。

## 注意点(厳守)
- 変数やプレースホルダ(例: `{variable}`)はそのまま残す。
- 翻訳のトーンは原文の意図に合わせる(形式的/口語的など)。
- 各 PO ファイルでは `msgstr` を追加・修正し、PO の構文やエンコーディングを壊さないこと。
- 既存の訳文(空でない `msgstr`)は変更しない。

GitHub Copilotは本来コードを書くためのツールですが、さすがAI、結構正確な翻訳をしてくれます。
また、翻訳作業手順で示したコマンドも、Pythonコードos.system("YOUR_COMMAND")で自動化してCopilotに実行させることで効率化しています。

今回は紹介しませんが、GitHub ActionsなどのCIで翻訳がすべてできているかのチェックをしてもいいかもしれません。

翻訳レビュー

翻訳作業そのものがこれにて終了で、あとはデプロイするだけです。私も翻訳実装をするまでは、これ以上できることは無いと思っていました。
しかし、私は以前からCoderabbitを活用していて、すべてのpull requestにレビューをもらっていました。
ある時、いつも通り翻訳更新PRを作ってレビューを見ると...

image.png

Coderabbitが一生懸命翻訳のレビューをしていました。

しかも場合によってはhtmlファイルを確認して文脈を確認したうえでのレビューを提供してくれたり、diffの外側まで見て指摘してくれます。

Coderabbit以外にもAIコードレビューサービスをいくつか試しましたが、翻訳の内容にまで突っ込んだ指摘をしてくれたのは、Coderabbitのみでした。

image.png

さすがに翻訳はソースコードとは少し違うから見てもらえないかなと思ったのですが、1つ1つ丁寧に確認しているログがしっかり残っており、これには驚きました。
(ただしめちゃくちゃ時間かかります...)

20言語も対応しているとすべてをこちらで検証するのは難しいですが、そもそもCopilotで使えるAIって自然言語を学習したものです。ChatGPT3がリリースされた時点で、すでに翻訳については高評価だったので、今後どんなモデルが出ても翻訳に関して心配する必要はないと考えています。

実際、韓国語・中国語・英語ネイティブの方に確認いただいたところ、翻訳精度に関して高い評価をいただいています。

おそらくはCoderabbitの方すら想像していないであろう、かつ非常に簡単(ただCoderabbitを導入するだけ!)な活用事例でした。

appreciate = {
    '日本語': 'ここまで読んでいただき、ありがとうございました!',
    '한국어': '끝까지 읽어주셔서 감사합니다!',
    'English': 'Thank you for reading until the end!',
    'Беларуская': 'Дзякуй, што дачыталі да канца!',
    'Dansk': 'Tak fordi du læste med helt hertil!',
    'Deutsch': 'Vielen Dank fürs Lesen bis hierhin!',
    'Español': '¡Gracias por leer hasta aquí!',
    'Eesti': 'Aitäh, et lugesite lõpuni!',
    'Français': "Merci d'avoir lu jusqu'ici !",
    'Gaeilge': 'Go raibh maith agat as léamh go dtí seo!',
    'हिन्दी': 'यहाँ तक पढ़ने के लिए धन्यवाद!',
    'Magyar': 'Köszönöm, hogy eddig elolvastad!',
    'Italiano': 'Grazie per aver letto fin qui!',
    'Bahasa MY': 'Terima kasih kerana membaca sehingga ke sini!',
    'Norsk': 'Takk for at du leste helt hit!',
    'Polski': 'Dziękuję za przeczytanie do końca!',
    'Português': 'Obrigado por ler até aqui!',
    'தமிழ்': 'இவ்வளவு தூரம் படித்ததற்கு நன்றி!',
    '简体中文': '感谢您读到这里!',
    '繁體中文': '感謝您讀到這裡!',
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?