はじめに
こんにちは。エンジニアリングマネージャの星野です。今回はReactを用いたSPAの他言語化についての事例を紹介します。
テックドクターで開発している臨床研究支援システム「SelfBase」において、海外案件への対応をきっかけに管理画面の多言語化が必要となりました。
フロントエンドはReactを用いたSPA(Single Page Application)で構築されており、自前で実装する場合は react-i18next などを利用したi18n(国際化)対応を行うことになります。そのためには数ヶ月単位の少なくない開発工数が見込まれました。
そこで、「自前での実装」という選択肢だけでなく、「SaaS型の翻訳サービス」の導入を本格的に検討することにしました。
フロントエンド技術スタックと検討ポイント
多言語化を検討するにあたり、技術スタックとSaaS選定のポイントについて説明します。
フロントエンド技術スタック
フロントエンドの主要な技術スタックは以下の通りです。
- UI: React
- 言語: TypeScript
- ルーティング: React Router
- スタイリング: MUI + Emotion
SaaS選定における検討のポイント
SaaSを選定するにあたっては、開発工数をかけずに多言語化を実現するため、いくつかの点を重視しました。
- SPAに対応していること。
- 翻訳管理が容易であること。たとえば、翻訳された文言の一元管理機能ができる、ユーザーデータのような翻訳不要な要素を柔軟に除外できる、など。
- 予算内で導入できるコストであるか。
- SOC2やGDPRなどのセキュリティ基準を満たしているか。
- 国内外での十分な導入実績があるか。
SaaSによる多言語化の比較検討
上記のポイントに基づき、いくつかのSaaSを比較検討しました。
| サービス名 | SPA対応 | 価格帯 | 特徴 |
|---|---|---|---|
| shutto翻訳 | 実績不明 | 安価 | 国内サービス。SPAでの利用実績が確認できず、今回の要件には合致しませんでした。 |
| WOVN.io | 対応可能 | 高額(要問合せ) | 日本国内での大手企業による採用実績が豊富。ただし、コストが比較的高額でした。アプリの翻訳機能もあり、予算があるなら利用したかった。 |
| ConveyThis | 対応可能 | 安価 | 比較的安価で導入しやすそう。ただ、後述するWeglotと比較すると実績やシェアの面で見劣りしていました。 |
| Weglot | 対応可能 | 手頃 | SPA対応が可能。料金も手頃で、セキュリティ基準も満たしていました。調べた範囲ではPV数ベースの集計において高いシェアを持っているようでした。 |
検討結果
比較検討の結果、Weglotを導入することにしました。理由は下記です。
- ReactなどのSPAプロジェクトへの導入がヘルプに記載されており、実績があると判断できました。
- 実際にテストで動作させてみても、問題なく対応していることが確認できました。
- 翻訳結果を管理するダッシュボードがあり、非エンジニアでも直感的に翻訳の修正や管理が可能でした。
- AIを利用した翻訳が利用でき、翻訳の修正工数を減らせると期待しました。
- SOC2およびGDPRに準拠しており、エンタープライズレベルのセキュリティ要件を満たしています。
- Google検索やWappalyzerなどの情報から、ある程度シェアがあると判断。国外では大手での導入実績もあるようでした。
- 必要な機能を備えつつ、料金が手頃で、予算感に最もマッチしていました。
実装と運用の工夫
Weglotの導入はスムーズでしたが、実際のプロダクトで運用するためにはいくつかの工夫が必要でした。
導入方法
- Weglotでのプロジェクト作成
Weglotでアカウントを作成し、翻訳元(日本語)と翻訳先の言語(英語など)を設定します。
- インテグレーションの方式の選択
サブドメイン方式とサブディレクトリ方式があります
SEOなどの観点からサブディレクトリ方式が推奨されていますが、今回はサブドメイン方式を選択しました。
理由としては、既存サイト全体がWeglot経由で配信されようになるため、影響範囲を抑える目的でサブドメイン方式を選択しました。
- DNSレコードの設定
WeglotからCNAMEに登録すべきURLが提供されるので、利用しているDNSプロバイダー(Amazon Route 53、Google Cloud DNSなど)から、指定したサブドメインをCNAMEレコードとして、追加します。
この設定により、例えば、en.example.comへのアクセスがWeglotのサーバーに向けられ、翻訳されたコンテンツが配信されるようになります。
- JavaScriptスニペットの埋め込み
発行されたAPIキーを含むJavaScriptスニペットをWebサイトに埋め込みます。
これは主に、翻訳単語の抽出や言語切り替えボタン(言語スイッチャー)の表示、言語によるサイトの自動切り替えなどに利用します。
- SPA特有の設定
デフォルトでは動的に描画されるコンテンツは翻訳されません。
翻訳対象に含めるため、Weglotのプロジェクト設定にある Dynamic Element にて、 body セレクタを指定します。

