見出し画像

Now in REALITY Tech #75 多言語の複数形対応のプロジェクト紹介

Hey guys! こんにちは!タイ出身のiOSエンジニア、時々ローカライズ大使と名乗る @chuymaster です!
REALITYは世界中63地域にサービスを展開していて、アプリでは12言語の表示に対応しています。日本以外のユーザー数が約8割で、ローカライゼーションの重要性が非常に高いサービスです。

REALITYのユーザー分布 https://speakerdeck.com/realityinc/reality-introduction より

今回はローカライゼーションの取り組みの一環として、多言語の複数形対応(Pluralization)プロジェクトを企画から担当しましたので、この記事で説明していきたいと思います。


背景

12言語対応に当たって、REALITYではLokaliseというLMP(Localization Management Platform)を導入しました。クライアント・サーバーを含め、アプリケーション上の言語リソースを一箇所で管理できるようになっています。Lokalise導入の詳しい経緯や翻訳のワークフローについては、下記記事からご覧ください。

Lokalise導入によって12言語の翻訳の適用は簡単にできるようにはなりましたが、翻訳の質という面ではいくつか課題があります。そのうち、名詞の「複数形」に対応できていなかったので、例えば英語では下記のような翻訳がなされています。

日本語:ガチャをn回まわす
英語:Pull Gacha n time(s)

time(s) はネイティブスピーカーからすると不自然な文章で、間違った文法の翻訳といえます。この現象が、英語、フランス語、ドイツ語、ポルトガル語(ブラジル)、ロシア語、スペイン語の6か国語で長年起こっていました。

幸い、Lokaliseの言語リソース管理の標準機能として、Plurals機能があるので、アプリ側が複数形フォーマットの言語リソースを読み込むことさえできれば直すことができます。ということで、正しい文法で、過不足なく翻訳を適用できるように、複数形対応プロジェクトを発足しました。

文法が正しいと気持ちよくアプリが使える!

複数形のルールの奥深さ

ところで、複数形(Plural Form)とはどういう意味でしょうか?多くの方は、英語の名詞に「s」をつけることを思い浮かぶと思います。しかし、世の中の言語には実に様々な複数形があります。このルールはUnicodeが定義したLanguage Plural Rulesから確認できます。ここでは日本語・英語・ロシア語のルールを解説します。

日本語の複数形ルール

日本語のような、名詞の複数形がない言語の場合、ルールは存在せず、カテゴリが「other」のみであり、単位を表す名詞が数に関わらず同じです。「日」は「1日」「10日」「100日」だろうと同じですね。

英語の複数形ルール

英語の場合、複数形のカテゴリが「one」「other」になります。数が1の場合は「one」、それ以外は「other」になります。「day」だと、1 day、2 daysのように、2種類まで変化しますね。

ロシア語の複数形ルール

ロシア語の場合、複数形のカテゴリが「one」「few」「many」「other」になります。ロシア語の文法では、名詞の形が数によって最大4種類まで変化します。結構難しいですね。

このように、複数形のルールは言語によって違っています。数が1だったらa、それ以外だったらbといった単純なプログラムで分類することはできません。

実装の紹介

複数形のルールについて理解したところで、実装について説明します。現時点リリース済のiOS, Android, Unityの実装方法について紹介します。

言語リソースの出力フォーマット

Lokaliseは様々なファイルフォーマットへの出力に対応しています。REALITYが使うフォーマットに複数形の言語リソースキーを出力すると、それぞれこのようになります。

iOS

stringsdict で言語リソースが出力されます。

<dict>
    <key>resource_key</key>
    <dict>
      <key>NSStringLocalizedFormatKey</key>
      <string>%#@format@</string>
      <key>format</key>
      <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>li</string>
        <key>one</key>
        <string>%1$li item</string>
        <key>other</key>
        <string>%1$li itemss</string>
      </dict>
    </dict>
  </dict>

このフォーマットはそのままLocalizedStringのフォーマットとして利用できます。特に実装なしで、数字を代入すれば、iOSがアプリの言語に従って複数形のカテゴリを判定して、正しい文字列を返してくれます。

Android

xml で言語リソースが出力されます。キーの種別が plurals になります。

 <plurals name="resource_key">
    <item quantity="one">%1$d item</item>
    <item quantity="other">%1$d items</item>
 </plurals>

getQuantityString (Kotlin) および pluralStringResource (Compose) 関数を使えば、Androidがアプリの言語に従って複数形のカテゴリを判定して、正しい文字列を返してくれます。

Unity

