Sprout Social のような動的アプリケーションを複数の言語にローカライズするのは複雑な作業です。アプリケーションに表示されるテキストの翻訳は、話の半分にすぎません。また、翻訳用のテキストを簡単に抽出して交換できる方法でアプリケーションを開発することも含まれます。 Sprout では、翻訳についてはサードパーティ ベンダーに依存しています。しかし、翻訳リクエストを抽出、バンドルしてベンダーに送信し、その翻訳をエンド ユーザーに提供してレンダリングするためのツールが依然として必要です。



オープンソース ソリューションがまだ成熟していたため、Sprout エンジニアリング チームは何年もの間、カスタム ローカリゼーション ソリューションを使用して対応してきました。これにより、サポート対象言語で最大の顧客に対応できるようになりましたが、いくつかの便利な機能が欠けていました。この記事では、新しいローカリゼーション システムの概要、最も複雑なローカリゼーション シナリオにどのように取り組むか、Web エンジニアリング組織全体にそれらの変更をどのように段階的に導入したかについて説明します。



私たちの古いシステム

新しいローカリゼーション システムを理解するには、まず古いシステムがどのように機能し、改善できる領域を理解する必要があります。

メッセージ構文

アプリケーションのローカリゼーションは、エンド ユーザーに表示されるテキストをメッセージと呼ばれる文字列単位に抽象化することによって機能します。これらのメッセージは抽出され、翻訳者に送信されます。これらの文字列を抽象化することで、エンド ユーザーの優先言語に応じて文字列を簡単に交換できます。

これらのメッセージは、「Hello, world」などの単純な静的文字列にすることも、「Hello, {name}」などのプレースホルダーや「Hello, world」などのリッチ テキスト形式を使用することもできます。これらの機能は文字列にシリアル化する必要があるため、テキストを適切に翻訳してレンダリングするには、翻訳者とアプリケーション コードの両方が理解できる構文が必要です。

私たちの古いローカリゼーション システムが使いにくくなった原因の 1 つは、私たちが独自の構文を作成し、その構文用に自家製の「パーサー」を維持していたことにあります。このコードは保守に時間がかかり、構文は非常に最小限でした。より複雑なメッセージをレンダリングするのに役立つ追加機能が必要でした。

例: Sprout アプリケーションでは、「X 個の投稿があります」(X は動的な数値) をレンダリングする方法が必要です。




9の意味

複数形の場合を考えてみましょう。「You have 5」 投稿 ”。 「あなたは 1 を持っています」という特異なケースを考えてみましょう。 役職 ”。 「0」の場合を考えてみましょう。中国語や日本語など、「1」の場合に文法がある可能性のある言語を考えてみましょう。アラビア語、ポーランド語、ロシア語など、X が「大きな数」である場合の文法を備えた言語を考えてみましょう。

メッセージ管理

翻訳者に送信してアプリケーション内で交換できるメッセージがあります。私たちのアプリケーションには、これらのメッセージを保存し、エンド ユーザーに提供する方法が必要です。

私たちの古いシステムでは、すべてのメッセージが JSON ファイル (「lang ファイル」と呼ばれていました) に保存されており、手動で管理されていました。これらのファイル内のメッセージは、ソース JavaScript コード内の ID を使用して参照しました。ユーザーがスペイン語でのアプリケーションを希望した場合、スペイン語言語ファイルを提供し、JavaScript が ID を使用して対応するスペイン語メッセージをレンダリングします。



パフォーマンス上の理由から、そのページにあるユーザー メッセージのみを提供しようとしたため、アプリケーションのさまざまなページに個別の lang ファイルを用意しました。これは有効なシステムでしたが、チームとアプリケーションが拡大するにつれて、開発者がこれらの ID と lang ファイルを手動で作成および管理する時間が増えました。

  Sprout でメッセージと翻訳を手動で管理するために以前に使用されていた JavaScript のスクリーンショット's codebase.

新しいメッセージをアプリケーションに追加するには、開発者は、そのメッセージを参照するための一意の ID を使用して、メッセージを正しい lang ファイルに手動で追加する必要がありました。場合によっては、ID の衝突や ID のタイプミスの問題が発生し、アプリケーション内で lang が失われることがありました。 Web アプリケーションにテキストを追加するのは、直感的ではない手順が多く、面倒に感じられました。

