多言語対応の第一歩!静的コンテンツを翻訳する仕組みの一例
はじめに
こんにちは。株式会社ペライチ開発チーム フロントエンドエンジニアの関(@nekoneko_wan2)と申します。
現在、ペライチではサービスのグローバル化を進める計画があります。グローバルなユーザーに対応するための最初のステップとして「多言語化」は重要な取り組みです。
多言語化を実現するには、単にテキストを翻訳し置き換えるだけではなく、効率的に管理・運用できる仕組みを整える必要があります。本記事では、辞書データを活用し、静的コンテンツの多言語化に焦点を当てながら、具体的にどのようなアプローチが可能かを考えてみたいと思います。
言葉の整理
まずは前提として、よく出てくる言葉の意味を簡単に整理してみます。
- グローバル化 (Globalization)
- 製品やサービスを世界中で展開するための全体的なプロセスや戦略
- 国際化 (Internationalization: i18n)
- 多様な言語や地域に対応可能な形に設計するプロセス
- 地域化 (Localization: L10n)
- 特定の言語や地域に合わせて最適化するプロセス
- 多言語化
- 製品やサービスを複数の言語に対応させること
- ユーザーが選択した言語で適切なコンテンツやUIを表示できるようにする仕組み
こんな感じでしょうか
gettext
つぎに多言語化について調べると gettext
というワードが見つかります。
gettextは国際化と地域化に対応するライブラリ構成要素の一つであり、様々な地域の言語に対応した地域化ソフトウェアを開発する際に用いられる。gettextライブラリを用いることで、ソフトウェアの対話的メッセージを翻訳された現地語にて容易に表示させることができる。
こちらを利用することで、翻訳管理を効率的に行うことができそうです。
- エンジニアと翻訳者の分担
- 複数言語への対応や翻訳アップデート
- 適切な翻訳の自動表示
ファイル形式
gettextで翻訳データを管理するために以下の3種類のファイル形式を使用します。
- .potファイル(翻訳テンプレートファイル)
- .poファイル(翻訳データファイル)
- .moファイル(コンパイル済み翻訳ファイル)
翻訳対象のテキストを.potファイルにまとめ、それを基に言語ごとの.poファイルを生成します。翻訳者は.poファイルを編集して翻訳作業を行い、必要に応じてシステムで利用しやすい形式である.moファイルに変換します。
また専用のGUIツールも存在し、ある程度の品質を保ちやすいメリットもあるかもしれません。
簡単なデモ
言葉だけだと中々難しいので、ここからは簡単に流れを紹介したいと思います。
翻訳ファイルの準備
まずはpotファイルを用意します
実際にはgettextでソースファイルからテキストを抽出して作成するのが良さそうですが、ひとまず手動(ChatGPT)で作ってみます。
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YYYY-MM-DD HH:MM+ZZZZ\n"
"PO-Revision-Date: YEAR-MO-DA HH:MM+ZZZZ\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "Hello, world!"
msgstr ""
次にここから.poファイルを作成します。
Poeditでも生成可能そうですがコマンドから生成してみます。
msginit --locale=ja --input=hello.pot
以下のようなファイルが生成されました
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Project-Id-Version: i 18n_sample\n"
"POT-Creation-Date: YYYY-MM-DD HH:MM+ZZZZ\n"
"PO-Revision-Date: 2024-12-26 15:44+0900\n"
"Last-Translator: xxx\n"
"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
msgid "Hello, world!"
msgstr ""
Poeditで翻訳テキストを入力して上書き保存します
msgid ""
msgstr ""
"Project-Id-Version: i 18n_sample\n"
"POT-Creation-Date: YYYY-MM-DD HH:MM+ZZZZ\n"
"PO-Revision-Date: 2024-12-26 15:47+0900\n"
"Last-Translator: xxx\n"
"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.5\n"
msgid "Hello, world!"
msgstr "こんにちわ!"
msgstrにテキストが反映されました。
以降はmsgidとmsgstrをもとに、日本語用翻訳データとして育てていきます。
必要に応じてpo→moへの変換も行います
アプリケーションの用意
実際に用意したデータを使った簡単なアプリケーションを作ってみたいと思います。
今回はNuxtで @nuxtjs/i18n
というモジュールを使って実装してみます。
- データの準備
- ja.poとen.poを用意
- 扱いやすいようpoをjsonに変換(変換処理は省略します)
- Nuxtの設定
- @nuxtjs/i18nをインストール
- jsonファイルを特定ディレクトリに格納
- nuxt.config.ts
{
"Hello, world!": "こんにちは"
}
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
// restructureDir: 'i18n/',
lazy: true,
langDir: './lang',
locales: [
{ code: 'en', file: 'en.json', iso: 'en-US', name: 'English' },
{ code: 'ja', file: 'ja.json', iso: 'ja-JP', name: '日本語' },
],
vueI18n: './i18n.config.ts',
defaultLocale: 'en',
detectBrowserLanguage: {
useCookie: true,
cookieKey: 'i18n_redirected',
alwaysRedirect: true,
fallbackLocale: 'en'
},
strategy: 'no_prefix'
},
})
ドキュメントなどはこちら
Viewでは t()
を通してデータにアクセスします
<script setup>
import { useI18n } from 'vue-i18n'
const { t} = useI18n();
</script>
<template>
<div>
<p>{{ t('Hello, world!') }}</p>
</div>
</template>
実際の画面
今回cookieの値をみて翻訳を切り替える設定にしたので例えばユーザーの操作要求に応じてcookieを加工して該当言語で表示させる、といったことも実現できそうです。
en | ja |
---|---|
終わりに
メリットは前述の通り、効率的に翻訳管理を行える点が挙げられます。一方で、翻訳データを辞書として分離することで、実際に使われるコンテキストの把握が難しくなり、その結果、翻訳者によって品質にばらつきが出る可能性もあるかなと感じています。
本記事が多言語化対応の参考になれば幸いです
採用情報
現在エンジニア募集しています!
▼ 採用ページ
▼ 選考をご希望の方はこちら(募集職種一覧)
▼ まずはカジュアル面談をご希望の方はこちら
募集中の職種についてご興味がある方は、お気軽にお申し込みください(CTO がお会いします)
Discussion