読者です 読者をやめる 読者になる 読者になる

まめ畑

ゆるゆると書いていきます

選択した文字を翻訳するJetpack Featureを作ってみた

Jetpack javascript

Jetpackがバージョンアップして、JEPからAudio以外にも取り込まれたものがあります。
Selectionというものなのですが、これはWebサイト上の選択した文字を取得したりする事が出来ます。
凄く簡単なAPIなので、仕様などはLabs/Jetpack/JEP/12 - MozillaWikiをご覧下さい。


文字を選択時に以下の関数が呼び出されます

jetpack.selection.onSelection( callback );

この関数の中に処理を書きます。

選択した文字は

//Textを取得
var textOfSel = jetpack.selection.text;
//タグも取得(タグつきで設定も可能)
var htmlOfSel = jetpack.selection.html;

で取得が出来ます。
このプロパティに代入する事で文字を置換する事も出来ます。

使用しなくなったら

jetpack.selection.onSelection.unbind( callback );

でイベントを外してやる事も可能です。


ふと英語論文を簡単(?)に翻訳するためのツールを作ってみた - あたご型護衛艦日記を読んで、選択した文字の翻訳が便利そうだったので、Selectionを使ってFeatureを作ってみました。
とりあえず「Translate Text mini」という名前で。
Featureのインストールはhttp://userscripts.org/jetpacks/122/から出来ます。

インストールするとステータスバーに

が出てきます。
ここで選択した言語に翻訳します。

後は、気になった文字を選択するだけです
文章の選択も可能です。
以下のようにります。


うまく翻訳出来ない場合もあるのでご了承ください。
Textプロパティから取得設定しているので一気に選択すると、画像が無くなったりレイアウトが崩れる場合もあります。
機能としては選択した文字をAJAX Language APIに渡してるだけなので、場合によってはそこそこ面白い事になるかも。


ソースは

/*
	@author: con_mame
	@url: http://d.hatena.ne.jp/con_mame/
	@title: Translate Text mini
	@description: Translate Selected Word
	@version: 0.2
*/