REALITYのUnityアプリ(UaaL)は独自でjsonのdictionaryを読み込んでローカライゼーションを行っています。複数形のキーはこのようなdictionaryが出力されます。

   "resource_key": {
        "one": "%1$d item",
        "other": "%1$d items"
    }

Unityは残念ながら複数形のカテゴリを判定するAPIがないため、様々な可能性を検討した結果、NativePluginを書くことにしました。詳細は割愛しますが、iOSとAndroid側に数字を渡して、複数形のカテゴリを判定してもらい、 one か other (またはそれ以外)かを返してもらいます。Unity側ではその種別をjsonのdictionaryから探して、文字列を取得します。

全プラットフォームの共通点として、開発者が複数形のカテゴリを判別するコードを書かないで、OS任せで実現できました。これにより、表示言語が増えても、複数形の判別に悩まずに済みました。

複数形が複数ある場合

複数形の単位が一つの文章に2つ以上ある場合、それぞれ正しく複数形を適用するのはかなり難しいです。例えば、2つある場合、最大4パターンの組み合わせになります。

  • 単数形x単数形 - 1 day 1 item

  • 単数形x複数形 - 1 day 2 items

  • 複数形x単数形 - 2 days 1 item

  • 複数形x複数形 - 2 days 2 items

プログラムでこれらのケースを出し分けるのは難しいことと、現在の言語リソースではこのパターンの文章は極めて少ないため、「対応できなくても良い」と決めました。

結果、AndroidとUnityは1つ目の数字で複数形を決める仕様にしていますが、iOSは組み合わせのパターンでも出し分けられるので対応しました。ただし、特殊なフォーマットが必要です。それについては、WWDC2023のDiscover String Catalogsの動画の15:47のComplex plural stringsの解説より参照できます。

運用の紹介

アプリ側が複数形の表示に対応できましたので、次に複数形の運用について紹介します。

できれば複数形化しない

Lokaliseでは、言語リソースキーの複数形化は簡単で、ワンクリックですべての言語に適用できます。しかし、複数形化すると、英語の文章修正はもちろん、他の5ヶ国語も修正しないといけないため、運用コストが上がります。そのため、複数形化しなくても自然な文章が作れる場合、複数形化をしない方針としています。

よく使っている回避方法は3つあります。

  • 短縮形を使う:5時間前 → 5h ago

  • 単位をなくす:ガチャチケット5枚 → Gacha Ticket x 5

  • 必ず複数形だと見なす:500アバターポイント → 500 Avatar Points

    • アバターポイントは500単位での交換のため、1になることはない

Left:2, Resets in 13h, Pull x1 のように、複数形ではなくても問題ない工夫がされています。

このように整理すると、複数形化しなくても済む文章がかなり多かったので、翻訳コスト・管理コストを抑えることができました。

英語以外の言語はベストエフォートで翻訳

REALITYでは12言語表示に対応していますが、社内にすべての言語の翻訳者がいるわけではなく、基本的に英語のみプロの翻訳者に翻訳を依頼しています。その他の言語は、最初は外部に翻訳を依頼しましたが、最近追加した文章は機械翻訳を使っています。(ちなみにタイ語は私がチェックしています。)

Lokalise管理画面上の複数形の言語リソース例

上記のスクショのように、言語リソースキーを複数形化すると、当然ながら、英語のみならず他の言語も単数形・複数形で翻訳しなければなりません。ここで活用しているのがChatGPTです。

ChatGPTでドイツ語の複数形を聞いた様子

上記では、ドイツ語の複数形が正しいかどうかを聞きました。単数形が Zeihung で複数形が Ziehungenですね。ネイティブスピーカーがいない場合、Google翻訳やDeepLの翻訳が特定のコンテキストにおいて正しいかどうかを聞くにはChatGPTが非常に精度高いです。これにより、タイムラグなく複数形対応が必要な言語の翻訳ができました。

まとめ

以上、複数形対応についてご紹介しました。

冒頭で書いたように、REALITYは海外ユーザーが実に約8割です。日本発のコミュニケーションプラットフォームとして、日本ユーザーの方が少ないプラットフォームは非常に珍しいと思います。「言語」はすべてのユーザーが目に触れる基礎要素であり、そのユーザーの母国語に対応しているか否かでサービスの印象が大きく変わります。

複数形対応によって、ローカライゼーションの質をシステム面から向上させることができましたが、REALITYプラットフォーム全体のローカライゼーションにはまだまだ課題があり、試行錯誤しながら改善に努めています。アバターを通して日本の魅力を見せつつ、グローバルユーザーにより一層受け入れられるサービスを目指します!