2011年11月11日金曜日

「Google翻訳」使用時での SyntaxHighlighter の設定に関して

今回は SyntaxHighlighter を使ったページを、Google翻訳Google translate) で翻訳する場合の設定について考えてみます。

個人的には全く使っていない Google翻訳 だが、未知の言語で書かれたページを読むには便利ではないだろうか。とは言っても海外から、このブログを翻訳してでも読みたいという需要は皆無だと思う。ただ需要はないにしても、実際に記事を翻訳した場合、妙な表示になるところだけは直したいと思う。

なお 「Googleウェブサイト翻訳ツール」 での設定については、こちらで 説明しています。

Google翻訳 でのページ表示異常

Google翻訳で何の対策もせず、ブログ記事を表示させると次のようになる。

SyntaxHighlighter を使ったコード部分が妙なことになっているのがわかる。Google翻訳はマウスオーバで原文を表示するために、spanタグを利用して記事に翻訳文と原文が混在したコードを追加してしまう。それでおかしな表示になる。

このような場合次のように、Google翻訳を制御するコードを追加することで解決が可能だ。

  • ページ全体を翻訳されないようにする
    次のメタタグをHTMLファイルに追加する
    <meta name="google" value="notranslate">
    
  • ページの一部分が翻訳されないようにする
    HTML 要素に class=notranslate を追加する
    <span class="notranslate">この部分は翻訳されない</span>
    

参考: Google translate - よくある質問

今回の場合、SyntaxHighlighterが動くコード部分が翻訳されないようにすれば良いので、preタグに notranslate を追加して試してみる。

<pre class="brush: py;">

のところを、次のように変更する。

<pre class="brush: py; notranslate">

すると次のようになった。

コード部分は翻訳されないのはよいのだが、それ以降の文書まで翻訳されないようになってしまった・・・。

正しい notranslate の設置方法

GoogleのヘルプにはHTML要素に設置すればよいと書いてあるが、どうも違うようだ。いろいろなパターンで試してみたが、よく分からない。Google翻訳のロジックによって、うまく翻訳を制御する場合としない場合があるようだ。

ただ SyntaxHighlighter に限って言えば、ほぼ100%制御する方法が分かった。それが次の方法である。

SyntaxHighlighter に対して notranslate を設定する方法

preタグをdivタグで包み、divタグにnotranslateを設定する。

<div class="notranslate">
<pre class="brush:html">
・・・コード・・・
</pre>
</div>

先ほどのサンプルのソースを修正し、再度 Google翻訳 にかけた結果は次のようになる。

うまく制御されている。

divタグに notranslate を設定する方法は確実なのだが、全記事を直さなければいけない。もっと簡単な方法はないだろうか?。

SyntaxHighlighter を Google翻訳 に対応させる簡単な方法

最初に考えるのはやはり、Javascript を使用して notranslate付きの divタグを設置する方法である。ただこの方法は成功しない。なぜなら Javascript が動く前に、Google翻訳 がページを改変するからである。

次に考えるのは、Google翻訳が改変するコードを参考に原文を Javascript で拾ってくる方法である。Google翻訳が挿入するコードは次のような構造になっている。

<span onmouseover="_tipon(this)" onmouseout="_tipoff()">
<span class="google-src-text" style="direction: ltr; text-align: left">
原文</span>
翻訳文</span>

これがセンテンス単位で挿入されてくるので、原文の部分だけ拾って置き換えればよい。例えば次のような javascript(jQuery)を設置すれば可能だ。

<script type='text/javascript'>
jQuery(function($) {
  var v = $('.google-src-text').css('display');
  if(v == 'none'){
    $('pre > span').each(function() {
      $(this).replaceWith($(this).contents().filter(function(){return this.nodeType == 3;}).text());
    });
  }
  else {
    $('pre > span').each(function() {
      $(this).replaceWith($(this).contents().filter('.google-src-text').text());
    });
  }
});
</script>

しかしこの方法で表示した場合、SyntaxHighlighter がタグを誤認して表示が無茶苦茶になる場合がある。

他に良い方法はないだろうか?。ここで思い付いたのは Google翻訳 を使用する場合だけ、SyntaxHighlighter の動作を止める方法である。SyntaxHighlighterが動かなければコードも乱れず表示されるし、マウスオーバで原文表示も可能になる。

Google翻訳使用時、SyntaxHighlighter の動作を停止する Javascript(jQuery)
<script type='text/javascript'>
jQuery(function($) {
  $('pre[class^="brush"]:has(span[onmouseover])')
   .css('padding','5px')
   .css('background-color','#F0F0F0')
   .removeAttr('class');
});
</script>

このコードは、preタグのclass属性に brush と記述されているタグの中に、onmouseover 属性を持つ spanタグ が子供要素として存在する場合は、preタグのclass属性を削除する。

コードを head タグ内に設置し、Google翻訳を実行すると次のように表示される。

方法は本末転倒であるが、マウスオーバも使用できるし意外と快適だ。コード内のコメントも翻訳してくれる。だたコードとは言っても、Google翻訳は一部原文も変換してしまう。やはり一番確実なのは、divタグに notranslate を設定する方法である。

最終的に SyntaxHighlighter の動作を止める Javascript を設置することになりましたが、最小の変更で正常に(近い形で)表示する方法ではないかと思います。

参考: Google翻訳 - 英語でこの記事を翻訳


Googleウェブサイト翻訳ツール について

SyntaxHighlighter は、『Google翻訳』 を使用した場合は記事のように表示が乱れます。しかし 『Googleウェブサイト翻訳ツール』 ではキチンと表示されるようです。これは「Googleウェブサイト翻訳ツール」は、Javascriptが動作した後に翻訳しているのが理由のようです。

参考
Google翻訳
Googleウェブサイト翻訳ツール

このため「Googleウェブサイト翻訳ツール」で SyntaxHighlighter のコードを翻訳させないようにする、次のような簡単な方法があります。

SyntaxHighlighter の設定(通常は headタグ内に記述)で、次のようにクラスとして notranslate を指定する。
SyntaxHighlighter.defaults['class-name'] = 'notranslate';
デフォルトクラス名として指定することにより、SyntaxHighlighter が成形する全てのコードのタグに notranslate がクラス属性として設定される。