(function(){
	jetpack.future.import("selection");

	const API_URL = "http://ajax.googleapis.com/ajax/services/language/translate";
	const JAPAN_FLAG = "data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAPAKAADwCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQkJMAgICFMICAhQCAgIUAgICFAHBwdQBwcHUAcHB1AHBwdQBwcHUAcHB1AHBwdQBwcHUAcHB1AICAhTBAQENa6urt7Dw8P7wcHB+sHBwfrBwcH6wMDA+r+/v/q+vr76vb29+ru7u/q5ubn6t7e3+rW1tfqzs7P6srKy/D8/P5LKysrt7u7u/+zs7P/t7e3/7Ozt//Dv7P/39Or/+PXo//Xy5v/t6+X/4+Pj/+Dg4f/d3d3/29vb/9bW1v9HR0eTx8fH6evr6//p6en/6enp//Du6P/c4Or/mq3w/3yV8v+DmvD/t8Ho/+jm3//e3tz/2dna/9jY2P/T09P/RkZGksnJyenu7u7/7Ozs//Px7P/W2+7/Rm77/w5D//8HPP//BDr//xFD/v+MoO3/6OXe/9zc3P/a2tr/1tbW/0hISJLMzMzp8fHx//Hx7//z8/D/Z4j6/xRJ//8fUP//HE3//xdJ//8MQP//E0T+/7nC5//l493/3Nzc/9jY2P9JSUmSz8/P6fT09P/49vL/1971/zBg//8mV///JVb//yFS//8dTv//GUv//wY7//9wi/L/6+ne/97d3f/Z2dn/SUlJktHR0en39/f/+/r1/9Tc9/80ZP//LF3//ypb//8mV///IlP//x9Q//8MQf//a4jz/+vp3//f397/2tra/0lJSZLT09Pp+Pj4//v6+P/w8/n/Vn7//y1f//8xYf//LFz//yhZ//8jVP//GUz//6Cx7v/r6eH/39/f/9vb2/9LS0uS1tbW6fn5+f/5+fn////8/8TS/f81Zv//Ll///y9g//8pW///Gk///2KE+P/p6Ob/5OTi/+Dg4P/b29v/TExMktfX1+n5+fn/+fn5//39/f////z/r8L7/1qB/f9Cb/7/RnH9/3KR+P/a3ur/6+nl/+Li4v/g4OD/3Nzc/0xMTJLZ2dnp+fn5//n5+f/7+/v/+/v7///++P/z9Pb/5+r0/+fp8f/x8Oz/7u3p/+bm5v/i4uP/4ODg/93d3f9MTEyT39/f+P7+/v/+/v7//v7+//7+/v/9/fz//f37//z7+P/6+fb/9fX0//Hx8f/t7e3/6enp/+bm5v/m5ub/VFRUl5eXl29lZWV8ZGRkemNjY3piYmJ6YmJiemFhYXpgYGB6X19fel5eXnpdXV16XFxceltbW3paWlp6X19ffyoqKjoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAA";
	const USA_FLAG = "data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAPAKAADwCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEPNwAAD1wAAA5YAAAOWAAADlgAAA1YAAANWAAADVgAAAxYAAAMWAAAC1gAAAtYAAAKWAAAClgAAApbAAAFPhhC6+szXuz/NV7r/zRc6f8wWOj/K1Pm/yZO5v8jSeT/HkXj/xpB4f8VPN//Ejfe/w4y2/8JLtn/Bifa/wIETauns9/zyNP1/8TQ8f/Czu//v8zv/7zI7f+4xez/tcHr/7K/6f+uvOj/rLnn/6i35v+ls+T/o7Lk/6Sx5/8+PlOpWXju8H2d+f99nPf/e5r2/3eW9f9xkfX/bI30/2iI9P9jhPP/Xn/y/1p78v9Vd/H/UHLw/0xv8f9KafL/HB1RqKCt3vDAzfP/vMnv/7rI7v+4xOz/tMHr/7G+6v+uu+n/q7jn/6i25f+ls+T/orDj/56t4f+cq+L/nqvk/zw8U6hXePnweZ7//3me//93nP//cpf//22T//9ojf//Zor7/2WF9P9ggvP/XHzz/1d48v9SdPH/UHDx/1Fs8/8fIFOo0b6v8O7dyv/p18P/5tTA/+TQvf/hzbr/4s23/87Gyv+tu+r/q7jo/6i15/+lsuX/oq/k/6Ct4/+jrub/Pz9UqMpoEfDqn0L/5JhA/+GPNP/ekDz/3ZNF/9+MM/+4gl3/gJz1/36X8v96k+//do/v/3KM7f9vie7/cYbw/ystVajNag3w7aRI/+ecRf/klTf/4ZZA/+GZSf/ikjj/uINd/3mX9f93k/L/dI7w/2+L8P9rh+7/aYTv/2yB8f8qK1So0nYb8PCvWP/qqFj/555F/+WaQf/jnE3/5JdB/8iQX/+htPL/nrHv/5yt7f+Yquz/lafr/5Kk6v+Xpe7/OzxXqNV2E/Dzq0f/7KNF/+qaNf/nmDb/5ZpB/+eVM//EjVz/j6j0/46k8v+Loe//h53u/4OZ7v+Bl+3/hJbw/zQ1VqjafBjw9rpi//KyXf/vqUv/7KhQ/+qsXv/spkz/y5dj/5qw9v+XrfT/k6ny/5Cl8P+MofD/iZ/w/4ue9P83N1ip44AT//+vP//8pzn/+Z8s//abLP/znTX/+pso/7OAZ/8/a///Pmf//zlj//80Xv//L1n//ypV//8oTP//DxFZr5hXF3hmOxGAZDkQgGM3D4BhNg+AYDMOgGM0CoBAKS+ABxdtgAkXaoAJFmeACRRkgAgSYYAHEF6ACA5ggAQFKkYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+BAP//CAAAAFkDAABZAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAANT+AATU////DPg";

	var lang = "off";

	jetpack.selection.onSelection(function() {
		if(lang == "off") return;

		var selectedElement = jetpack.selection;
		var langPair = (lang == "ja") ? "en":"ja";
		langPair += "|" + lang;

		$.getJSON(API_URL,{"v": "1.0", "q": selectedElement.text, "langpair": langPair} ,function(result){
			if(result.responseData == null || result.responseData == ""){
				jetpack.notifications.show({
					title: "Not Found",
					body: "Can not Translate"
				});
				return;
			}
			selectedElement.text = result.responseData.translatedText;
		});
	});

	jetpack.statusBar.append({
		html: <>
			<span id="language"><input type="radio" name="language" value="ja" checked="checked"/><img src={JAPAN_FLAG} /><input type="radio" name="language" value="en"/><img src={USA_FLAG} /><input type="radio" name="language" value="off"/><b>OFF</b></span>
		</>,
		onReady: function(doc){
			$("#language", doc).css({
				position: "absolute",
				paddingTop: "3px",
				fontSize: "14px"
			});
			$(":radio", doc).change(function(){
				lang = $(":radio:checked", doc).val();
			});
		},
		width: 150
	});
})();