私たちの新しいソリューション

これらの欠点を認識し、製品組織全体の Web エンジニアが解決策を開発するためにローカリゼーション ワーキング グループを設立しました。私たちはブレインストーミングのために定期的に会っていました。綿密な調査プロセスの結果、FormatJS を使用するために、Sprout アプリケーションを自家製ローカリゼーション システムから移行することにしました。 反応国際 ライブラリを作成し、その周りにメッセージを管理するためのインフラストラクチャを構築します。 React-intl は、JavaScript エコシステム内で最も機能が豊富で人気のあるオープンソース ローカリゼーション ライブラリであり、コードベースにうまく統合されました。

メッセージの構文

私たちはより堅牢なソリューションを望んでいましたが、最初から何かを作成することは望んでいませんでした。私たちが採用したのは、 ICU メッセージの構文 、Java、PHP、および C アプリケーションで使用される標準化された構文で、動的アプリケーション メッセージの複雑さを捉えます。の 反応国際 このライブラリは、ICU メッセージ構文メッセージの解析とレンダリングもサポートしています。

  ICU メッセージ構文が複数のケースをどのように捉えるかについての例を並べて示します。左側はロシア語に翻訳される前の英語のメッセージです。右側はロシア語に翻訳されたメッセージです。翻訳者がこのメッセージを他の言語に変換するときに、その言語を適切にサポートするために必要に応じて大文字と小文字を追加および削除できることに注目してください。このメッセージのロシア語翻訳では、「少数の」ケースと「多数の」ケースが追加されています。

これは、ICU メッセージ構文が複数のケースをどのように捉えるかの例です。これは英語とロシア語でのメッセージです。翻訳者がこのメッセージを他の言語に変換するときに、その言語を適切にサポートするために必要に応じて大文字と小文字を追加および削除できることに注目してください。このメッセージのロシア語翻訳では、「少数の」ケースと「多数の」ケースが追加されています。

ICU メッセージ構文は、数え切れないほどの言語の多くのアプリケーションによって徹底的にテストされています。高度な顧客のニーズをサポートできること、ローカライゼーションに関するあらゆる質問に対して、多くのソリューションや教育リソースがあることを信頼できました。


420番号の意味

メッセージ管理

私たちは、FormatJS が提供するツールを使用して、メッセージの追加、削除、保存のプロセスを自動化するシステムを開発しました。これには、メッセージの保存と参照へのアプローチ方法にいくつかの哲学的な変更が含まれていました。

FormatJS が推奨する古いシステムからの大きな変更は、メッセージの信頼できる情報源として UI コードを使用することでした。以前のシステムでは、メッセージのソースとメッセージの使用法が 2 つの異なる場所にあったため、それらの同期を保つ必要がありました。新しいシステムは、残りの UI コードとともにメッセージ ソースを保持します。 UI ファイルからすべてのメッセージを抽出して lang ファイルを生成するスクリプトを実行するだけで済みます。メッセージの内容は、ハッシュ関数を利用して一意の ID になります。


1313の意味

  Sprout でメッセージと翻訳を自動的に管理するために以前に使用されていた JavaScript のスクリーンショット's codebase.

この変更により、メッセージが UI コードと同じ場所に配置され、いくつかの利点がありました。

  • より読みやすく: UI コードにロボット用に設計された ID はもう必要ありません。これで、UI コード内の英語のメッセージを読み、ユーザーにどのようなテキストが表示されるかを理解できるようになりました。
  • 非手動 ID: マシンによってのみ使用されていたこれらの ID は、マシンによって生成されるようになり、定義上、メッセージごとに一意になります。
  • 手動で管理される lang ファイルはありません: 開発者はこれらの lang ファイルに触れる必要はありません。私たちのスクリプトはメッセージの追加と削除を管理します。

私たちはどのようにして移住したのでしょうか?

