tech.guitarrapc.cóm

Technical updates

ドキュメント翻訳をCopilotエージェントに補助させる

GitHubで管理しているドキュメントは多言語対応しても維持管理が大変です。 今回は、ドキュメントの翻訳・維持をCopilotエージェントに補助させる方法についてです。

3行まとめ

  • GitHub Issueを使って、GitHub Copilotエージェントにドキュメント翻訳を補助させられる
  • GitHub IssueへのGitHub Copilotアサインには、Copilotライセンスを付与されたユーザーのPATが必要
  • GitHub Copilotにどう翻訳をさせるかは、インストラクションで指示、Issueボディで調整する

多言語翻訳は維持が難しい

ドキュメント管理で難しいことの1つが多言語対応です。 自分がある言語のネイティブかどうかに関わらず、同じドキュメントを複数言語で差異なくメンテし続けるのは想像よりも大変です。

私の場合、GitHubリポジトリのREADMEは基本的に英語で書いています。しかし、時には日本語READMEや中国語READMEなど利用ユーザーに合わせた翻訳版を用意したいことがあります。 とはいえ、どれかの言語でREADMEの内容が更新されるたびに、各言語版を漏れなく・文書構造を維持したまま翻訳追随するのは、手作業ではかなり困難といわざるを得ません。

例えば次のような英語文章があったとして、ごく一部だけ変化したとしましょう。

# 適当な長い技術文章 (before)
When working with GitHub repositories, it is common to encounter the need for multi-language documentation.
Maintaining consistency across different language versions can be challenging, especially when updates are frequent.

# 一部だけ文章を修正する (after)
When working with GitHub repositories, it is common to encounter the need for multi-language documentation.
Keeping consistency across different language versions can be challenging, especially when updates are frequent and require careful attention.

多言語対応するということは、この変更を他言語版にも反映させる必要があります。多言語対応の難しいところは、文章入れ替え、追加、削除だけではなく、ニュアンスの違いなども考慮しなければならない点です。

# 適当な長い技術文章の日本語訳 (before)
GitHubリポジトリを扱う際、多言語ドキュメントの必要性に直面することがよくあります。
異なる言語バージョン間での一貫性を維持することは、特に更新が頻繁な場合、困難です。

# 変更を反映させた日本語訳 (after)
GitHubリポジトリを扱う際、多言語ドキュメントの必要性に直面することがよくあります。
異なる言語バージョン間での一貫性を維持することは、特に更新が頻繁で注意が必要な場合、困難です。

LLMの翻訳補助

長年この難しさに悩まされ、多言語対応を断念することも多かったのですが、最近はLLM(大規模言語モデル)による翻訳補助がかなり実用的になってきました。 GitHubの場合、こういったドキュメント記述タスクにGitHub Copilotエージェントを割り当てるのは想定されたユースケースの一つです。

GitHub Copilotのユースケース例

ただ、何も補助なしでCopilotエージェントに翻訳を任せるのはいくつか微妙な点があります。

  • どこまで翻訳するか、どのような基準で翻訳するかが安定しない
  • コードやリンクなど意図しない箇所が翻訳されえる
  • 固有語句の翻訳ニュアンスがずれえる
  • ドキュメント毎の言語やスタイルの違い対応が一貫性を欠く

ちゃんと使うなら、インストラクションを与えて翻訳基準を明確にすると意図した翻訳が得られやすくなります。例えば以下のような点を指示します。

  • 翻訳対象ドキュメントとその言語を判断を指示する
  • 翻訳すべき箇所と翻訳すべきでない箇所を明示する (コードブロック、リンク、固有名詞は翻訳しないなど)
  • ドキュメント後の翻訳スタイルや一貫性を具体的に指示する

GitHub Copilotを用いたドキュメント翻訳の自動化

GitHub IssueにCopilotエージェントを割り当てると、Copilot coding agentが行った翻訳結果をPRでレビューしやすくなります。 ということで、私が実際に使っている多言語READMEの翻訳フローを紹介します。

  • GitHub Actionsでドキュメント翻訳用のIssueを自動作成する
  • Issueへのラベル付与をトリガーに、GitHub ActionsでCopilotエージェントをアサインする
  • CopilotエージェントがIssue内容に基づき、ドキュメントを翻訳する
  • レビュー、修正、マージする

一連の作業をGitHub Actionsに組み込み、Issue作成からCopilotエージェントのアサインまで自動化しています。Copilotインストラクションで翻訳ガードレールを組みつつ、Issueで細かい指示をだすことで、Issueの文章を変えれば翻訳タスクの内容を調整できる柔軟性があります。次の流れで、これを構築してみましょう。

  1. Copilotライセンス付きユーザーでPATを生成
  2. インストラクションを用意する
  3. GitHub Actionsワークフローを用意する

