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,
|
||||
"name": "Simple Translate",
|
||||
"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": {
|
||||
"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": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
|
||||
"css": ["simple-translate.css"],
|
||||
"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 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: steelblue;
|
||||
|
||||
body {
|
||||
font-family: 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ Pro W3', 'Meiryo', 'メイリオ', 'Osaka', 'MS PGothic', 'arial', 'helvetica', 'sans-serif';
|
||||
text-align: left;
|
||||
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>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<link rel="stylesheet" type="text/css" href="popup.css">
|
||||
</head>
|
||||
|
||||
<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>
|
||||
|
||||
</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");
|
||||
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末尾にボタン配置
|
||||
|
||||
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末尾にボタン配置
|
||||
var button = document.getElementById("simple-translate-button");
|
||||
var panel = document.getElementById("simple-translate-panel");
|
||||
var popup = document.getElementById("simple-translate-popup");
|
||||
var selectionWord;
|
||||
var clickPosition;
|
||||
|
||||
function showPanel() {
|
||||
console.log(selectionWord);
|
||||
}
|
||||
|
||||
function popupButton(e) {
|
||||
button.style.display = 'block';
|
||||
button.style.left = e.clientX + 20 + 'px';
|
||||
button.style.top = e.clientY + 0 + 'px';
|
||||
var targetLang;
|
||||
var ifShowButton;
|
||||
var ifCheckLang;
|
||||
|
||||
//設定を読み出し
|
||||
getSetting();
|
||||
browser.storage.onChanged.addListener(getSetting);
|
||||
|
||||
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) {
|
||||
button.style.display = 'none'; //マウスクリックでボタンを非表示に
|
||||
hidePanel(e);
|
||||
setTimeout(function () { //誤動作防止の為ディレイを設ける
|
||||
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")) { //選択範囲が存在かつ左クリックかつパネル以外のとき
|
||||
if (ifCheckLang) {
|
||||
checkLang().then(function (results) {
|
||||
if (results) popupButton(e);
|
||||
});
|
||||
} else {
|
||||
popupButton(e);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
window.addEventListener("mouseup", Select, false);
|
||||
button.addEventListener("click", showPanel, false);
|
||||
}, 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);
|
||||
}
|
||||
|
|