しかし、Web エンジニアリング チーム全体とコードベースをこの新しいシステムにどのように移行したのでしょうか?私たちはこれを 4 つのマイルストーンに分けました。新しいシステムの試験運用、チームの教育、古いシステムの廃止、新しいソリューションへの移行です。

新しいシステムの試験運用

ワーキング グループは、アプリケーションの特定のセクションで新しいシステムを試験運用し、そのベスト プラクティスと完全な移行範囲を把握しました。これにより、クライアント側 (ポリフィルなど) とアプリケーションのビルド側で新しいシステムがセットアップされました。これにより、開発者のエクスペリエンスを反復してリスクを軽減することができました。

教育

私たちはパイロットから学んだことを取り入れて、Web エンジニアリング チーム全体の教育に使用しました。新しいライブラリを使用する開発者を支援するために、FAQ やその他の教育文書やプレゼンテーションを作成しました。このステップは過小評価されがちですが、移行のこの部分は非常に重要です。新しいシステムがどれほど優れているかは関係ありません。人々はそれをどのように、そしてなぜ使用する必要があるのか​​を知る必要があります。

また、Sprout の各 Web 機能チームに任命されたローカリゼーション アンバサダーを配置するアンバサダー プログラムも開発しました。このアンバサダーは、チームの新しいシステムの教育を支援し、問題や問題点をワーキング グループに報告する責任を負いました。

これにより、教育責任を委任し、個々のチームに固有の問題を特定することができました。

古いシステムの廃止

新しいシステムの開発者エクスペリエンス、共有された知識、拡張性の可能性に自信を持った後、古いシステムを非推奨にしました。いくつかのカスタム eslint ルールを作成し、lint ツールを使用しました。 エスプリント 、既存の使用を許可しながら古いシステムの使用をブロックします。この時点から、Web エンジニアは新しいコードを記述するときに新しいシステムを使用することが期待されました。

新しいシステムへの移行

新しいシステムと一定数の古い使用法に自信を持って、移行を開始しました。

新しいシステムでは、多くの使用法が 1 対 1 で同等でした。これらの同等のものが存在する場合、次を使用してコード MOD を記述することで移行を自動化できました。 jscodeshift 。コードベースのセクションに対してコード MOD を繰り返し実行し、学習しながら問題を解決することができました。簡単にコードモードできないエッジケースはほとんど残っていないため、手動で修正することに抵抗がありませんでした。

ロールアウトする

すべてを一度に移行するのではなく、このような反復的なアプローチを選択したのはなぜですか?反復的なアプローチを使用することは Sprout のエンジニアリング文化の一部であり、私たちは常に学習し、改善することが重要であると信じています。

この方法で移行に取り組むことで、進行しながら学習し、問題をリアルタイムで調整および修正することができました。移行によってアプリケーション開発がブロックされ始めた場合は、変更をロールバックすることもできます。反復的なアプローチにより、他の取り組みに取り組みながら進歩することができ、大きな変更を全員に展開する前に、より小さなグループで機能フラグを立てることができるようになりました。アプリケーションの機能開発と同じ原則が、内部開発者ツールの開発にも当てはまります。

学んだことと教訓

ローカリゼーション システムの再考は、Web エンジニアリング組織全体にわたる大規模な作業でした。同様のプロジェクトや課題に直面している他の人たちへの私のアドバイスは次のとおりです。

  • 広く採用されている標準を使用します。 この問題領域について何年も考えてきたエンジニアがすでに ICU メッセージ構文を開発しているのに、なぜカスタム メッセージ構文を作成するのでしょうか?
  • 関連する項目を併置することを検討してください。 追加、変更、削除がはるかに簡単になります。
  • 反復的なロールアウトを採用します。 変更を進めながら学習できるように、変更のロールアウトを設計します。すべてを予測することは不可能なので、計画に頼れるスペースを組み込んでください。
  • 学んだことを共有してください: 教育は展開の半分です。新しいシステムがどれほど優れていても、人々がその使い方やなぜそれが優れているのかを知らなければ、意味がありません。

Sprout のエンジニアリング文化の詳細については、こちらをご覧ください。 キャリアページ 今日。


7の数秘術の意味

友達と共有してください: