Slide 1

Slide 1 text

Unity,PHP+Jenkins+GAS 多言語対応を意識させない 開発を目指したシステム構築 株式会社ポケラボ 基盤エンジニア 篠原 功

Slide 2

Slide 2 text

自己紹介 ● 篠原 功 (Isao Shinohara) ○ 2013年株式会社ポケラボに入社。 ○ 「SINoALICE -シノアリス-」「アサルトリリィ Last Bullet」などを経て 現在は基盤チームに所属。 ○ ローカライズやリソース管理のシステム構築を中心に 「開発・運用フローも踏まえた最適化」を目指して絶賛開発中。 2

Slide 3

Slide 3 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 3

Slide 4

Slide 4 text

● 多言語対応のために開発メンバーにお願いしている具体的な実装ルール ● ゲーム内で使っている日本語テキストの抽出や翻訳後のフロー 話すこと 4

Slide 5

Slide 5 text

● 言語や地域の違いで発生する問題 ● リリース済みアプリを多言語対応するために役立つ情報 ● 画像に埋め込まれた日本語テキストやフォントなど 話さないこと(話せないこと) 5

Slide 6

Slide 6 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 6

Slide 7

Slide 7 text

● 海外対応状況 ○ 「SINoALICE -シノアリス-」「戦姫絶唱シンフォギア XD UNLIMITED」 などいくつかのアプリですでに海外リリース実績あり ● 開発体制 ○ 日本版リリース後、海外版をリリース ○ 開発チームは日本版、開発版で別チーム これまでの海外対応状況 7

Slide 8

Slide 8 text

課題点 ● 日本語テキストの抽出作業負担 ● 連番によるID管理と翻訳間違い ● git管理で発生していたコンフリクト問題 ● 翻訳チェックと巻き戻し作業の負荷 8

Slide 9

Slide 9 text

日本語テキストの抽出作業負担 ● 内容 ○ 実装が完了したタイミングでプランナー、エンジニアそれぞれが 翻訳対象となるテキストをまとめていた ● 課題 ○ 日本語テキスト実装箇所は多岐に渡るので抽出が大変 ○ 手動で行うため抜け漏れが発生する可能性がある 9

Slide 10

Slide 10 text

連番によるID管理と翻訳間違い ● 内容 ○ 翻訳対象の日本語テキストに対し連番 IDを付与 ■ ID:1 おはよう ■ ID:2 こんにちは ■ ID:3 こんばんは ○ 開発メンバーは日本語テキストと対応した IDを関連付ける ● 課題 ○ 日本語テキスト実装箇所は多岐に渡るので IDの関連付け作業が大変 ○ 番号を間違えると誤った翻訳が行われる可能性がある ○ 一度IDを割り振ったら変更することは至難 10

Slide 11

Slide 11 text

git管理で発生していたコンフリクト問題 ● 内容 ○ 翻訳データはcsv形式で保存しGitHub上で管理 ● 課題 ○ 同じcsvファイルを編集することがありコンフリクトが発生していた ○ 作業者にはgitのスキルが求められる 11

Slide 12

Slide 12 text

● 内容 ○ QAチームは翻訳されたテキストを実機上ですべて確認 ● 課題 ○ 翻訳漏れが発生した場合の巻き戻し作業が多い ○ 翻訳漏れは五月雨に発覚することもある 翻訳チェックと巻き戻し作業の負担 12

Slide 13

Slide 13 text

課題を踏まえた対応方針 13

Slide 14

Slide 14 text

課題点 ● 日本語テキストの抽出作業負担 ● 連番によるID管理と翻訳間違い ● git管理で発生していたコンフリクト問題 ● 翻訳チェックと巻き戻し作業の負担 14

Slide 15

Slide 15 text

翻訳が必要な日本語テキストを自動抽出 ● 対応 ○ ゲーム内で利用しているテキストすべてを自動で抽出できるようにする ● 期待 ○ 手動で日本語テキストを集めていた労力がなくなる ○ 翻訳漏れが発生した際の手戻りもなくなる ○ QAチームの確認範囲を限定 15

Slide 16

Slide 16 text

課題点 ● 日本語テキストの抽出作業負担 ● 連番によるID管理と翻訳間違い ● git管理で発生していたコンフリクト問題 ● 翻訳チェックと巻き戻し作業の負担 16

Slide 17

Slide 17 text

IDを連番から日本語ハッシュ値に変更 ● 内容 ○ IDを日本語を元に生成したハッシュ値に変更 ■ 例:) こんにちは ● ID: 1 -> ID: 20427A708C3F6… ● 期待 ○ IDの採番と関連付けのための実装が不要になる ○ IDの割り当て間違いによる誤った翻訳が防げる 17

