Slide 1

Slide 1 text

©MIXI 7カ国語に対応したサービスでの 翻訳管理システムの改善事例紹介 Crowdin Enterprise 導入 みてね事業部プロダクト開発グループ 七尾 貴史

Slide 2

Slide 2 text

©MIXI 自己紹介 ● 七尾 貴史 / @punchdrunker ● 1児の父、育児休業4ヶ月 ● 2011年7月株式会社ミクシィ(現株式会社MIXI)入社 ● 2016年7月からみてねでアプリを開発しています

Slide 3

Slide 3 text

©MIXI 「家族アルバム みてね」の多言語対応の歴史 ● 2015年4月 サービス開始、日本語のみに対応 ● 2017年7月 英語に対応 ● 2019年10月 中国語&韓国語に対応 ● 2020年4月 フランス語に対応 ● 2020年6月 ドイツ語に対応 ● 2021年7月 スペイン語に対応 3

Slide 4

Slide 4 text

©MIXI 用語の説明 ● TMS ○ 翻訳管理システム、 Translations Management Systemの略。 ● 元言語 ○ 翻訳の元となる言語。みてねで は「日本語」が元言語となりま す。 ● 原文 ○ 元言語の文言。翻訳者はこの 文言から翻訳を作ります。 ● TM ○ 翻訳メモリ。Translation Memoryの 略 ○ 翻訳履歴から作られる翻訳例文集。 同じ翻訳があればそれを使うように推 薦、自動翻訳などをしてくれます。 ○ 翻訳の一貫性を向上するために役立 ちます。 ● PR ○ 本資料ではGitHubの pull request をPRと表記します。

Slide 5

Slide 5 text

©MIXI 翻訳に関わる人々 ● デザイン ○ アプリ/Web全般の画面デザイ ン作成 ○ バナー作成 ● 開発 ○ 表示が必要なエラーメッセージ の作成 ○ ユーザーが選択する必要があ るダイアログなどの文言を作成 ● CS ○ 各言語でのお問い合わせに返 信 ● マーケティング ○ アプリ内で表示するユーザーへ の新機能のお知らせなどを作 成 ○ プロモーション関連のPUSH通 知の文言を作成 ● 翻訳 ○ 各チームから依頼された原文 から担当の言語に翻訳 ● QA/LQA ○ 各言語担当者が実装された各 言語での表示を確認

Slide 6

Slide 6 text

©MIXI 従来の翻訳依頼フロー 6 GitHubと連携するシステムは無く、基本的にはスプレッドシートのやり とりで翻訳を依頼/反映していた。 翻訳者は補助的にMemsourceというTMSを使っていた。

Slide 7

Slide 7 text

©MIXI 従来フローでの課題 ● 最新の翻訳がどれかわからない ● 翻訳メモリを他のメンバーと共有 できない ● コンテキスト情報がほしい 7 開発者の課題 翻訳者の課題 ● 依頼の手間が煩雑 ● スプレッドシートからの転記ミス ○ 英語対応当時はスプレッドシート からxmlやplistを自動生成してい た ○ コードとスプレッドシートの同期が 取れなくて運用不能になってしまっ た ● 手戻りが多い ○ 画面に反映したら文言が長すぎ た、など

Slide 8

Slide 8 text

©MIXI 現在の翻訳フロー GitHubとCrowdinの連携によ り、以下のような事が可能に ● FigmaやPRから翻訳 依頼を作成 ● 翻訳結果から自動で PRを作成 ● 翻訳者が依頼を開く時 には、過去に翻訳済み の文言はTMから自動 翻訳/レコメンドされてい る

Slide 9

Slide 9 text

©MIXI 新フローで改善した点 ● 最新(当日朝9時)の翻訳がいつで も参照可能 ● 翻訳メモリがプロジェクト内で共有 される ● Figmaから連携可能なので、翻訳 作業画面内で表示イメージを確認 できる 9 開発者の課題を解決 翻訳者の課題を解決 ● Figmaから直接原文追加可能 ● GitHubとCrowdinの翻訳 データを相互に同期できるの で、手で編集することがなく なった ● コンテキスト情報を見ながら翻 訳してもらえるので、実装して からの修正が減った

Slide 10

Slide 10 text

©MIXI Figmaとの連携 Crowdin for Figma FigmaからCrowdinに流し込まれた原文 ※非表示の要素なども追加されるので、エ ディタ上で翻訳対象のチェックを外す必要 がある

Slide 11

Slide 11 text

©MIXI 翻訳管理システムの選定 社内ヒアリングを行い課題整理しながら、色々なサービスを比較検討 ● Crowdin ● POEditor ● Phrase Strings ● Lokalise ● Transifex ● Smartling

Slide 12

Slide 12 text

©MIXI なぜCrowdinを選んだか ● APIやCLIが充実している(一番重要) ○ 公式のGitHub Actionsを使って翻訳文言の取り込みPRを自動生成できる ● 開発中機能に対応するブランチを作成出来る ● 翻訳元言語を日本語に出来る ○ 日本語は複数形がないので、他のシステムでは翻訳も複数形を登録できなかった。 ○ Crowdinは元の言語が何であれ複数形の表現を定義することが可能だった。 ● NBSP欠落などに対応が出来る(アドオンで特殊文字を入力) ● スペルチェッカーを翻訳文言に対して実行が出来る ● ある程度まとまった単位で翻訳依頼を管理出来る ● 翻訳文のLQAフローが組める ○ 校正者のレビューと別でLQAのレビューを設定可能 ● サポートのレスポンスがかなり早い

Slide 13

Slide 13 text

