Upgrade to Pro — share decks privately, control downloads, hide ads and more …

7カ国語に対応したサービスでの翻訳管理システムの改善事例

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 7カ国語に対応したサービスでの翻訳管理システムの改善事例

Avatar for punchdrunker

punchdrunker

March 02, 2023
Tweet

More Decks by punchdrunker

Other Decks in Programming

Transcript

  1. ©MIXI 自己紹介 • 七尾 貴史 / @punchdrunker • 1児の父、育児休業4ヶ月 •

    2011年7月株式会社ミクシィ(現株式会社MIXI)入社 • 2016年7月からみてねでアプリを開発しています
  2. ©MIXI 「家族アルバム みてね」の多言語対応の歴史 • 2015年4月 サービス開始、日本語のみに対応 • 2017年7月 英語に対応 •

    2019年10月 中国語&韓国語に対応 • 2020年4月 フランス語に対応 • 2020年6月 ドイツ語に対応 • 2021年7月 スペイン語に対応 3
  3. ©MIXI 用語の説明 • TMS ◦ 翻訳管理システム、 Translations Management Systemの略。 •

    元言語 ◦ 翻訳の元となる言語。みてねで は「日本語」が元言語となりま す。 • 原文 ◦ 元言語の文言。翻訳者はこの 文言から翻訳を作ります。 • TM ◦ 翻訳メモリ。Translation Memoryの 略 ◦ 翻訳履歴から作られる翻訳例文集。 同じ翻訳があればそれを使うように推 薦、自動翻訳などをしてくれます。 ◦ 翻訳の一貫性を向上するために役立 ちます。 • PR ◦ 本資料ではGitHubの pull request をPRと表記します。
  4. ©MIXI 翻訳に関わる人々 • デザイン ◦ アプリ/Web全般の画面デザイ ン作成 ◦ バナー作成 •

    開発 ◦ 表示が必要なエラーメッセージ の作成 ◦ ユーザーが選択する必要があ るダイアログなどの文言を作成 • CS ◦ 各言語でのお問い合わせに返 信 • マーケティング ◦ アプリ内で表示するユーザーへ の新機能のお知らせなどを作 成 ◦ プロモーション関連のPUSH通 知の文言を作成 • 翻訳 ◦ 各チームから依頼された原文 から担当の言語に翻訳 • QA/LQA ◦ 各言語担当者が実装された各 言語での表示を確認
  5. ©MIXI 従来フローでの課題 • 最新の翻訳がどれかわからない • 翻訳メモリを他のメンバーと共有 できない • コンテキスト情報がほしい 7

    開発者の課題 翻訳者の課題 • 依頼の手間が煩雑 • スプレッドシートからの転記ミス ◦ 英語対応当時はスプレッドシート からxmlやplistを自動生成してい た ◦ コードとスプレッドシートの同期が 取れなくて運用不能になってしまっ た • 手戻りが多い ◦ 画面に反映したら文言が長すぎ た、など
  6. ©MIXI 現在の翻訳フロー GitHubとCrowdinの連携によ り、以下のような事が可能に • FigmaやPRから翻訳 依頼を作成 • 翻訳結果から自動で PRを作成

    • 翻訳者が依頼を開く時 には、過去に翻訳済み の文言はTMから自動 翻訳/レコメンドされてい る
  7. ©MIXI 新フローで改善した点 • 最新(当日朝9時)の翻訳がいつで も参照可能 • 翻訳メモリがプロジェクト内で共有 される • Figmaから連携可能なので、翻訳

    作業画面内で表示イメージを確認 できる 9 開発者の課題を解決 翻訳者の課題を解決 • Figmaから直接原文追加可能 • GitHubとCrowdinの翻訳 データを相互に同期できるの で、手で編集することがなく なった • コンテキスト情報を見ながら翻 訳してもらえるので、実装して からの修正が減った
  8. ©MIXI なぜCrowdinを選んだか • APIやCLIが充実している(一番重要) ◦ 公式のGitHub Actionsを使って翻訳文言の取り込みPRを自動生成できる • 開発中機能に対応するブランチを作成出来る •

    翻訳元言語を日本語に出来る ◦ 日本語は複数形がないので、他のシステムでは翻訳も複数形を登録できなかった。 ◦ Crowdinは元の言語が何であれ複数形の表現を定義することが可能だった。 • NBSP欠落などに対応が出来る(アドオンで特殊文字を入力) • スペルチェッカーを翻訳文言に対して実行が出来る • ある程度まとまった単位で翻訳依頼を管理出来る • 翻訳文のLQAフローが組める ◦ 校正者のレビューと別でLQAのレビューを設定可能 • サポートのレスポンスがかなり早い
  9. ©MIXI Crowdinを導入するための下準備 • 文言はリソースファイルに集約する ◦ プログラム上で定義/動的生成しない ◦ 英語対応の時点でかなり減ってはいたが、一文の文言は不規則なところに あった •

    文言は使いまわさない ◦ 同じkeyのものを複数箇所で使ってしまうと、変更時の動作確認が大変 • 文字列結合は使わない ◦ 管理が煩雑になってしまうので、プレースホルダーを適切に利用する ◦ プレースホルダーの位置指定はちゃんと書く • 日付や時間表記はシステム標準のものを使う(無理にカスタマイズしな い) • 特定言語でしか使わないなど翻訳が不要な文言は、除外するためファ イルによけておく
  10. ©MIXI crowdin.yml • 接続に必要なIDなどの接続情 報 • 対応言語の定義 • 言語ごとの修飾子をマッピング (fr:

    values-fr など) • ↑を変数として用いて翻訳対象 となるリソースファイルのファイ ルパスを定義 (/app/src/main/res/%andr oid_code%/%original_file_n ame% ) • リソースファイルの種別: iOS, android, json, yaml… preserve_hierarchy: true export_languages: - de - … project_id_env: "CROWDIN_PROJECT_ID" api_token_env: "CROWDIN_PERSONAL_TOKEN" base_url: "https://xxx.crowdin.com" languages_mapping: &languages_mapping android_code: de: values-de en: values … files: - source: /app/src/main/res/values-ja/strings.xml translation: /app/src/main/res/%android_code%/%original_file_name % labels: - android type: android languages_mapping: *languages_mapping … Androidでの例
  11. ©MIXI Crowdinの標準のGitHub連携で困ったところ • 1ファイル(1言語)に対して1コミットのgitログが残る • 同期が最短で1時間ごとにしかできない • ブランチ連携のルールがある ◦ 条件にマッチするブランチ名にしないといけない(4文字以上)

    • mainブランチと作業用ブランチで同期する設定などを分けられなかっ た ◦ 自動連携に任せると古いmainから分岐したPR全てに翻訳変更のPRが作成 されてしまう ◦ 原文/翻訳を それぞれupload / downloadするかを状況によって選択したい • 連携を管理/設定変更できるのは管理者のみ
  12. ©MIXI crowdin/github-action • GitHubの作業用ブランチ名に 対応したCrowdin上のブラン チを作成して新しい原文を追加 • 翻訳が完了していれば、 Crowdinの翻訳結果をコード に反映するためのPRを作成

    - name: Sync with Crowdin (branches) if: ${{ github.ref_name != 'main' }} uses: crowdin/[email protected] with: upload_sources: false upload_translations: false download_translations: true crowdin_branch_name: '[${{ env.REPOSITORY_NAME_WITHOUT_SLASHES }}] ${{ env.BRANCH_NAME_WITHOUT_SLASHES }}' localization_branch_name: 'l10n_${{ github.ref_name }}' create_pull_request: true pull_request_title: 'Crowdinから翻訳の取り込み' pull_request_base_branch_name: '${{ github.ref_name }}' pull_request_labels: 'l10n' pull_request_assignees: '${{ github.actor }}' … Androidでの例
  13. ©MIXI 文言を追加する手順 • FigmaのPluginを使ってCrowdinで翻訳依頼を作成 • 翻訳者が翻訳する • 依頼した原文(日本語)をコード上に追加した作業用ブランチをpushしてPRを作成 (機能実装のついででも良い) ◦

    stringのkeyと日本語がここで確定する • Crowdinと同期するworkflowを実行 ◦ 作業ブランチに対応するCrowdin内の翻訳用ブランチを作成し、原文が追加される ◦ TM pre-translation = Crowdinが自動でマッチング処理が実行される ▪ TMにあるものは自動翻訳してくれる(設定によりプロジェクトを跨いでメモリを共有できる) ▪ minimum match ratio 80%で運用しているので、誤訳する可能性はあるので、今後調整する かもしれない ▪ プレースホルダーも置換してくれる ◦ 抜け漏れがあれば開発者が手動で調整する必要がある ◦ TM pre-translationで翻訳が完了していれば、作業ブランチに対しての翻訳済み PRが作成 される • 作成されたPRをマージ
  14. ©MIXI workflowがやっていること GitHub上の gitリポジトリ Crowdin 2. upload_sources コードで追加/変更された原 文をCrowdinに追加 GitHub

    Actions 1.コードをチェックアウト TM pre-translation 翻訳メモリ内に対応する翻 訳が追加されると自動翻訳 される(Crowdin側で自動的 に実行される) 4-a. (mainブランチ以 外)download_translations 翻訳が完了した文言を追加す るPRを作成 4-b. (mainブランチの み)upload_sources と download_translations を両 方実行し、mainを同期する 3. pre-translationを待つために 60秒スリープ
  15. ©MIXI 文言の編集 - 日本語以外を修正したい [簡単だがちょっと危険] Crowdinのmainブランチの翻訳を修正し、workflowを実行し、作成されたPRをマー ジする。 PRへのマージが遅れるとworkflow実行時に余計なPRが作成されるため早くマージす る必要がある。そのためQAの時間は限られてしまう。 [通常]

    • GitHubに作業用ブランチを作成しpush • 作業用ブランチに対してworkflowを実行 • Crowdinの該当ブランチで管理者が変更したい文言をUnhideする • 翻訳してもらう • workflowを実行するとPRが作成される
  16. ©MIXI 文言の削除 • GitHubに作業用ブランチを作成し削除したい文言の日本語を削除し てpush • 作業用ブランチに対してworkflowを実行 • 削除した元言語と同じkeyの他言語の文言を削除したPRが作成され る

    • 人間がレビューしてマージ (GitHubだけで削除したPRを作ってマージするのも可能だが、消したい文 言がたくさんある場合はCrowdin連携にまかせた方が楽かもしれない。)