Slide 18

Slide 18 text

課題点 ● 日本語テキストの抽出作業負担 ● 連番によるID管理と翻訳間違い ● git管理で発生していたコンフリクト問題 ● 翻訳チェックと巻き戻し作業の負担 18

Slide 19

Slide 19 text

GoogleSpreadSheetを利用 ● 内容 ○ 翻訳作業はGoogleSpreadSheetで行う ● 期待 ○ gitスキルが不要になる ○ Web公開することで外部サービスとの連携が可能に 19

Slide 20

Slide 20 text

対応方針 ● 翻訳が必要な日本語テキストを自動抽出 ● IDを連番から日本語ハッシュ値に変更 ● GoogleSpreadSheetを利用 20

Slide 21

Slide 21 text

所感・実装コンセプト ● 所感 ○ 日本語の開発完了後から翻訳対応までの作業量が多い ○ どのような実装になっているかでその作業量は大幅に変わる ● 実装コンセプト ○ 日本向けに開発しているメンバーがいつも通り作業をしているだけで 多言語対応のための実装も完了している 21

Slide 22

Slide 22 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 22

Slide 23

Slide 23 text

翻訳対象 ● クライアント (Unity) ○ シーン・プレハブ ■ TextMeshProなどのコンポーネント ■ SerializeField ○ ソースコード (C#) ○ ScriptableObject ● サーバー (PHP, Spanner, Smarty) ○ マスタデータ ○ yaml ○ ユーザーデータ ○ WebView 23

Slide 24

Slide 24 text

シーン・プレハブ ● 対象箇所 ○ シーン、プレハブでアタッチしている TextMeshProなどのテキストコンポーネント ● 実装ルール ○ 翻訳用のコンポーネントをアタッチ ■ 翻訳不要でもアタッチ ● 抽出方法 ○ AssetDatabase.FindAssets("t:Scene t:Prefab"); ○ GameObjectにアタッチされているテキスト コンポーネントから翻訳対象テキストを取得 ● 表示処理 ○ シーン、プレハブをアクティブにするタイミングで 各言語の翻訳テキストに置き換え 24

Slide 25

Slide 25 text

SerializeField ● 対象箇所 ○ public stringや[SerializeField] private stringで 作成した変数にインスペクターから入力している テキスト ● 実装ルール ○ 使用禁止 ● 理由 ○ 翻訳対象の日本語テキストを抽出するのが難しい ○ 翻訳処理を通しているかの保証ができない 25

Slide 26

Slide 26 text

ScriptableObject ● 対象箇所 ○ ScriptableObject内に含まれるテキストデータ ○ ADVパートのシナリオ管理に利用 ● 実装ルール ○ なし ● 抽出方法 ○ ScriptableObjectファイルをロード後、 翻訳対象の日本語テキストを取得 ● 表示処理 ○ 言語毎に翻訳された JSONファイルを用意して管理 ■ story.asset -> story_en-Latn.json, story_ko-Kore.json ■ JsonUtility.ToJson(); ○ 空のScriptableObjectにJSONのデータを反映 ■ JsonUtility.FromJsonOverwrite(); 26

Slide 27

Slide 27 text

ソースコード (C#) ● 対象箇所 ○ ソースコードに直に記述している日本語テキスト ● 実装ルール ○ 決められたクラス内に定義 ○ プロパティ形式にして翻訳メソッドを通す ○ 決められたクラス以外で定義することは禁止 ● 抽出方法 ○ 決められたクラス内に存在する string or string[] を返すプロパティから翻訳対象のテキストを取得 ● 表示処理 ○ プロパティ利用時に各言語の翻訳テキストを返却 27

Slide 28

Slide 28 text

マスタデータ ● 対象箇所 ○ Spannerで管理されている全ユーザー共通データ ● 実装ルール ○ なし ● 抽出方法 ○ テーブルのスキーマ情報から STRING(XX)で 定義されているカラムの値を取得 ● 表示処理 ○ 言語毎に翻訳済みのマスタテーブルを用意し、 利用時に対象テーブルを切り替える ■ ItemMst -> ItemMst_en-Latn, ItemMst_ko-Kore 28

Slide 29

Slide 29 text

yaml ● 対象箇所 ○ yamlファイル内に記述しているテキスト ● 実装ルール ○ なし ● 抽出方法 ○ 正規表現で「ひらがな」「カタカナ」「漢字」を 含んだテキストを抽出 ○ 英語で記述されたテキストも翻訳対象だった ケースにどう対応するかは課題 ■ 例:) HP, MP ● 表示処理 ○ yamlのパース処理後に対象日本語テキストを 各言語の翻訳テキストに置き換え ○ 置き換えたyamlは言語毎にキャッシュ 29

Slide 30

Slide 30 text

ユーザーデータ ● 対象箇所 ○ データベースにユーザー個別で記録している 日本語テキスト ● 実装ルール ○ 日本語テキストで記録 ● 抽出方法 ○ マスタデータやyamlに記載されている 日本語テキストの場合は必要なし ○ 上記以外の日本語テキストを利用するケースに どう対応するかは課題 ● 表示処理 ○ テーブルからデータ取得時に日本語テキストを 各言語の翻訳テキストに置き換える 30

Slide 31

Slide 31 text

WebView ● 対象箇所 ○ テンプレートファイル内に直接記述されている 日本語テキスト ○ テンプレートエンジンを利用してプログラムから 埋め込まれている文字列 ■ マスタデータやyamlに記載されている 日本語テキストの場合は必要なし ● 実装ルール ○ なし ● 抽出方法 ○ テンプレートファイル内の要素を取得 (予定) ● 表示処理 ○ テンプレート内に直接記述されている 日本語テキストはロード時に各言語の翻訳テキスト へと置き換える(予定) 31

Slide 32

Slide 32 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 32

Slide 33

Slide 33 text

翻訳対象となる日本語テキストの抽出フロー 33

Slide 34

Slide 34 text

翻訳対象となる日本語テキストの抽出フロー 34 ①

Slide 35

Slide 35 text

翻訳対象となる日本語テキストの抽出フロー 35 ② ②

Slide 36

Slide 36 text

翻訳対象となる日本語テキストの抽出フロー 36 ③ ③

Slide 37

Slide 37 text

翻訳対象となる日本語テキストの抽出フロー 37 ④ ④

Slide 38

Slide 38 text

Google Spread Sheet 38

Slide 39

Slide 39 text

Google Spread Sheet 39

Slide 40

Slide 40 text

Google Spread Sheet 40

Slide 41

Slide 41 text

Google Spread Sheet 41

Slide 42

Slide 42 text

Google Spread Sheet 42

Slide 43

Slide 43 text

Google Spread Sheet 43

Slide 44

Slide 44 text

翻訳作業後のフロー 44

Slide 45

Slide 45 text

翻訳作業後のフロー 45 ①

Slide 46

Slide 46 text

翻訳作業後のフロー 46 ②

Slide 47

Slide 47 text

翻訳作業後のフロー 47 ③

Slide 48

Slide 48 text

翻訳作業後のフロー 48 ④

Slide 49

Slide 49 text

翻訳作業後のフロー 49 ⑤

Slide 50

Slide 50 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 50

Slide 51

Slide 51 text

UI テキストエリアのサイズ問題 ● 内容 ○ 言語によってはテキストがエリア内に収まらない問題 ● 原因 ○ 想定されるケース、解決方法が多岐にわたりシステム化が難しい ● 方針 ○ 現時点で良い案がないことを周知 ○ ノウハウが溜まりシステム化できるまでは 1箇所1箇所対応 51

Slide 52

Slide 52 text

「やってはいけないこと」の厳守 ● 内容 ○ 開発メンバーが「やってはいけない」を「やってしまってはいないか?」 ● 原因 ○ 「やってはいけないこと」の対象範囲が広い ○ チェックツールの作成も難しい ● 方針 ○ 現場レベルで各個人に厳守していただくことを口頭でお願い ○ 問題ひとつひとうに対して泥臭く対応 52

Slide 53

Slide 53 text

● これまでの海外対応状況と課題点・改修方針 ● システム化のための実装ルール ● 翻訳依頼から反映までの作業フロー ● 積み残しになっている課題 ● まとめ アジェンダ 53

Slide 54

Slide 54 text

実装ルール ● クライアント (Unity) ○ シーンやプレハブには必ず翻訳用のコンポーネントをアタッチ ○ テキストは決められたクラスに定義 ■ プロパティ形式で翻訳処理を通す ■ 特定クラス以外以外は使用禁止 ○ SerializeFieldを使った日本語テキストの利用は禁止 ● サーバー (PHP, Spanner, Smarty) ○ 基本なし。ただし注意点あり。 ■ ユーザーデータに日本語テキストを保存する場合は日本語テキストのまま ■ yamlに定義したテキストは英語のみだと翻訳されないので注意 54

Slide 55

Slide 55 text

今後の展望 ● システムはまだ発展途上 ○ ゲームはまだリリースもされていない ○ 翻訳チームの要望もまだ組み込めていない ○ QAチームの要望もまだ組み込めていない ● 実装したい機能 ○ デバッグツール ○ Slack連携 55

Slide 56

Slide 56 text

56