GTranslate無料版がSafariで不安定になる原因と対処法【WordPress】

その他
その他

当サイトを多言語化したいと以前から考えていた。

これまでも海外の友人たちとやり取りする際には、よく自分のブログのURLを伝え、相手側でブラウザの翻訳機能を使って内容を理解してもらっていた。
最近はページごと簡単に翻訳できるようになったとはいえ、毎回その手間をかけてもらうのは少し申し訳なく感じていたし、サイト側で多言語対応できれば、もっとスムーズに読んでもらえるのではないかと思っていた。

そこで、WordPressで簡単に多言語化できるプラグインはないかと調べてみたところ、GTranslateが良さそうだと知り、試しに導入してみた。

すると、設定から数分でサイト全体が多言語対応となり、想像以上に手軽に翻訳環境を構築することができた。

有料版にしないと翻訳されたページは検索エンジンにインデックスされない仕様ではあるものの、無料版でも100言語以上に対応しており、海外SEOを本格的に狙わないのであれば十分実用的である。
実際、当サイトにも少しずつではあるが海外からのアクセスはあり、ユーザー体験の向上という意味でも導入する価値は高いと判断した。

GTranslate導入後の表示イメージ

GTranslateは100言語以上に対応しているが、すべてを表示すると逆にユーザー体験が悪くなると感じたため、

  • 日本語
  • 英語
  • スペイン語
  • 中国語(簡体)
  • フランス語

の5か国語のみに絞って設定した。

左上の言語切り替えから選ぶだけで、その後は常に選択した言語で表示され続けるため、非常に使い勝手が良い。

ここでは実際の表示例をスクリーンショットで紹介する。左右にスライドすると違いを見比べることができる。

このように、言語を切り替えるだけでサイト全体が即座に翻訳され、閲覧体験としても非常に自然である。

「海外の読者に読んでもらう際に毎回翻訳してもらう」という手間をなくせる点は、大きなメリットだと感じた。

Safariだけ動作が不安定になる問題が発生

しかし、導入後すぐに問題が発生した。

ChromeやGoogleアプリでは問題なく動作するものの、iPhoneのデフォルトブラウザであるSafari上だけ、翻訳の挙動が不安定になる現象が起きたのである。

  • 言語が切り替わらないことがある
  • リロードすると元の日本語に戻る
  • 動いたり動かなかったりする

といった状態で、どうにも安定しない。

最初は「AIと一緒に一瞬で解決した」と思った

私はまず、ネット上の情報を探したが、同じ症状を根本的に解決している記事はほとんど見つからなかった。

そこでAIを活用しながら原因を整理し、無料版のままSafariでも安定動作させる方法を組み立てた。
以前なら一晩かけて調査しながら対応していたようなことが、短時間で形になったので「いい時代だな」と思った。

そして実際にSafariで動作したため、私は「解決した」と判断して記事を一度公開した。

しかし、たまたま“動きやすい時間帯”だっただけだと分かった

ところが、公開後しばらくして同じ症状が再発した。

結論から言うと、最初に動いていたのはたまたま早朝で成功しやすい条件が揃っていただけの可能性が高い。
翻訳は外部サービス(スクリプトの配信や処理)を経由するため、時間帯による混雑や経路の違いで、成功率が上下することがある。

つまり「こちらの対策だけで100%安定化できた」と断言できる状態ではなかった。

記事は一度非公開に戻し、改めて検証と方針整理をやり直した。

なぜSafariだけ不安定になりやすいのか(要因の一つ:ITPなど)

Safariにはプライバシー保護の仕組みがあり(ITP:Intelligent Tracking Prevention など)、外部スクリプトやCookieの扱いが他ブラウザより厳しめである。

GTranslate無料版は、JavaScriptでページ内容を書き換えつつ、状態をCookie等に依存して動作する。そのためSafariでは環境やタイミングによって挙動が不安定になりやすい。

Chromeなどで問題が出にくかったのは、同じ条件でも外部スクリプトやCookieの扱いが比較的素直で、処理が最後まで走り切りやすいからだと考えている。

結論:無料版の現実解は「失敗した時だけ案内する」だった

記事を非公開にしてからも、AIと述べ数時間やり取りしながら原因の切り分けや実装の見直しを行った。

そして最終的に「Safariで100%成功させる」方向ではなく、「Safariでも読める導線を用意する」方向に舵を切った。

具体的には、Safariで言語を選択した後、短時間監視して翻訳状態が変わらなければ、エラーダイアログ(案内メッセージ)を表示する。
メッセージは選択した言語に合わせて切り替え、Safari内蔵翻訳の利用を促すようにした。

  • Safariではこの翻訳ボタンが動作しないことがあります
  • 一度リロードしてください
  • それでもダメなら、Safariのアドレスバーから使える内蔵翻訳を使ってください

この方式にしてからは、Chrome等は従来通り快適に動作し、Safariでも「失敗して終わり」にならず、読者が迷わない状態にできた。

実装例:functions.php(Safariで失敗した時だけ案内を出す)

以下は子テーマの functions.php に追記する形のサンプルコード(該当部分のみ抜粋)である。
※ すでに運用中の functions.php がある場合は、丸ごと置き換えではなく追記で導入すること。