実装上の注意点
Weglotは手軽に導入できる反面、自由度は低いと感じました。
そのため運用にあたっては、以下のような工夫が必要でした。
翻訳対象の除外設定:
Weglotはデフォルトでページ上の全テキストを翻訳しようとします。翻訳が不要な箇所については、翻訳対象から除外する設定を行う必要がありました。
- ユーザー名などのユーザが入力した内容
本来翻訳の対象としたくない部分ですし、翻訳の管理上もユーザが新しい単語を入力するために訳語の設定が必要となってしまうのは好ましくありません。
また、翻訳語数ベースの課金モデルにおいてコストを抑える意図もあります。
対策としては、翻訳したくない要素をラップする
export const NoTranslate = forwardRef<HTMLElement, BoxProps>( ({ component = 'span', ...boxProps }, ref) => ( <Box ref={ref} className="no-translate" translate="no" component={component} {...boxProps} > {boxProps.children} </Box> ), ) NoTranslate.displayName = 'NoTranslate'

- 日付や数値のローカライズ
日付や数値は翻訳ではなく、各言語の文化に合わせたフォーマットが必要です。これらは翻訳対象から除外し、Intl.DateTimeFormatやIntl.NumberFormatといったブラウザ標準APIで対応しました。
動的テキストの制約(語順と単数/複数形):
例えば {count}日間以上デバイスのデータがアップロードされてない場合 のような動的に数値を埋め込むテキストを翻訳する場合、{count} 部分は翻訳から除外するため、数字を除いた「日間以上デバイスのデータがアップロードされてない場合」というテキストをもとに翻訳が行われます。
これにより、2つの大きな問題が生じます。
1つ目は語順の問題です。
翻訳後のテキストは、翻訳されなかった {count} の後ろに単純に連結されます。しかし、多くの言語では日本語と語順が異なります。例えば、英語で「For more than {count} days...」のような {count} の前に前置詞が来るケースがありますし、他にも文法上、数字が文中に入ってしまう場合もあります。こういった文章は自然に作ることができません。
2つ目は単数/複数形の切り替えです。`{count}`の値に応じて `1 day` / `2 days` のように単語の形を変化させることができません。
今回はこれらの制約を許容し、妥協案として {count} day(s) without device data uploaded のような、英語表記で対応しました。
1つ目の問題は翻訳元の文に変数プレースホルダーを挿入する「variables」機能を利用することで解決はできそうでしたが、今回はそこまで対応することができませんでした。
文脈に応じた翻訳の難しさ
Weglotでは、基本的に一つの単語は一つの訳語に対応します。例えば「日」という単語を day(s) と翻訳した場合、別のページで「日曜日」の文脈で使われていても day(s) と訳されてしまう可能性があります。これを防ぐには、元の日本語の単語を文脈に応じてより具体的に(例:「日付」「日曜日」など)使い分けるといった、原文側での工夫が必要になります。
Weglotよりもさらに厳密な表現や文脈に合わせた翻訳が求められる場合は、やはり react-i18next のようなi18nライブラリによる本格的な対応が必要と感じました。


翻訳の質と翻訳管理について
自動翻訳の品質は、まずまずといった程度でしたが、AI機能を使うとかなり不自然な内容は減りました。
長文では、手動での言い換えが必要になる場合も多少ありましたが、短いフレーズや単語レベルの翻訳は正確でした。全体としては十分に実用的な品質といえます。
また、専門用語や製品名などについては、翻訳するかどうかも含めて辞書登録できる点が便利でした。

さらに、翻訳結果にレビュー済みかどうかが分かる仕組みが用意されており、今後画面修正などが発生した際にも、追加翻訳をスムーズに行えるようになっています。

i18nライブラリのように翻訳者が翻訳ファイルを直接編集するわけではないため、翻訳者と開発者の役割分担が明確になり、運用がスムーズになる点もメリットと感じています。

導入後の感想
Weglotの導入を決定したことで、当初3ヶ月以上かかると想定していた多言語化対応が、1ヶ月程度で完了する見込みとなりました!
これにより、SaaS導入は期待通りにエンジニアの工数を大幅に削減でき、非常に助かりました。
課題点としては、初回アクセス時は一瞬だけ日本語が表示されてから英語に切り替わるという動作になっています。
この点は、当初から理解していて実用上は問題ないと判断していましたが、不自然さは感じてしまいます。
今後について
今回は、まずはいったん多言語サイトをサービス提供することが重要だと考えて、SaaSという選択肢を選びました。
ですが、一瞬日本語で表示されてしまう点や翻訳の制限などから、どこかでi18nライブラリを用いた本格的な多言語化基盤の構築も必要だと感じています。
その際には、今回見送った react-i18next によるi18n基盤の構築を再度検討し、翻訳ファイルの管理に特化したSaaS(Lokalise, Transifexなど)へ移行することも検討したいと考えています。
まずは、Weglotで翻訳の知見を溜めつつ、翻訳精度の向上や用語の統一を行うことでグローバルに通用するサービスの第一歩目としていきます。

書いた人:星野