🌐

多言語翻訳機能をWebサイトにお気軽導入!「GTranslate」を使う時のポイントとJavascriptでの検知方法

に公開

どうもこんにちは!!!
クラウドワークスグループのソニックムーブで働いている安立です。
今年もAdvent Calendarの季節になりましたね。
今年はシリーズ2をソニックムーブで埋め尽くすぜ!というノリでやっています。
組織として1年間アウトプットを続けてきた総決算です。

さてさて、今回は・・・
先日個人的に「GTranslate」という、無料かつ簡単にWebサイトに多言語翻訳機能を導入できるサービスを使う機会がありました。
その「GTranslate」の紹介と実際使う中でのポイントだと思った3点、おまけでJavaScriptでの翻訳イベントの検知方法を書きますね。

ポイントのみ見たいという人は、以下リンクから飛んでくださいませ。


GTranslateとは

GTranslateは、ウェブサイトの多言語化・翻訳サービスです。
JavaScriptのコードをWebサイトに設置するだけで導入できちゃいます。

AIによる自動翻訳を使っていて、現時点(2025年12月)で、なんとびっくり103言語に対応しています。
機械的に翻訳させるだけであれば、無料版でも十分に対応が可能なのでとりあえず補助的に翻訳を導入したいな〜という場合は十分に使えるのでは無いでしょうか?

有料版は使ったことがないため、今回は無料で使うことを前提としてます。

使い方

以下の「言語選択ウィジェット」ページで、お好みの設定をするとページ下部の「ウィジェットコード」が更新されるので、そのコードを自身のサイトに貼り付ければOKです!
プレビューも可能なので、設定を編集しながらプレビューして自分のサイトに合う形に編集できますよ。
https://ja.gtranslate.io/ウェブサイト翻訳ウィジェット

無料で使える機能の範囲

無料版で使える機能は以下です。
無料版でも機械的に翻訳するだけであれば、十分な機能です。

  • すべての言語
  • 機械翻訳
  • 無制限の単語とページビュー

有料版を使うと、翻訳の編集ができたり、翻訳されたページを検索ページにインデックスする事が可能になるようです。
その辺りの詳細はオフィシャルサイトを見てください。
https://ja.gtranslate.io/#pricing


さてさて、それでは使う上でのポイント、行ってみよーーー!!!

ポイント1:翻訳させたくない場合の方法

場合によっては部分的にテキストを翻訳対象外としたい場合があると思います。
やり方は2つあります。

実際の挙動はデモを用意しています。「翻訳対象にしたくない場合」部分をみてください。

classを指定する

翻訳させたくない部分にnotranslateというclassを指定します。

<p class="notranslate">
    翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。
</p>

<!-- 親の要素に指定すると、子孫のテキストは翻訳されなくなります -->
<div class="notranslate">
    <p>翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。</p>
    <p>翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。</p>
</div>

translate属性を指定する

HTMLにはtranslate属性というのがあるので、それを使って翻訳対象外にする事も可能です。
translate属性をnoで指定します。

<p translate="no">
    翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。
</p>

<!-- 親の要素に指定すると、子孫のテキストは翻訳されなくなります -->
<div translate="no">
    <p>翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。</p>
    <p>翻訳させたくない文章。翻訳させたくない文章。翻訳させたくない文章。</p>
</div>

ポイント2:組み方によっては崩れる可能性がある

翻訳を実行するとDOMの構造に変化があるため、CSSの組み方によっては崩れる可能性があります。
実際の挙動はデモを用意しています。「CSS次第で崩れる例」部分をみてください。

パターンはいくつも考えられるのですが、flexを使っている部分が特に注意が必要です。

flexの子要素でbrを使用している場合

以下のようなコードです。
要素の上下センターにテキストを配置したい時にありそうなコードです。

<div class="kuzureruyo">
    文章1文章1文章1<br>
    文章2文章2文章2文章2
</div>

<style>
    .kuzureruyo {
        display: flex;
        align-items: center;
        padding: 20px;
        width: 300px;
        height: 150px;
        border: 1px solid #000;
    }
</style>

ですが、GTranslateとは相性が悪いです。
なぜかというと、翻訳を実行するとコードが以下のようになります。

翻訳対象によってfontタグのネスト具合は微妙に異なります。
また、実際には色々な属性が付与されたりするのですが、その点は省略しています。

<div class="kuzureruyo">
    <font>
        <font>文章1文章1文章1</font>
    </font>
    <br>
    <font>
        <font>文章2文章2文章2文章2</font>
    </font>
</div>

これにより、flexにした要素の子要素が2つに増えて、意図しないレイアウトになります。
この場合だと、文章1と文章2が横並びで表示されるようになります。

という形で、DOMが変更されることによって崩れる可能性があるCSSの書き方はやめましょう。

ポイント3:iPhoneのSafariでの挙動が不安定

iPhoneのSafariで翻訳が動かない事が多いようです。
https://discussionsjapan.apple.com/thread/256097803

下記はwordpressのプラグインの話ではありますが同じものではあるため、有料プラン使えば動くみたいです。
https://wordpress.org/support/topic/safariで翻訳機能が使えない/

無料のものを使用してWebサイトに設置する際は、iPhoneのSafariで動かない場合がある事を書いておいた方が良いですね。


JavaScriptでの検知方法

おまけで、翻訳が実行された際にJavaScriptで検知する方法について書いておきます。

GTranslateは翻訳実行時に<html>タグのlang属性を変更します。
この変更をMutationObserverで監視することで、翻訳のタイミングを検知できます。

結論のコードは以下。
属性変更の検知を1回に絞りたかったのですが、複数回検知されてしまうため翻訳実行した時に最初の1回だけ実行するようにsetTimeoutでフラグ管理した処理にしています。

// 変更を監視するノード
const targetNode = document.getElementsByTagName("html")[0];

// オブザーバーのオプション:属性のlang属性のみに絞る
const config = { attributes: true, attributeFilter: ['lang']  };

// なぜかオブザーバーが複数回呼び出されてしまうため、処理を1回に限定するためのフラグ
let isDone = false;

// オブザーバー処理
const observer = new MutationObserver((mutations) => {
    if(!isDone) {
        console.log("ここに翻訳を実行した時に実行したい処理を書く");
    }
    isDone = true;
    setTimeout(() => isDone = false, 100);
});

// 実行
observer.observe(targetNode, config);

これで、JavaScriptで翻訳されたかを検知してイベントを実行できます。
ただし、表示の出しわけを行いたい場合などは、JavaScriptを使用せずになるべくCSSで行いましょう。

htmlの属性セレクタを使えば特定の言語での表示制御が可能になりますよ。

html[lang="en"]

まとめ

GTranslateを実際に使ってみて気をつけたいポイントをまとめました

  • 翻訳対象外にしたい場合はnotranslateクラスかtranslate="no"属性を使用
  • flexとbrの組み合わせなど、DOM構造の変化で崩れる可能性に注意
  • iPhoneのSafariでは無料版だと動作しない場合がある
  • 翻訳検知はMutationObserverで可能だが、表示制御はCSSで行う方が良い

それではまた〜〜〜!

株式会社ソニックムーブ

Discussion