©MIXI 選定時のCrowdinのマイナスポイント ● 重複文言の一本化が出来ない ( Android/iOS重複・ デザインツール からの依頼など) ● 翻訳文がfixされるまで翻訳者以外が変更出来ない ● 管理者・翻訳者UI・ドキュメントが日本語対応してない ○ 導入時に各ロールの方々向けにマニュアルを作成

Slide 14

Slide 14 text

©MIXI セットアップ

Slide 15

Slide 15 text

©MIXI Crowdinを導入するための下準備 ● 文言はリソースファイルに集約する ○ プログラム上で定義/動的生成しない ○ 英語対応の時点でかなり減ってはいたが、一文の文言は不規則なところに あった ● 文言は使いまわさない ○ 同じkeyのものを複数箇所で使ってしまうと、変更時の動作確認が大変 ● 文字列結合は使わない ○ 管理が煩雑になってしまうので、プレースホルダーを適切に利用する ○ プレースホルダーの位置指定はちゃんと書く ● 日付や時間表記はシステム標準のものを使う(無理にカスタマイズしな い) ● 特定言語でしか使わないなど翻訳が不要な文言は、除外するためファ イルによけておく

Slide 16

Slide 16 text

©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での例

Slide 17

Slide 17 text

©MIXI CrowdinとGitHubの連携方法 GitHubとの自動連携機能が標準で用意されています。 しかし実際に利用してみたところ、みてねの開発フローと相性が良くなかっ たので、GitHub Actions のworkflow(以下workflowとします)で必要な 同期処理を実行することにしました。 workflowを実行することでCrowdinへの原文追加やCrowdinでの翻訳 結果を反映したPRを作成しています。 workflowの実行は同期が必要な時にブランチごとに都度手動で行うの と、毎朝1回mainブランチに対しての同期処理をスケジュール実行してい ます。

Slide 18

Slide 18 text

©MIXI Crowdinの標準のGitHub連携で困ったところ ● 1ファイル(1言語)に対して1コミットのgitログが残る ● 同期が最短で1時間ごとにしかできない ● ブランチ連携のルールがある ○ 条件にマッチするブランチ名にしないといけない(4文字以上) ● mainブランチと作業用ブランチで同期する設定などを分けられなかっ た ○ 自動連携に任せると古いmainから分岐したPR全てに翻訳変更のPRが作成 されてしまう ○ 原文/翻訳を それぞれupload / downloadするかを状況によって選択したい ● 連携を管理/設定変更できるのは管理者のみ

Slide 19

Slide 19 text

©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での例

Slide 20

Slide 20 text

©MIXI Crowdinでのブランチ

Slide 21

Slide 21 text

©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をマージ

Slide 22

Slide 22 text

©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秒スリープ

Slide 23

Slide 23 text

©MIXI Crowdinのworkflow

Slide 24

Slide 24 text

©MIXI 文言の編集 - 全言語を編集したい ● GitHubに作業用ブランチを作成し日本語を修正してpush ● 作業用ブランチに対してworkflowを実行 ● Crowdinの該当ブランチに該当の文言が翻訳対象として表示される ので翻訳してもらう

Slide 25

Slide 25 text

©MIXI 文言の編集 - 日本語以外を修正したい [簡単だがちょっと危険] Crowdinのmainブランチの翻訳を修正し、workflowを実行し、作成されたPRをマー ジする。 PRへのマージが遅れるとworkflow実行時に余計なPRが作成されるため早くマージす る必要がある。そのためQAの時間は限られてしまう。 [通常] ● GitHubに作業用ブランチを作成しpush ● 作業用ブランチに対してworkflowを実行 ● Crowdinの該当ブランチで管理者が変更したい文言をUnhideする ● 翻訳してもらう ● workflowを実行するとPRが作成される

Slide 26

Slide 26 text

©MIXI Unhide? Crowdinでは翻訳対象の単語数で課金されるので、予算があまり無いと 全てのstringを常に翻訳対象の状態にできない。(ブランチ x 単語数で課 金されてしまう) main以外は変更したい文言のみ翻訳対象として扱う事で料金を節約でき る。 元言語(日本語)に変更が無いと他の言語は翻訳対象として表示されない ので、元言語の変更が無い場合は管理者権限のユーザーで個別に Unhideする必要がある。

Slide 27

Slide 27 text

©MIXI 文言の削除 ● GitHubに作業用ブランチを作成し削除したい文言の日本語を削除し てpush ● 作業用ブランチに対してworkflowを実行 ● 削除した元言語と同じkeyの他言語の文言を削除したPRが作成され る ● 人間がレビューしてマージ (GitHubだけで削除したPRを作ってマージするのも可能だが、消したい文 言がたくさんある場合はCrowdin連携にまかせた方が楽かもしれない。)

Slide 28

Slide 28 text

©MIXI 導入後の課題と対応

Slide 29

Slide 29 text

©MIXI 画像やpush通知など、コードベース内に無い文言 Crowdinのスコープ外なので、個別に依頼して対応するしかない

Slide 30

Slide 30 text

©MIXI 連携してみてからわかる問題が結構ある ● 標準のGitHub連携が期待していたものと違った ○ workflowによる同期に変更 ● Crowdinのブランチ名のルールやmatcherの条件の制約 ○ ブランチ名にスラッシュは使えない ○ 特定の命名のブランチに任意の処理を行えるが、その名前のルールは4文 字以上

Slide 31

Slide 31 text

©MIXI TM pre-stanslationに時間がかかる TMのマッチング処理に時間がかかり、PRを作るworkflowを実行した時 に新しい翻訳が一部抜けたPRを作ってしまうことがある →60秒sleepしてからPRを作成するように変更 →60秒でも足りない事があるので、完了後に任意の処理を実行する方法 がないかなどを調査したい

Slide 32

Slide 32 text

©MIXI FIN