Add files via upload
29
simple-translate/_locales/en/messages.json
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"extName": {
|
||||||
|
"message": "Simple Translate"
|
||||||
|
},
|
||||||
|
"extDescription": {
|
||||||
|
"message": "View translations easily as you browse the web."
|
||||||
|
},
|
||||||
|
"initialTextArea":{
|
||||||
|
"message": "Enter text"
|
||||||
|
},
|
||||||
|
"showLink":{
|
||||||
|
"message": "Translate this page"
|
||||||
|
},
|
||||||
|
"LangListLabel":{
|
||||||
|
"message":"Destination language"
|
||||||
|
},
|
||||||
|
"langList":{
|
||||||
|
"message":"<option value=\"is\">Icelandic</option><option value=\"ga\">Irish</option><option value=\"az\">Azerbaijani</option><option value=\"af\">Afrikaans</option><option value=\"am\">Amharic</option><option value=\"ar\">Arabic</option><option value=\"sq\">Albanian</option><option value=\"hy\">Armenian</option><option value=\"it\">Italian</option><option value=\"yi\">Yiddish</option><option value=\"ig\">Igbo</option><option value=\"id\">Indonesian</option><option value=\"cy\">Welsh</option><option value=\"uk\">Ukrainian</option><option value=\"uz\">Uzbek</option><option value=\"ur\">Urdu</option><option value=\"et\">Estonian</option><option value=\"eo\">Esperanto</option><option value=\"nl\">Dutch</option><option value=\"kk\">Kazakh</option><option value=\"ca\">Catalan</option><option value=\"gl\">Galician</option><option value=\"kn\">Kannada</option><option value=\"el\">Greek language</option><option value=\"ky\">Kirghiz</option><option value=\"gu\">Gujarati</option><option value=\"km\">Khmer</option><option value=\"ku\">Kurdish</option><option value=\"hr\">Croatian</option><option value=\"xh\">Xosa</option><option value=\"co\">Corsican</option><option value=\"sm\">Samoan</option><option value=\"jv\">Javanese</option><option value=\"ka\">Georgian</option><option value=\"sn\">Shona</option><option value=\"sd\">Sindhi</option><option value=\"si\">Sinhala</option><option value=\"sv\">Swedish</option><option value=\"zu\">Zulu</option><option value=\"gd\">Scottish Gaelic</option><option value=\"es\">Spanish</option><option value=\"sk\">Slovak</option><option value=\"sl\">Slovenian</option><option value=\"sw\">Swahili</option><option value=\"su\">Sundanese</option><option value=\"ceb\">Cebuano</option><option value=\"sr\">Serbian</option><option value=\"sx\">Sotho</option><option value=\"so\">Somali</option><option value=\"th\">Thai</option><option value=\"tl\">Tagalog</option><option value=\"tg\">Tajiki</option><option value=\"ta\">Tamil</option><option value=\"cs\">Czech</option><option value=\"ny\">Chewa</option><option value=\"te\">Telugu</option><option value=\"da\">Danish</option><option value=\"de\">German</option><option value=\"tr\">Turkish</option><option value=\"ne\">Nepali</option><option value=\"no\">Norwegian</option><option value=\"ht\">Haitian</option><option value=\"ha\">Hausa</option><option value=\"ps\">Pushto</option><option value=\"eu\">Basque</option><option value=\"haw\">Hawaiian</option><option value=\"hu\">Hungarian</option><option value=\"pa\">Punjabi</option><option value=\"hi\">Hindi</option><option value=\"fi\">Finnish</option><option value=\"fr\">French</option><option value=\"fy\">Frisian</option><option value=\"bg\">Bulgarian</option><option value=\"vi\">Vietnamese</option><option value=\"he\">Hebrew</option><option value=\"be\">Belarusian</option><option value=\"fa\">Persian</option><option value=\"bn\">Bengali</option><option value=\"pl\">Polish</option><option value=\"bs\">Bosnian</option><option value=\"pt\">Portuguese</option><option value=\"mi\">Maori</option><option value=\"mk\">Macedonian</option><option value=\"mr\">Marathi</option><option value=\"mg\">Malagasy</option><option value=\"ml\">Malayalam</option><option value=\"mt\">Maltese</option><option value=\"ms\">Malay</option><option value=\"my\">Myanmar</option><option value=\"mn\">Mongolian</option><option value=\"hmn\">Monk</option><option value=\"yo\">Yoruba</option><option value=\"lo\">Laotian</option><option value=\"la\">Latin</option><option value=\"lv\">Latvian</option><option value=\"lt\">Lithuanian</option><option value=\"ro\">Romanian</option><option value=\"lb\">Luxembourgish</option><option value=\"ru\">Russian</option><option value=\"en\">English</option><option value=\"ko\">Korean</option><option value=\"zh-CN\">Chinese (PRC)</option><option value=\"zh-TW\">Chinese (Taiwan)</option><option value=\"ja\">Japanese</option>"
|
||||||
|
},
|
||||||
|
"ifShowButtonLabel":{
|
||||||
|
"message": "Pop up a button when selecting text"
|
||||||
|
},
|
||||||
|
"ifCheckLangLabel":{
|
||||||
|
"message": "Do not display the button if the selected text is the same as the destination language"
|
||||||
|
},
|
||||||
|
"ifShowMenuLabel":{
|
||||||
|
"message": "Display context menu"
|
||||||
|
}
|
||||||
|
}
|
29
simple-translate/_locales/ja/messages.json
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"extName": {
|
||||||
|
"message": "Simple Translate"
|
||||||
|
},
|
||||||
|
"extDescription": {
|
||||||
|
"message": "シンプルな翻訳を表示するツールです。"
|
||||||
|
},
|
||||||
|
"initialTextArea":{
|
||||||
|
"message": "テキストを入力"
|
||||||
|
},
|
||||||
|
"showLink":{
|
||||||
|
"message": "このページを翻訳"
|
||||||
|
},
|
||||||
|
"LangListLabel":{
|
||||||
|
"message":"翻訳先の言語"
|
||||||
|
},
|
||||||
|
"langList":{
|
||||||
|
"message":"<option value=\"en\">英語</option><option value=\"ko\">韓国語</option><option value=\"zh-CN\">中国語(簡体)</option><option value=\"zh-TW\">中国語(繁体)</option><option value=\"ja\">日本語</option><option value=\"is\">アイスランド語</option><option value=\"ga\">アイルランド語</option><option value=\"az\">アゼルバイジャン語</option><option value=\"af\">アフリカーンス語</option><option value=\"am\">アムハラ語</option><option value=\"ar\">アラビア語</option><option value=\"sq\">アルバニア語</option><option value=\"hy\">アルメニア語</option><option value=\"it\">イタリア語</option><option value=\"yi\">イディッシュ語</option><option value=\"ig\">イボ語</option><option value=\"id\">インドネシア語</option><option value=\"cy\">ウェールズ語</option><option value=\"uk\">ウクライナ語</option><option value=\"uz\">ウズベク語</option><option value=\"ur\">ウルドゥ語</option><option value=\"et\">エストニア語</option><option value=\"eo\">エスペラント語</option><option value=\"nl\">オランダ語</option><option value=\"kk\">カザフ語</option><option value=\"ca\">カタルーニャ語</option><option value=\"gl\">ガリシア語</option><option value=\"kn\">カンナダ語</option><option value=\"el\">ギリシャ語</option><option value=\"ky\">キルギス語</option><option value=\"gu\">グジャラト語</option><option value=\"km\">クメール語</option><option value=\"ku\">クルド語</option><option value=\"hr\">クロアチア語</option><option value=\"xh\">コーサ語</option><option value=\"co\">コルシカ語</option><option value=\"sm\">サモア語</option><option value=\"jw\">ジャワ語</option><option value=\"ka\">ジョージア(グルジア)語</option><option value=\"sn\">ショナ語</option><option value=\"sd\">シンド語</option><option value=\"si\">シンハラ語</option><option value=\"sv\">スウェーデン語</option><option value=\"zu\">ズールー語</option><option value=\"gd\">スコットランド ゲール語</option><option value=\"es\">スペイン語</option><option value=\"sk\">スロバキア語</option><option value=\"sl\">スロベニア語</option><option value=\"sw\">スワヒリ語</option><option value=\"su\">スンダ語</option><option value=\"ceb\">セブアノ語</option><option value=\"sr\">セルビア語</option><option value=\"st\">ソト語</option><option value=\"so\">ソマリ語</option><option value=\"th\">タイ語</option><option value=\"tl\">タガログ語</option><option value=\"tg\">タジク語</option><option value=\"ta\">タミル語</option><option value=\"cs\">チェコ語</option><option value=\"ny\">チェワ語</option><option value=\"te\">テルグ語</option><option value=\"da\">デンマーク語</option><option value=\"de\">ドイツ語</option><option value=\"tr\">トルコ語</option><option value=\"ne\">ネパール語</option><option value=\"no\">ノルウェー語</option><option value=\"ht\">ハイチ語</option><option value=\"ha\">ハウサ語</option><option value=\"ps\">パシュト語</option><option value=\"eu\">バスク語</option><option value=\"haw\">ハワイ語</option><option value=\"hu\">ハンガリー語</option><option value=\"pa\">パンジャブ語</option><option value=\"hi\">ヒンディー語</option><option value=\"fi\">フィンランド語</option><option value=\"fr\">フランス語</option><option value=\"fy\">フリジア語</option><option value=\"bg\">ブルガリア語</option><option value=\"vi\">ベトナム語</option><option value=\"iw\">ヘブライ語</option><option value=\"be\">ベラルーシ語</option><option value=\"fa\">ペルシャ語</option><option value=\"bn\">ベンガル語</option><option value=\"pl\">ポーランド語</option><option value=\"bs\">ボスニア語</option><option value=\"pt\">ポルトガル語</option><option value=\"mi\">マオリ語</option><option value=\"mk\">マケドニア語</option><option value=\"mr\">マラーティー語</option><option value=\"mg\">マラガシ語</option><option value=\"ml\">マラヤーラム語</option><option value=\"mt\">マルタ語</option><option value=\"ms\">マレー語</option><option value=\"my\">ミャンマー語</option><option value=\"mn\">モンゴル語</option><option value=\"hmn\">モン語</option><option value=\"yo\">ヨルバ語</option><option value=\"lo\">ラオ語</option><option value=\"la\">ラテン語</option><option value=\"lv\">ラトビア語</option><option value=\"lt\">リトアニア語</option><option value=\"ro\">ルーマニア語</option><option value=\"lb\">ルクセンブルク語</option><option value=\"ru\">ロシア語</option>"
|
||||||
|
},
|
||||||
|
"ifShowButtonLabel":{
|
||||||
|
"message": "テキスト選択時にボタンを表示する"
|
||||||
|
},
|
||||||
|
"ifCheckLangLabel":{
|
||||||
|
"message": "選択したテキストが翻訳先言語と同じ場合はボタンを表示しない"
|
||||||
|
},
|
||||||
|
"ifShowMenuLabel":{
|
||||||
|
"message": "コンテキストメニューを表示する"
|
||||||
|
}
|
||||||
|
}
|
115
simple-translate/background.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
getSetting();
|
||||||
|
browser.storage.onChanged.addListener(getSetting)
|
||||||
|
|
||||||
|
//設定の読み出し
|
||||||
|
function getSetting() {
|
||||||
|
browser.storage.sync.get(["targetLang", "ifShowButton", "ifCheckLang", "ifShowMenu"], function (value) {
|
||||||
|
if (value.targetLang == undefined) initialSetting(); //初回起動時
|
||||||
|
targetLang = value.targetLang;
|
||||||
|
ifShowButton = value.ifShowButton;
|
||||||
|
ifCheckLang = value.ifCheckLang;
|
||||||
|
ifShowMenu = value.ifShowMenu;
|
||||||
|
if (ifShowMenu) menuCreate();
|
||||||
|
else menuRemove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//設定の初期化 動く?
|
||||||
|
function initialSetting() {
|
||||||
|
switch (browser.i18n.getUILanguage()) { //一部の言語はブラウザの設定に合わせる
|
||||||
|
case "ja":
|
||||||
|
case "zh-CN":
|
||||||
|
case "zh-TW":
|
||||||
|
case "ko":
|
||||||
|
targetLang = browser.i18n.getUILanguage();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
targetLang = "en";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
browser.storage.sync.set({
|
||||||
|
'targetLang': targetLang,
|
||||||
|
'ifShowButton': true,
|
||||||
|
'ifCheckLang': true,
|
||||||
|
'ifShowMenu': true
|
||||||
|
}, function () {
|
||||||
|
getSetting();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//メニューを表示
|
||||||
|
function menuCreate() {
|
||||||
|
browser.contextMenus.create({
|
||||||
|
id: "translateText",
|
||||||
|
title: "選択したテキストを翻訳",
|
||||||
|
contexts: ["selection"],
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.contextMenus.create({
|
||||||
|
id: "translatePage",
|
||||||
|
title: "ページ全体を翻訳",
|
||||||
|
contexts: ["all"],
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.contextMenus.create({
|
||||||
|
id: "translateLink",
|
||||||
|
title: "選択したリンクを翻訳",
|
||||||
|
contexts: ["link"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//メニューを削除
|
||||||
|
function menuRemove() {
|
||||||
|
browser.contextMenus.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//メニュークリック時
|
||||||
|
browser.contextMenus.onClicked.addListener(function (info, tab) {
|
||||||
|
switch (info.menuItemId) {
|
||||||
|
case "translateText":
|
||||||
|
translateTextMenu(info, tab);
|
||||||
|
break;
|
||||||
|
case "translatePage":
|
||||||
|
translatePageMenu(info, tab);
|
||||||
|
break;
|
||||||
|
case "translateLink":
|
||||||
|
translateLinkMenu(info, tab);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//テキストを翻訳
|
||||||
|
function translateTextMenu(info, tab) {
|
||||||
|
browser.tabs.sendMessage(
|
||||||
|
tab.id, {
|
||||||
|
message: "showPanelFromMenu"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//ページ全体を翻訳
|
||||||
|
function translatePageMenu(info, tab) {
|
||||||
|
browser.tabs.create({
|
||||||
|
'url': "https://translate.google.co.jp/translate?hl=" + targetLang + "&sl=auto&u=" + encodeURIComponent(info.pageUrl),
|
||||||
|
'active': true,
|
||||||
|
'index': tab.index + 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//リンクを翻訳
|
||||||
|
function translateLinkMenu(info, tab) {
|
||||||
|
browser.tabs.create({
|
||||||
|
'url': "https://translate.google.co.jp/translate?hl=" + targetLang + "&sl=auto&u=" + encodeURIComponent(info.linkUrl),
|
||||||
|
'active': true,
|
||||||
|
'index': tab.index + 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//スクリプトからのメッセージに返信
|
||||||
|
browser.runtime.onMessage.addListener(function (request) {
|
||||||
|
switch (request.message) {
|
||||||
|
case "getSetting":
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
BIN
simple-translate/icons/128.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
simple-translate/icons/16.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
simple-translate/icons/19.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
simple-translate/icons/256.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
simple-translate/icons/32.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
simple-translate/icons/38.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
simple-translate/icons/48.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
simple-translate/icons/512.png
Normal file
After Width: | Height: | Size: 1 MiB |
BIN
simple-translate/icons/64.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
simple-translate/icons/icon.tif
Normal file
BIN
simple-translate/langage.xlsx
Normal file
|
@ -1,20 +1,58 @@
|
||||||
{
|
{
|
||||||
|
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Simple Translate",
|
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
|
|
||||||
"description": "Adds a red border to all webpages matching mozilla.org.",
|
"name": "__MSG_extName__",
|
||||||
|
"description": "__MSG_extDescription__",
|
||||||
|
"default_locale": "en",
|
||||||
|
|
||||||
|
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "addon@example.com",
|
||||||
|
"update_url": "https://example.com/updates.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"permissions": ["<all_urls>", "storage", "contextMenus"],
|
||||||
|
|
||||||
|
"options_ui": {
|
||||||
|
"page": "options/options.html"
|
||||||
|
},
|
||||||
|
|
||||||
"icons": {
|
"icons": {
|
||||||
"48": "icons/border-48.png"
|
"512": "icons/512.png",
|
||||||
|
"128": "icons/128.png",
|
||||||
|
"64": "icons/64.png",
|
||||||
|
"48": "icons/48.png",
|
||||||
|
"32": "icons/32.png"
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"]
|
||||||
|
},
|
||||||
|
|
||||||
|
"browser_action": {
|
||||||
|
"default_icon": {
|
||||||
|
"512": "icons/512.png",
|
||||||
|
"128": "icons/128.png",
|
||||||
|
"64": "icons/64.png",
|
||||||
|
"48": "icons/48.png",
|
||||||
|
"38": "icons/38.png",
|
||||||
|
"32": "icons/32.png",
|
||||||
|
"19": "icons/19.png",
|
||||||
|
"16": "icons/16.png"
|
||||||
|
},
|
||||||
|
"default_popup": "popup/popup.html"
|
||||||
},
|
},
|
||||||
|
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["<all_urls>"],
|
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
|
||||||
|
"css": ["simple-translate.css"],
|
||||||
"js": ["simple-translate.js"]
|
"js": ["simple-translate.js"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
28
simple-translate/options/options.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
<label id=targetLangLabel>翻訳先の言語:</label>
|
||||||
|
<select id="targetLang"></select>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" name="ifShowButton" value="1">
|
||||||
|
<label id=ifShowButtonLabel>テキスト選択時にボタンを表示する</label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" name="ifCheckLang" value="1">
|
||||||
|
<label id=ifCheckLangLabel>選択したテキストが翻訳先言語と同じ時はボタンを表示しない</label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" name="ifShowMenu" value="1">
|
||||||
|
<label id=ifShowMenuLabel>コンテキストメニューを表示する</label>
|
||||||
|
</p>
|
||||||
|
<script type="text/javascript" src="options.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
32
simple-translate/options/options.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
var targetLang = document.getElementById("targetLang");
|
||||||
|
var ifShowButton = document.getElementsByName("ifShowButton").item(0);
|
||||||
|
var ifCheckLang = document.getElementsByName("ifCheckLang").item(0);
|
||||||
|
var ifShowMenu = document.getElementsByName("ifShowMenu").item(0);
|
||||||
|
|
||||||
|
targetLang.innerHTML=browser.i18n.getMessage("langList");
|
||||||
|
document.getElementById("targetLangLabel").innerHTML=browser.i18n.getMessage("langListLabel");
|
||||||
|
document.getElementById("ifShowButtonLabel").innerHTML=browser.i18n.getMessage("ifShowButtonLabel");
|
||||||
|
document.getElementById("ifCheckLangLabel").innerHTML=browser.i18n.getMessage("ifCheckLangLabel");
|
||||||
|
document.getElementById("ifShowMenuLabel").innerHTML=browser.i18n.getMessage("ifShowMenuLabel");
|
||||||
|
|
||||||
|
//設定を読み込んで反映
|
||||||
|
browser.storage.sync.get(["targetLang", "ifShowButton", "ifCheckLang", "ifShowMenu"], function (value) {
|
||||||
|
targetLang.value = value.targetLang;
|
||||||
|
ifShowButton.checked=value.ifShowButton;
|
||||||
|
ifCheckLang.checked=value.ifCheckLang;
|
||||||
|
ifShowMenu.checked=value.ifShowMenu;
|
||||||
|
});
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
browser.storage.sync.set({
|
||||||
|
'targetLang': targetLang.value,
|
||||||
|
'ifShowButton': ifShowButton.checked,
|
||||||
|
'ifCheckLang': ifCheckLang.checked,
|
||||||
|
'ifShowMenu': ifShowMenu.checked
|
||||||
|
}, function () {});
|
||||||
|
}
|
||||||
|
|
||||||
|
targetLang.addEventListener("change", save);
|
||||||
|
ifShowButton.addEventListener("change", save);
|
||||||
|
ifCheckLang.addEventListener("change", save);
|
||||||
|
ifShowMenu.addEventListener("change", save);
|
|
@ -1,6 +1,70 @@
|
||||||
#button {
|
body {
|
||||||
width: 20px;
|
font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', 'Meiryo', 'メイリオ', 'Osaka', 'MS PGothic', 'arial', 'helvetica', 'sans-serif';
|
||||||
height: 20px;
|
text-align: left;
|
||||||
background-color: steelblue;
|
font-size: 13px;
|
||||||
|
height: auto;
|
||||||
|
width: 300px;
|
||||||
|
padding: 5px 20px 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main{
|
||||||
|
margin: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
size: 1;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', 'Meiryo', 'メイリオ', 'Osaka', 'MS PGothic', 'arial', 'helvetica', 'sans-serif';
|
||||||
|
text-align: left;
|
||||||
|
font-size: 13px;
|
||||||
|
resize: none;
|
||||||
|
overflow: auto;
|
||||||
|
max-height: 250px;
|
||||||
|
height: 30px;
|
||||||
|
width: 277px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#link a {
|
||||||
|
font-style: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #4268da;
|
||||||
|
}
|
||||||
|
|
||||||
|
#distination {
|
||||||
|
color: #aaa;
|
||||||
|
max-height: 250px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#target {
|
||||||
|
max-height: 250px;
|
||||||
|
overflow-y: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#link {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#langList {
|
||||||
|
font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', 'Meiryo', 'メイリオ', 'Osaka', 'MS PGothic', 'arial', 'helvetica', 'sans-serif';
|
||||||
|
text-align: left;
|
||||||
|
font-size: 13px;
|
||||||
|
float: right;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
max-width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-selection {
|
||||||
|
background: #ebebeb;
|
||||||
}
|
}
|
|
@ -4,11 +4,23 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" href="popup.css">
|
<link rel="stylesheet" type="text/css" href="popup.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id=button></div>
|
<div id=main>
|
||||||
|
<form>
|
||||||
|
<textarea id=textarea spellcheck=false></textarea>
|
||||||
|
</form>
|
||||||
|
<hr>
|
||||||
|
<div id=target>
|
||||||
|
<p></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<select id="langList"></select>
|
||||||
|
<div id=link></div>
|
||||||
|
|
||||||
|
<script src="popup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
138
simple-translate/popup/popup.js
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
let target = document.getElementById("target");
|
||||||
|
let langList = document.getElementById("langList");
|
||||||
|
let textarea = document.getElementById("textarea");
|
||||||
|
|
||||||
|
const initialText = browser.i18n.getMessage("initialTextArea");
|
||||||
|
langList.innerHTML = browser.i18n.getMessage("langList");
|
||||||
|
textarea.innerText = initialText;
|
||||||
|
|
||||||
|
let targetLang;
|
||||||
|
let sourceWord = "";
|
||||||
|
|
||||||
|
browser.storage.onChanged.addListener(getTargetLang);
|
||||||
|
getTargetLang(); //翻訳先言語初期化
|
||||||
|
//設定を読み出し
|
||||||
|
function getTargetLang() {
|
||||||
|
browser.storage.sync.get("targetLang", function (value) {
|
||||||
|
targetLang = value.targetLang;
|
||||||
|
langList.value = targetLang; //リスト初期値をセット
|
||||||
|
langList.addEventListener("change", changeLang);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳先言語変更時に更新
|
||||||
|
function changeLang() {
|
||||||
|
targetLang = langList.value;
|
||||||
|
if (sourceWord !== "") {
|
||||||
|
removeResult();
|
||||||
|
splitLine();
|
||||||
|
}
|
||||||
|
if (url !== "") showLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
//アクティブなタブを取得して渡す
|
||||||
|
browser.tabs.query({
|
||||||
|
currentWindow: true,
|
||||||
|
active: true
|
||||||
|
}).then(function (tabs) {
|
||||||
|
getSelectionWord(tabs);
|
||||||
|
});
|
||||||
|
|
||||||
|
//アクティブタブから選択文字列とurlを取得
|
||||||
|
function getSelectionWord(tabs) {
|
||||||
|
for (let tab of tabs) {
|
||||||
|
browser.tabs.sendMessage(
|
||||||
|
tab.id, {
|
||||||
|
message: "fromPopup"
|
||||||
|
}
|
||||||
|
).then(response => {
|
||||||
|
sourceWord = response.word;
|
||||||
|
url = response.url;
|
||||||
|
refleshSource();
|
||||||
|
showLink();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ページ翻訳へのリンクを表示
|
||||||
|
function showLink() {
|
||||||
|
document.getElementById("link").innerHTML = "<a href=https://translate.google.co.jp/translate?hl=" + targetLang + "&sl=auto&u=" + encodeURIComponent(url) + ">" + browser.i18n.getMessage('showLink') + "</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳元テキストを表示
|
||||||
|
function refleshSource() {
|
||||||
|
if (sourceWord !== "") {
|
||||||
|
textarea.innerHTML = sourceWord;
|
||||||
|
translate();
|
||||||
|
resize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea.addEventListener("keydown", resize);
|
||||||
|
//テキストボックスをリサイズ
|
||||||
|
function resize() {
|
||||||
|
setTimeout(function () {
|
||||||
|
textarea.style.height = "0px";
|
||||||
|
textarea.style.height = parseInt(textarea.scrollHeight) + "px";
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//テキストエリアクリック時の処理
|
||||||
|
textarea.addEventListener("click", textAreaClick, {
|
||||||
|
once: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function textAreaClick() {
|
||||||
|
if (textarea.value == initialText) {
|
||||||
|
textarea.value = "";
|
||||||
|
} else {
|
||||||
|
textarea.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea.addEventListener("keyup", inputText);
|
||||||
|
//文字入力時の処理
|
||||||
|
function inputText() {
|
||||||
|
sourceWord = textarea.value;
|
||||||
|
translate();
|
||||||
|
}
|
||||||
|
|
||||||
|
//改行で分割してgetRequestに渡す
|
||||||
|
function translate() {
|
||||||
|
let promises = [];
|
||||||
|
sourceLine = sourceWord.split("\n");
|
||||||
|
for (i = 0; i < sourceLine.length; i++) {
|
||||||
|
promises.push(getRequest(sourceLine[i]));
|
||||||
|
}
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(function (results) {
|
||||||
|
showResult(results); //翻訳結果が帰ってきたらshowResult
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳リクエストを送信,取得して返す
|
||||||
|
function getRequest(word) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
let url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=" + targetLang + "&dt=t&q=" + encodeURIComponent(word);
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.send();
|
||||||
|
xhr.onload = function () {
|
||||||
|
resolve(xhr);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳結果を表示
|
||||||
|
function showResult(results) {
|
||||||
|
target.innerText = "";
|
||||||
|
let resultText = "";
|
||||||
|
for (let j = 0; j < results.length; j++) {
|
||||||
|
for (let i = 0; i < results[j].response[0].length; i++) {
|
||||||
|
resultText += results[j].response[0][i][0];
|
||||||
|
}
|
||||||
|
resultText += "\n"; //
|
||||||
|
}
|
||||||
|
target.innerText = resultText;
|
||||||
|
}
|
78
simple-translate/simple-translate.css
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#simple-translate-button {
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
||||||
|
border-radius: 3px;
|
||||||
|
background-image: url("icons/16.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
height: 22px;
|
||||||
|
width: 22px;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 151;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
display: none;
|
||||||
|
cursor: pointer;
|
||||||
|
animation-duration: 200ms;
|
||||||
|
animation-name: showButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
#simple-translate-panel {
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', Meiryo, メイリオ, Osaka, 'MS PGothic', arial, helvetica, sans-serif;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 13px;
|
||||||
|
/*opacity: 0;*/
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
||||||
|
border-radius: 3px;
|
||||||
|
min-height: 20px;
|
||||||
|
max-height: 200px;
|
||||||
|
line-height: 150%;
|
||||||
|
height: auto;
|
||||||
|
min-width: 10px;
|
||||||
|
max-width: 300px;
|
||||||
|
width:300px;/*消すかも*/
|
||||||
|
position: fixed;
|
||||||
|
padding: 10px 18px;
|
||||||
|
z-index: 150;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
display: none;
|
||||||
|
overflow-y: auto;
|
||||||
|
/*
|
||||||
|
transition-property: height, width, opacity;
|
||||||
|
transition-timing-function: ease-out;
|
||||||
|
transition-duration: 400ms;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#simple-translate-panel p {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
transition-duration: 200ms;
|
||||||
|
animation-name: fadein;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes showButton {
|
||||||
|
0% {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale3d(1.1, 1.1, 1.1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale3d(1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadein {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#simple-translate-panel p::-moz-selection {
|
||||||
|
background: #ebebeb;
|
||||||
|
}
|
|
@ -1,41 +1,180 @@
|
||||||
var style = document.createElement("style");
|
document.body.insertAdjacentHTML("beforeend", "<div id='simple-translate-button'></div><div id='simple-translate-panel'><p>...</p></div><div id='simple-translate-popup'></div>"); //body末尾にボタン配置
|
||||||
style.setAttribute("type", "text/css");
|
|
||||||
style.innerHTML = "" +
|
|
||||||
"#simple-translate-button {" +
|
|
||||||
"background-color :rgba(87, 199, 232, 0.6);" +
|
|
||||||
"height :20px;" +
|
|
||||||
"width :20px;" +
|
|
||||||
"position :fixed;" +
|
|
||||||
"z-index: 150;" +
|
|
||||||
"left :0px;" +
|
|
||||||
"top :0px;" +
|
|
||||||
"display :none;" +
|
|
||||||
"cursor :pointer;" +
|
|
||||||
"}";
|
|
||||||
document.getElementsByTagName("head")[0].appendChild(style); //headに上記スタイルを追記
|
|
||||||
document.body.insertAdjacentHTML("beforeend", "<div id='simple-translate-button'></div>"); //body末尾にボタン配置
|
|
||||||
|
|
||||||
var button = document.getElementById("simple-translate-button");
|
var button = document.getElementById("simple-translate-button");
|
||||||
|
var panel = document.getElementById("simple-translate-panel");
|
||||||
|
var popup = document.getElementById("simple-translate-popup");
|
||||||
var selectionWord;
|
var selectionWord;
|
||||||
|
var clickPosition;
|
||||||
|
|
||||||
function showPanel() {
|
var targetLang;
|
||||||
console.log(selectionWord);
|
var ifShowButton;
|
||||||
}
|
var ifCheckLang;
|
||||||
|
|
||||||
function popupButton(e) {
|
//設定を読み出し
|
||||||
button.style.display = 'block';
|
getSetting();
|
||||||
button.style.left = e.clientX + 20 + 'px';
|
browser.storage.onChanged.addListener(getSetting);
|
||||||
button.style.top = e.clientY + 0 + 'px';
|
|
||||||
|
function getSetting() {
|
||||||
|
browser.storage.sync.get(["targetLang", "ifShowButton", "ifCheckLang"], function (value) {
|
||||||
|
targetLang = value.targetLang;
|
||||||
|
ifShowButton = value.ifShowButton;
|
||||||
|
ifCheckLang = value.ifCheckLang;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener("mouseup", Select, false);
|
||||||
|
//テキスト選択時の処理
|
||||||
function Select(e) {
|
function Select(e) {
|
||||||
button.style.display = 'none'; //マウスクリックでボタンを非表示に
|
hidePanel(e);
|
||||||
setTimeout(function () { //誤動作防止の為ディレイを設ける
|
setTimeout(function () { //誤動作防止の為ディレイを設ける
|
||||||
selectionWord = String(window.getSelection());
|
selectionWord = String(window.getSelection());
|
||||||
if (selectionWord.length !== 0 && e.button == 0) { //選択範囲が存在かつ左クリックのとき
|
if ((selectionWord.length !== 0) && (e.button == 0) && (e.target.id !== "simple-translate-panel") && (e.target.parentElement.id !== "simple-translate-panel")) { //選択範囲が存在かつ左クリックかつパネル以外のとき
|
||||||
popupButton(e);
|
if (ifCheckLang) {
|
||||||
|
checkLang().then(function (results) {
|
||||||
|
if (results) popupButton(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
popupButton(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
//選択テキストの言語をチェックして返す
|
||||||
|
function checkLang() {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
getRequest(selectionWord.substr(0, 100)) //先頭100文字を抽出
|
||||||
|
.then(function (results) {
|
||||||
|
let lang = results.response[2];
|
||||||
|
let percentage = results.response[6];
|
||||||
|
//console.log(lang, percentage, lang!=targetLang && percentage>0);
|
||||||
|
resolve(lang != targetLang && percentage > 0); //真偽値を返す
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//ボタンを表示
|
||||||
|
function popupButton(e) {
|
||||||
|
button.style.left = e.clientX + 10 + 'px';
|
||||||
|
button.style.top = e.clientY + 5 + 'px';
|
||||||
|
if (ifShowButton) {
|
||||||
|
button.style.display = 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.addEventListener("click", function (e) {
|
||||||
|
translate();
|
||||||
|
showPanel(e);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
//改行で分割してgetRequestに渡す
|
||||||
|
function translate() {
|
||||||
|
promises = [];
|
||||||
|
sourceLine = selectionWord.split("\n");
|
||||||
|
for (i = 0; i < sourceLine.length; i++) {
|
||||||
|
promises.push(getRequest(sourceLine[i]));
|
||||||
|
}
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(function (results) {
|
||||||
|
showResult(results); //翻訳結果が帰ってきたらshowResult
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳リクエストを送信,取得して返す
|
||||||
|
function getRequest(word) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
let url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=" + targetLang + "&dt=t&q=" + encodeURIComponent(word);
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.send();
|
||||||
|
xhr.onload = function () {
|
||||||
|
resolve(xhr);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//翻訳結果を表示
|
||||||
|
function showResult(results) {
|
||||||
|
panel.innerText = "";
|
||||||
|
let resultText = "";
|
||||||
|
for (let j = 0; j < results.length; j++) {
|
||||||
|
for (let i = 0; i < results[j].response[0].length; i++) {
|
||||||
|
resultText += results[j].response[0][i][0];
|
||||||
|
}
|
||||||
|
resultText += "\n"; //
|
||||||
|
}
|
||||||
|
panel.innerHTML = "<p></p>"
|
||||||
|
panel.getElementsByTagName("p")[0].innerText = resultText;
|
||||||
|
panelPosition(clickPosition);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//パネル表示
|
||||||
|
function showPanel(e) {
|
||||||
|
clickPosition = e;
|
||||||
|
panel.style.display = 'block';
|
||||||
|
panelPosition(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//パネル非表示
|
||||||
|
function hidePanel(e) {
|
||||||
|
button.style.display = 'none'; //ボタンを非表示
|
||||||
|
if ((e.target.id !== "simple-translate-panel") && (e.target.parentElement.id !== "simple-translate-panel")) { //パネル以外の場所をクリックでパネルを非表示
|
||||||
|
panel.style.display = 'none';
|
||||||
|
panel.innerHTML = "<p>...</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//パネルがウィンドウ外にはみ出る時に位置を調整
|
||||||
|
function panelPosition(e) {
|
||||||
|
var p = new Object();
|
||||||
|
panel.style.width = '300px';
|
||||||
|
var panelHeight = panel.clientHeight;
|
||||||
|
var panelWidth = parseInt(window.getComputedStyle(panel.getElementsByTagName("p")[0], null).width);
|
||||||
|
//一旦パネルの横幅を300にしてpの横幅を取得
|
||||||
|
|
||||||
|
if (e.clientX + panelWidth > window.innerWidth - 80) {
|
||||||
|
p.x = window.innerWidth - panelWidth - 80;
|
||||||
|
} else {
|
||||||
|
p.x = e.clientX + 10;
|
||||||
|
}
|
||||||
|
if (e.clientY + panelHeight > window.innerHeight - 30) {
|
||||||
|
p.y = window.innerHeight - panelHeight - 30;
|
||||||
|
} else {
|
||||||
|
p.y = e.clientY + 10;
|
||||||
|
}
|
||||||
|
panel.style.width = 'auto'; //panelWidth + 'px';
|
||||||
|
panel.style.top = p.y + 'px';
|
||||||
|
panel.style.left = p.x + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//スクリプトからのメッセージに返信
|
||||||
|
browser.runtime.onMessage.addListener(function (request) {
|
||||||
|
switch (request.message) {
|
||||||
|
case "fromPopup":
|
||||||
|
return sendToPopup();
|
||||||
|
break;
|
||||||
|
case "showPanelFromMenu":
|
||||||
|
showPanelFromMenu();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//popupにテキストとurlを返す
|
||||||
|
function sendToPopup() {
|
||||||
|
return Promise.resolve({
|
||||||
|
word: String(window.getSelection()),
|
||||||
|
url: window.location.href
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//コンテキストメニュークリックでパネルを表示
|
||||||
|
function showPanelFromMenu() {
|
||||||
|
button.style.display = "none";
|
||||||
|
translate();
|
||||||
|
let event = new Object();
|
||||||
|
event.clientX = parseInt(button.style.left);
|
||||||
|
event.clientY = parseInt(button.style.top);
|
||||||
|
showPanel(event);
|
||||||
}
|
}
|
||||||
window.addEventListener("mouseup", Select, false);
|
|
||||||
button.addEventListener("click", showPanel, false);
|
|