add_action('wp_footer', function () {
  if (is_admin()) return;
  ?>
  <script>
  (function(){
    if (window.__gt_safari_failsafe_v2) return;
    window.__gt_safari_failsafe_v2 = true;
    var ua = navigator.userAgent;
    var isSafari = /^((?!chrome|android).)*safari/i.test(ua);
    if (!isSafari) return;
    function getCookie(name){
      var m = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\\\]\\/+^])/g,'\\$1') + '=([^;]*)'));
      return m ? decodeURIComponent(m[1]) : '';
    }
    function getState(){
      return {
        googtrans: getCookie('googtrans'),
        htmlLang: (document.documentElement.getAttribute('lang') || '').toLowerCase()
      };
    }
    function showBannerOnce(lang){
      var id = 'gt-failsafe-banner';
      if (document.getElementById(id)) return;
      lang = (lang || '').toLowerCase();
      var messages = {
        en: "Translation may not work properly in Safari.\nPlease reload once.\nIf it still doesn't work, use Safari's built-in Translate from the address bar.",
        fr: "La traduction peut ne pas fonctionner correctement dans Safari.\nVeuillez recharger la page.\nSi cela ne fonctionne toujours pas, utilisez la traduction intégrée de Safari dans la barre d'adresse.",
        es: "Es posible que la traducción no funcione correctamente en Safari.\nVuelve a cargar la página.\nSi aún no funciona, usa la traducción integrada de Safari desde la barra de direcciones.",
        "zh-cn": "Safari 中翻译可能无法正常工作。\n请先刷新一次页面。\n如果仍无效,请使用地址栏中的 Safari 内置翻译功能。"
      };
      var key = lang;
      if (key === 'zh' || key === 'zh-hans' || key === 'zh-cn') key = 'zh-cn';
      if (!messages[key]) key = 'en';
      var box = document.createElement('div');
      box.id = id;
      box.style.position = 'fixed';
      box.style.left = '12px';
      box.style.right = '12px';
      box.style.bottom = '12px';
      box.style.zIndex = '2147483647';
      box.style.background = 'rgba(255, 245, 0, 0.95)';
      box.style.color = '#000';
      box.style.padding = '12px 14px';
      box.style.borderRadius = '12px';
      box.style.fontSize = '14px';
      box.style.fontWeight = '700';
      box.style.boxShadow = '0 10px 30px rgba(0,0,0,0.25)';
      var btn = document.createElement('button');
      btn.type = 'button';
      btn.textContent = 'Close';
      btn.style.float = 'right';
      btn.style.marginLeft = '12px';
      btn.style.padding = '6px 10px';
      btn.style.borderRadius = '10px';
      btn.style.border = '2px solid #000';
      btn.style.background = 'transparent';
      btn.style.fontWeight = '900';
      btn.style.cursor = 'pointer';
      btn.onclick = function(){ box.remove(); };
      box.appendChild(btn);
      var msg = document.createElement('div');
      msg.style.whiteSpace = 'pre-wrap';
      msg.textContent = messages[key];
      box.appendChild(msg);
      document.documentElement.appendChild(box);
    }
    function inferLangFromClick(target){
      if (!target || !target.closest) return '';
      var el = target.closest('[data-gt-lang],[data-lang],[lang]');
      if (!el) return '';
      var lang = (el.getAttribute('data-gt-lang') || el.getAttribute('data-lang') || el.getAttribute('lang') || '').trim();
      return (lang || '').toLowerCase();
    }
    var lastWatchAt = 0;
    function watchFail(lang){
      var nowTs = Date.now();
      if (nowTs - lastWatchAt < 800) return;
      lastWatchAt = nowTs;
      var before = getState();
      var start = Date.now();
      var timer = setInterval(function(){
        var after = getState();
        var elapsed = Date.now() - start;
        var changed =
          (after.googtrans && after.googtrans !== before.googtrans) ||
          (after.htmlLang && after.htmlLang !== before.htmlLang);
        if (changed){
          clearInterval(timer);
          return;
        }
        if (elapsed > 2800){
          clearInterval(timer);
          showBannerOnce(lang);
        }
      }, 200);
    }
    document.addEventListener('click', function(e){
      var t = e.target;
      if (!t || !t.closest) return;
      if (!t.closest('.gt-fixed,[class*="gtranslate"],[id*="gtranslate"],[class*="gt_"],[id*="gt_"]')) return;
      var lang = inferLangFromClick(t);
      if (!lang) return;
      if (lang === 'ja' || lang === 'jp') return;
      watchFail(lang);
    }, true);
  })();
  </script>
  <?php
}, 30);

Safariの内蔵翻訳の使い方(簡単)

iPhone Safariには標準の翻訳機能がある。表示中のページで、アドレスバー付近のボタンから「翻訳」を選ぶだけでページ全体を翻訳できる。

GTranslateが不調な時でも、これで内容は問題なく読める。

注意点

本記事の内容は、現時点のSafariおよびGTranslateの仕様に基づく。Safari側の仕様変更やGTranslateのアップデートによって、将来的に挙動が変わる可能性がある点はご了承いただきたい。

無料版のまま運用する場合は、「完全な安定化」よりも、翻訳処理が失敗した時に読者が迷わない導線を用意する方が安全だと感じた。

まとめ

  • GTranslateは導入が簡単で、多言語化の導線として非常に便利
  • 無料版はiPhone Safariで不安定になることがある(時間帯など外部要因の影響も受ける)
  • 無料版で現実的に運用するなら、失敗時だけSafari内蔵翻訳を案内するのが最も安全な着地点だった
     

I’m a golf-a-holic man. ゴルフバカです。

ゴルフのためなら世界中どこでも行きます。食事とお酒も大好きな食いしん坊ゴルファー。

2026年現在、世界25か国・地域で日本国内約600コース、海外は約300コースをラウンドしているコースマニア。現在、世界中をゴルフ旅しています。ゴルフの腕前は平均スコア90前後のアベレージゴルファー。典型的なエンジョイゴルファーです。

芝鳥 のぶあまをフォローする

コメント

タイトルとURLをコピーしました