Refactor translate

This commit is contained in:
sienori 2022-03-03 16:24:35 +09:00
parent a63bf0f85d
commit 38e52e3a49
8 changed files with 70 additions and 69 deletions

13
package-lock.json generated
View file

@ -1421,6 +1421,14 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"dev": true "dev": true
}, },
"axios": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
"integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
"requires": {
"follow-redirects": "^1.14.8"
}
},
"babel-code-frame": { "babel-code-frame": {
"version": "6.26.0", "version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@ -3232,6 +3240,11 @@
} }
} }
}, },
"follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
},
"forever-agent": { "forever-agent": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",

View file

@ -2,6 +2,7 @@
"name": "simple-translate", "name": "simple-translate",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"axios": "^0.26.0",
"browser-info": "^1.2.0", "browser-info": "^1.2.0",
"loglevel": "^1.6.1", "loglevel": "^1.6.1",
"query-string": "^6.1.0", "query-string": "^6.1.0",

View file

@ -1,17 +0,0 @@
import browser from "webextension-polyfill";
export default statusText => {
let errorMessage = "";
switch (statusText) {
case "Network Error":
errorMessage = browser.i18n.getMessage("networkError");
break;
case "Service Unavailable":
errorMessage = browser.i18n.getMessage("unavailableError");
break;
default:
errorMessage = `${browser.i18n.getMessage("unknownError")} [${statusText}]`;
break;
}
return errorMessage;
};

View file

@ -1,4 +1,5 @@
import log from "loglevel"; import log from "loglevel";
import axios from "axios";
let translationHistory = []; let translationHistory = [];
const logDir = "common/translate"; const logDir = "common/translate";
@ -23,59 +24,62 @@ const setHistory = (sourceWord, sourceLang, targetLang, formattedResult) => {
}); });
}; };
const sendRequest = (word, sourceLang, targetLang) => { const sendRequest = async (word, sourceLang, targetLang) => {
log.log(logDir, "sendRequest()");
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&dt=bd&dj=1&q=${encodeURIComponent( const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&dt=bd&dj=1&q=${encodeURIComponent(
word word
)}`; )}`;
const xhr = new XMLHttpRequest(); const result = await axios.get(url).catch(error => error.response);
xhr.responseType = "json";
xhr.open("GET", url);
xhr.send();
return new Promise((resolve, reject) => {
xhr.onload = () => {
resolve(xhr);
};
xhr.onerror = () => {
resolve(xhr);
};
});
};
const formatResult = result => {
const resultData = { const resultData = {
resultText: "", resultText: "",
candidateText: "", candidateText: "",
sourceLanguage: "", sourceLanguage: "",
percentage: 0, percentage: 0,
statusText: "" isError: false,
errorMessage: ""
}; };
if (result.status === 0) resultData.statusText = "Network Error"; if (!result || result?.status !== 200) {
else if (result.status === 200) resultData.statusText = "OK"; resultData.isError = true;
else if (result.status === 429) resultData.statusText = "Service Unavailable";
else if (result.status === 503) resultData.statusText = "Service Unavailable";
else resultData.statusText = result.statusText || result.status;
if (resultData.statusText !== "OK") { if (!result || result.status === 0) resultData.errorMessage = browser.i18n.getMessage("networkError");
log.error(logDir, "formatResult()", resultData); else if (result.status === 429 || result.status === 503) resultData.errorMessage = browser.i18n.getMessage("unavailableError");
else resultData.errorMessage = `${browser.i18n.getMessage("unknownError")} [${result?.status} ${result?.statusText}]`;
log.error(logDir, "sendRequest()", result);
return resultData; return resultData;
} }
resultData.sourceLanguage = result.response.src; resultData.sourceLanguage = result.data.src;
resultData.percentage = result.response.ld_result.srclangs_confidences[0]; resultData.percentage = result.data.ld_result.srclangs_confidences[0];
resultData.resultText = result.response.sentences.map(sentence => sentence.trans).join(""); resultData.resultText = result.data.sentences.map(sentence => sentence.trans).join("");
if (result.response.dict) { if (result.data.dict) {
resultData.candidateText = result.response.dict resultData.candidateText = result.data.dict
.map(dict => `${dict.pos}${dict.pos != "" ? ": " : ""}${dict.terms.join(", ")}\n`) .map(dict => `${dict.pos}${dict.pos != "" ? ": " : ""}${dict.terms.join(", ")}\n`)
.join(""); .join("");
} }
log.log(logDir, "formatResult()", resultData); log.log(logDir, "sendRequest()", resultData);
return resultData; return resultData;
}; };
const sendRequestToDeepL = async (word, sourceLang, targetLang) => {
log.log(logDir, "sendRequestToDeepL()");
let params = new URLSearchParams();
const key = "f5a2c02c-7871-af5c-0d6a-244a9e6d4a1f:fx";
params.append("auth_key", key);
params.append("text", word);
params.append("target_lang", "ja");
const url = "https://api-free.deepl.com/v2/translate";
const res = await axios.post(url, params).catch(e => e.response);
console.log("!!!!!!!!!!!!!!!", res);
};
export default async (sourceWord, sourceLang = "auto", targetLang) => { export default async (sourceWord, sourceLang = "auto", targetLang) => {
log.log(logDir, "tranlate()", sourceWord, targetLang); log.log(logDir, "tranlate()", sourceWord, targetLang);
sourceWord = sourceWord.trim(); sourceWord = sourceWord.trim();
@ -92,7 +96,6 @@ export default async (sourceWord, sourceLang = "auto", targetLang) => {
if (history) return history.result; if (history) return history.result;
const result = await sendRequest(sourceWord, sourceLang, targetLang); const result = await sendRequest(sourceWord, sourceLang, targetLang);
const formattedResult = formatResult(result); setHistory(sourceWord, sourceLang, targetLang, result);
setHistory(sourceWord, sourceLang, targetLang, formattedResult); return result;
return formattedResult;
}; };

View file

@ -21,8 +21,7 @@ const matchesTargetLang = async selectedText => {
//先頭100字を翻訳にかけて判定 //先頭100字を翻訳にかけて判定
const partSelectedText = selectedText.substring(0, 100); const partSelectedText = selectedText.substring(0, 100);
const result = await translateText(partSelectedText); const result = await translateText(partSelectedText);
const isError = result.statusText !== "OK"; if (result.isError) return false;
if (isError) return false;
const isNotText = result.percentage === 0; const isNotText = result.percentage === 0;
if (isNotText) return true; if (isNotText) return true;
@ -42,7 +41,8 @@ export default class TranslateContainer extends Component {
currentLang: getSettings("targetLang"), currentLang: getSettings("targetLang"),
resultText: "", resultText: "",
candidateText: "", candidateText: "",
statusText: "OK" isError: false,
errorMessage: ""
}; };
this.selectedText = props.selectedText; this.selectedText = props.selectedText;
this.selectedPosition = props.selectedPosition; this.selectedPosition = props.selectedPosition;
@ -98,7 +98,8 @@ export default class TranslateContainer extends Component {
panelPosition: panelPosition, panelPosition: panelPosition,
resultText: result.resultText, resultText: result.resultText,
candidateText: getSettings("ifShowCandidate") ? result.candidateText : "", candidateText: getSettings("ifShowCandidate") ? result.candidateText : "",
statusText: result.statusText, isError: result.isError,
errorMessage: result.errorMessage,
currentLang: shouldSwitchSecondLang ? secondLang : targetLang currentLang: shouldSwitchSecondLang ? secondLang : targetLang
}); });
}; };
@ -122,7 +123,8 @@ export default class TranslateContainer extends Component {
currentLang={this.state.currentLang} currentLang={this.state.currentLang}
resultText={this.state.resultText} resultText={this.state.resultText}
candidateText={this.state.candidateText} candidateText={this.state.candidateText}
statusText={this.state.statusText} isError={this.state.isError}
errorMessage={this.state.errorMessage}
hidePanel={this.hidePanel} hidePanel={this.hidePanel}
/> />
</div> </div>

View file

@ -2,7 +2,6 @@ import browser from "webextension-polyfill";
import React, { Component } from "react"; import React, { Component } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { getSettings } from "src/settings/settings"; import { getSettings } from "src/settings/settings";
import getErrorMessage from "src/common/getErrorMessage";
import "../styles/TranslatePanel.scss"; import "../styles/TranslatePanel.scss";
const splitLine = text => { const splitLine = text => {
@ -163,8 +162,7 @@ export default class TranslatePanel extends Component {
}; };
render = () => { render = () => {
const { shouldShow, selectedText, currentLang, resultText, candidateText, statusText } = this.props; const { shouldShow, selectedText, currentLang, resultText, candidateText, isError, errorMessage } = this.props;
const isError = statusText !== "OK";
const { width, height } = this.state.shouldResize const { width, height } = this.state.shouldResize
? { width: parseInt(getSettings("width")), height: parseInt(getSettings("height")) } ? { width: parseInt(getSettings("width")), height: parseInt(getSettings("height")) }
: { width: this.state.panelWidth, height: this.state.panelHeight }; : { width: this.state.panelWidth, height: this.state.panelHeight };
@ -204,7 +202,7 @@ export default class TranslatePanel extends Component {
</p> </p>
{isError && ( {isError && (
<p className="simple-translate-error" style={candidateStyles}> <p className="simple-translate-error" style={candidateStyles}>
{getErrorMessage(statusText)} {errorMessage}
<br /> <br />
<a <a
href={`https://translate.google.com/?sl=auto&tl=${currentLang}&text=${encodeURIComponent(selectedText)}`} href={`https://translate.google.com/?sl=auto&tl=${currentLang}&text=${encodeURIComponent(selectedText)}`}

View file

@ -40,7 +40,8 @@ export default class PopupPage extends Component {
resultText: "", resultText: "",
candidateText: "", candidateText: "",
sourceLang: "", sourceLang: "",
statusText: "OK", isError: false,
errorMessage: "",
tabUrl: "", tabUrl: "",
isConnected: true, isConnected: true,
isEnabledOnPage: true, isEnabledOnPage: true,
@ -112,8 +113,9 @@ export default class PopupPage extends Component {
this.setState({ this.setState({
resultText: result.resultText, resultText: result.resultText,
candidateText: result.candidateText, candidateText: result.candidateText,
statusText: result.statusText, sourceLang: result.sourceLanguage,
sourceLang: result.sourceLanguage isError: result.isError,
errorMessage: result.errorMessage
}); });
return result; return result;
}; };
@ -174,7 +176,8 @@ export default class PopupPage extends Component {
targetLang={this.state.targetLang} targetLang={this.state.targetLang}
resultText={this.state.resultText} resultText={this.state.resultText}
candidateText={this.state.candidateText} candidateText={this.state.candidateText}
statusText={this.state.statusText} isError={this.state.isError}
errorMessage={this.state.errorMessage}
/> />
<Footer <Footer
tabUrl={this.state.tabUrl} tabUrl={this.state.tabUrl}

View file

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import browser from "webextension-polyfill"; import browser from "webextension-polyfill";
import getErrorMessage from "src/common/getErrorMessage";
import { getSettings } from "src/settings/settings"; import { getSettings } from "src/settings/settings";
import openUrl from "src/common/openUrl"; import openUrl from "src/common/openUrl";
import CopyButton from "./CopyButton"; import CopyButton from "./CopyButton";
@ -13,8 +12,7 @@ const splitLine = text => {
}; };
export default props => { export default props => {
const { resultText, candidateText, statusText, targetLang } = props; const { resultText, candidateText, isError, errorMessage, targetLang } = props;
const isError = statusText !== "OK";
const shouldShowCandidate = getSettings("ifShowCandidate"); const shouldShowCandidate = getSettings("ifShowCandidate");
const handleLinkClick = () => { const handleLinkClick = () => {
@ -28,7 +26,7 @@ export default props => {
<div id="resultArea"> <div id="resultArea">
<p className="resultText" dir="auto">{splitLine(resultText)}</p> <p className="resultText" dir="auto">{splitLine(resultText)}</p>
{shouldShowCandidate && <p className="candidateText" dir="auto">{splitLine(candidateText)}</p>} {shouldShowCandidate && <p className="candidateText" dir="auto">{splitLine(candidateText)}</p>}
{isError && <p className="error">{getErrorMessage(statusText)}</p>} {isError && <p className="error">{errorMessage}</p>}
{isError && ( {isError && (
<p className="translateLink"> <p className="translateLink">
<a onClick={handleLinkClick}>{browser.i18n.getMessage("openInGoogleLabel")}</a> <a onClick={handleLinkClick}>{browser.i18n.getMessage("openInGoogleLabel")}</a>