Copilotライセンス付きユーザーでPATを生成

GitHub Actionsで、IssueにCopilotエージェントをアサインするにはghが便利です。この時、Copilotライセンス付きユーザーのPATを使う必要1があります。今回はIssueを作らせて作業するので、Issueスコープで書き込み、Contentsスコープは読み取り専用としたPATを生成します。

  • Contents: read
  • Issue: read & write

生成したPATは、GitHubリポジトリのシークレットに登録します。ここではGITHUB_TOKEN_COPILOTという名前で登録します。

インストラクションを用意する

ドキュメント翻訳の基準を明確にするため、GitHub Copilotエージェントに与えるインストラクションを用意します。どのようなタスクを与えるかはIssueボディで調整できるので、インストラクションは翻訳ガードレールという立ち位置です。このためインストラクションでは、「翻訳対象ドキュメントの言語判断を指示する」「ドキュメント後の翻訳スタイルや一貫性を具体的に指示する」を誤解なくLLMに伝えることを重視すると良いでしょう。

私は以下のようなインストラクションを用意しています。

## Documentation Review Guidelines

When reviewing changes to documentation, focus on the following points:

- Spelling
- Clarity and Conciseness
  - Ensure the content is written in a clear and concise manner.
- Headings
  - Check that appropriate headings are used.
- Documentation Style
  - The writing style must be consistent with existing documentation.
  - Documentation is not a personal blog post. The subject is the project itself, and the project provides content to the reader.
- Language Consistency
  - Each language-specific document (e.g., README-ja.md for Japanese) must be written entirely in that language.
  - Only technical elements should remain in English: URLs, code snippets, command examples, PR/issue numbers, and technical tool names.
  - All descriptive text, instructions, and explanations must be translated to the document's target language.

If any part deviates from these points, propose a correction.

GitHub Actionsワークフローを用意する

GitHub Actionsワークフローを用意します。以下は私が実際に使っているワークフローの例です。

name: document translation
on:
  workflow_dispatch:
  issues:
    types: [labeled]

jobs:
  # ドキュメント翻訳イシューの作成ジョブ。ここでインストラクションする。
  issue:
    if: ${{ github.event_name == 'workflow_dispatch' }}
    permissions:
      contents: read
    runs-on: ubuntu-24.04
    timeout-minutes: 5
    steps:
      - name: Create Issue body
        run: |
          cat << 'EOF' > body.txt
          Apply the pull request fixes that have been applied to recently updated documents to each language's documentation.

          - README.md: English (en-us)
          - README-ja.md: Japanese (ja-jp)

          ---

          Issue created by GitHub Actions: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
          EOF
      - name: Create issue
        run: |
          gh issue create \
            --title "[Automate] Apply the fixes from pull requests to the doc for each language." \
            --body-file body.txt \
            --label "documentation"
        env:
          GH_REPO: ${{ github.repository }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN_COPILOT }} # require trigger workflow

  # @copilotのアサインジョブを分ける
  # イシューの作成とアサインを同一ジョブ内で行うと、Copilotエージェントタスクがトリガーされない。これは想定外の挙動。
  # 回避策として、GitHub Actionsのジョブをイシュー作成とアサインで分割する。
  assign:
    if: ${{ github.event_name == 'issues' && contains(github.event.issue.labels.*.name, 'documentation') && startsWith(github.event.issue.title, '[Automate]') }}
    permissions:
      contents: read
    runs-on: ubuntu-24.04
    timeout-minutes: 5
    steps:
      - name: Assign copilot agent
        run: gh issue edit ${{ github.event.issue.number }} --add-assignee @copilot
        env:
          GH_REPO: ${{ github.repository }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN_COPILOT }} # require user PAT with copilot license

本ワークフローは、Issueを2ジョブに分けて処理しています。1つはIssueの作成、もう1つはCopilotエージェントのアサインです。Issueの作成とアサインを同一ジョブ内で行うと、Copilotエージェントタスクがトリガーされないため回避策としてジョブを分割しています。ワークフローの流れは次の通りです。

  • issueジョブ: workflow_dispatch2をトリガーに実行され、ドキュメント翻訳用のIssueを作成 + ラベルを付与
  • assignジョブ: Issueへのラベル付与をトリガーに実行され、IssueにCopilotエージェントをアサイン

Copilotエージェントがアサインされると、Copilot Agent Taskが翻訳タスクを開始、PRを作成します。Issueに付与するラベルはdocumentationにしていますが、適宜変更してください。 issueジョブに埋め込んだIssueボディで、どのようなタスクにするか指示を調整できます。次の内容なら、README.md(英語)とREADME-ja.md(日本語)について翻訳されます。

Apply the pull request fixes that have been applied to recently updated documents to each language's documentation.

- README.md: English (en-us)
- README-ja.md: Japanese (ja-jp)

---

Issue created by GitHub Actions: https://github.com/guitarrapc/scoop-bucket/actions/runs/20479070004

インストラクションによるガードレール + Issueボディでのタスク調整で、柔軟にドキュメント翻訳をCopilotエージェントに補助させるイメージです。

どうでもいいんですが、issueへのCopilotアサインって@copilotで出来るんですね。

ドキュメント翻訳ワークフローを実行する

実際に実行してみましょう。 今回は、guitarrapc/scoop-bucketで試します。参照用にIssueとPRも載せておきます。

開始条件

README.md(英語)に変更をいれ、README-ja.md(日本語)はその変更に追随していない、かつ未翻訳部分がある状態です。 このため、本対応でREADME-ja.mdが更新されることを期待します。

実行する

起点となる、document translationワークフローを手動実行(workflow_dispatch)します。

workflow_dispatchで実行

issueジョブが実行

Issueが作成され、documentationラベルが付与されます。

Issue作成、documentationラベルを付与

documentationラベルが付与されると、再びdocument translationワークフローがトリガーされ、今度はassignジョブでIssueにCopilotエージェントがアサインされます。

issueにCopilotがアサインされる

CopilotエージェントがIssue内容に基づき、ドキュメントを翻訳しPRを作成します。

CopilotがPRを作成

CopilotエージェントがPRを作成しました。PR内容を確認しましょう。

翻訳対応PR

ファイル差分は次の通りです。翻訳内容をレビュー、修正、マージすれば完了です。

PRのファイル差分

TIPS: インストラクションでLanguage Consistencyを指示する効果

先に示したインストラクションの中で、特にLanguage Consistencyの指示がおすすめです。この指示を与えることで、ドキュメント全体の言語を統一し、技術要素のみ英語のままにできます。

- Language Consistency
  - Each language-specific document (e.g., README-ja.md for Japanese) must be written entirely in that language.
  - Only technical elements should remain in English: URLs, code snippets, command examples, PR/issue numbers, and technical tool names.
  - All descriptive text, instructions, and explanations must be translated to the document's target language.

LLMによる翻訳は、意外と文書が漏れます。 例えば、日本語文書の中に、These elements should .....のような英語文書が混じっていても、翻訳されずに残ってしまうことがよくあります。また、ある言語にPRで加えられた変更を他言語に反映させる場合、PRで変更されなかった箇所に異なる言語が混じっていても翻訳されず残ります。このインストラクションはそれらを防ぐ目的です。

インストラクションの効果を見てみましょう。 このインストラクションがない状態で、先ほどのワークフローを実行した結果です。差分を見ると、PRや直近コミットで変更を加えていない箇所が翻訳されずに残っています。

インストラクションを入れない場合

一度PR/Issueをクローズしてから、同インストラクションを入れて、先ほどのワークフローを実行した結果です。差分を見ると、先ほど取り残されていた英語部分が日本語翻訳されていることが分かります。このインストラクションがドキュメント全体の言語統一に効果的であることが分かります。

インストラクションを入れた場合

まとめ

READMEやドキュメントの多言語対応をGitHub Copilotエージェントに補助させる方法を紹介しました。 OSSは趣味時間で作成、更新することがほとんどです。そうでなくても時間は有限です。GitHub Copilotエージェントにドキュメント翻訳を補助させることで、ドキュメントの多言語が現実的に提供できるようになったと感じます。

ドキュメントだけを効率的に多言語化するためにLLMを使うのは、今後のドキュメント管理の1つの方向性だと考えています。 GitHubでやりやすいGitHub Copilotエージェントを用いていますが、Copilot以外のLLMでも同様のアプローチは可能です。LLMを活用したドキュメント多言語化の考え方は応用できるでしょう。

参考

GitHub


  1. 以前、GITHUB_TOKENやGitHub Appインストレーショントークンを用いてPATを避ける方法を書きましたが、このトークンではIssueにCopilotエージェントをアサインできないためPAT必須な例です。
  2. 任意タイミングの翻訳のためWorkflow Dispatchを使っていますが、特定ファイルへのpushトリガーなどに変更もよいでしょう。