Sõnaveeb support (only PopupPage yet)

This commit is contained in:
Bohdan Horbeshko 2023-10-12 01:09:02 +03:00
parent 2100449132
commit 7d1cd83de7
7 changed files with 128 additions and 19 deletions

View file

@ -89,6 +89,12 @@
"deeplAuthKeyCaptionLabel": { "deeplAuthKeyCaptionLabel": {
"message": "Enter the authentication key for the DeepL API." "message": "Enter the authentication key for the DeepL API."
}, },
"sonaveebApiLabel": {
"message": "Sõnaveeb API"
},
"sonaveebApiCaptionLabel": {
"message": "Use Sõnaveeb API. No registration is required."
},
"targetLangCaptionLabel": { "targetLangCaptionLabel": {
"message": "Select the default target language." "message": "Select the default target language."
}, },
@ -446,6 +452,9 @@
"deeplAuthError": { "deeplAuthError": {
"message": "Error: Authentication of DeepL API failed. Please set the authentication key and plan correctly on the settings page." "message": "Error: Authentication of DeepL API failed. Please set the authentication key and plan correctly on the settings page."
}, },
"sonaveebWordIdNotFound": {
"message": "Sõnaveeb word id not found"
},
"unknownError": { "unknownError": {
"message": "Error: Unknown error" "message": "Error: Unknown error"
}, },

View file

@ -3,9 +3,15 @@ const alphabeticallySort = (a, b) => a.name.localeCompare(b.name);
const langListGoogle = ["af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jv", "kn", "kk", "km", "rw", "ko", "ku", "ky", "lo", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "or", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "tt", "te", "th", "tr", "tk", "uk", "ur", "ug", "uz", "vi", "cy", "xh", "yi", "yo", "zu"]; const langListGoogle = ["af", "sq", "am", "ar", "hy", "az", "eu", "be", "bn", "bs", "bg", "ca", "ceb", "zh-CN", "zh-TW", "co", "hr", "cs", "da", "nl", "en", "eo", "et", "fi", "fr", "fy", "gl", "ka", "de", "el", "gu", "ht", "ha", "haw", "he", "hi", "hmn", "hu", "is", "ig", "id", "ga", "it", "ja", "jv", "kn", "kk", "km", "rw", "ko", "ku", "ky", "lo", "lv", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mn", "my", "ne", "no", "ny", "or", "ps", "fa", "pl", "pt", "pa", "ro", "ru", "sm", "gd", "sr", "st", "sn", "sd", "si", "sk", "sl", "so", "es", "su", "sw", "sv", "tl", "tg", "ta", "tt", "te", "th", "tr", "tk", "uk", "ur", "ug", "uz", "vi", "cy", "xh", "yi", "yo", "zu"];
const langListDeepl = ["bg", "cs", "da", "de", "el", "en-GB", "en-US", "es", "et", "fi", "fr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt-PT", "pt-BR", "ro", "ru", "sk", "sl", "sv", "tr", "uk", "zh"]; const langListDeepl = ["bg", "cs", "da", "de", "el", "en-GB", "en-US", "es", "et", "fi", "fr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt-PT", "pt-BR", "ro", "ru", "sk", "sl", "sv", "tr", "uk", "zh"];
const langListSonaveeb = ["et"];
export default (translationApi) => { export default (translationApi) => {
const langList = translationApi === "google" ? langListGoogle : langListDeepl; const langList = translationApi === "google"
? langListGoogle
: (translationApi === "deepl"
? langListDeepl
: langListSonaveeb
);
const langOptions = langList.map(lang => ({ const langOptions = langList.map(lang => ({
value: lang, value: lang,
name: browser.i18n.getMessage("lang_" + lang.replace("-", "_")) name: browser.i18n.getMessage("lang_" + lang.replace("-", "_"))

View file

@ -37,6 +37,7 @@ const sendRequestToGoogle = async (word, sourceLang, targetLang) => {
const resultData = { const resultData = {
resultText: "", resultText: "",
rawHTML: false,
candidateText: "", candidateText: "",
sourceLanguage: "", sourceLanguage: "",
percentage: 0, percentage: 0,
@ -81,6 +82,7 @@ const sendRequestToDeepL = async (word, sourceLang, targetLang) => {
const resultData = { const resultData = {
resultText: "", resultText: "",
rawHTML: false,
candidateText: "", candidateText: "",
sourceLanguage: "", sourceLanguage: "",
percentage: 0, percentage: 0,
@ -107,6 +109,75 @@ const sendRequestToDeepL = async (word, sourceLang, targetLang) => {
return resultData; return resultData;
}; };
const sendRequestToSonaveeb = async (word) => {
const resultData = {
resultText: "",
rawHTML: true,
candidateText: "",
sourceLanguage: "",
percentage: 0,
isError: false,
errorMessage: ""
};
const domParser = new DOMParser();
const mainPage = await _sendRequestToSonaveeb(`https://sonaveeb.ee/search/unif/dlall/dsall/${word}/1`, resultData);
if (resultData.isError) {
return resultData;
}
const mainDocument = domParser.parseFromString(mainPage.data, "text/html");
const wordIdElement = mainDocument.querySelector('input[name="word-id"]');
if (!wordIdElement) {
resultData.isError = true;
resultData.errorMessage = `${browser.i18n.getMessage("sonaveebWordIdNotFound")}`;
return resultData;
}
const wordId = wordIdElement.getAttribute("value");
const wordDetailsPage = await _sendRequestToSonaveeb(`https://sonaveeb.ee/worddetails/unif/${wordId}`, resultData);
if (resultData.isError) {
return resultData;
}
resultData.resultText = wordDetailsPage.data;
const wordDetailsDocument = domParser.parseFromString(wordDetailsPage.data, "text/html");
const morphoModalElement = wordDetailsDocument.querySelector('#morpho-modal-0');
if (morphoModalElement) {
const paradigmId = morphoModalElement.getAttribute("data-paradigm-id");
const morphoPage = await _sendRequestToSonaveeb(`https://sonaveeb.ee/morpho/unif/${paradigmId}/est`, resultData);
if (!resultData.isError) {
resultData.resultText += morphoPage.data;
} else {
resultData.isError = false;
resultData.errorMessage = "";
}
}
resultData.sourceLanguage = "et";
resultData.percentage = 1;
log.log(logDir, "sendRequestToSonaveeb()", resultData);
return resultData;
};
const _sendRequestToSonaveeb = async (url, resultData) => {
const result = await axios.get(url).catch(error => error.response);
if (!result || result?.status !== 200) {
resultData.isError = true;
if (!result || result.status === 0) resultData.errorMessage = browser.i18n.getMessage("networkError");
else resultData.errorMessage = `${browser.i18n.getMessage("unknownError")} [${result?.status} ${result?.statusText}] ${result?.data.message}`;
log.error(logDir, "sendRequestToSonaveeb()", result);
}
return result;
};
export default async (sourceWord, sourceLang = "auto", targetLang, translationApi) => { export default async (sourceWord, sourceLang = "auto", targetLang, translationApi) => {
log.log(logDir, "tranlate()", sourceWord, targetLang, translationApi); log.log(logDir, "tranlate()", sourceWord, targetLang, translationApi);
@ -123,9 +194,12 @@ export default async (sourceWord, sourceLang = "auto", targetLang, translationAp
const history = getHistory(sourceWord, sourceLang, targetLang); const history = getHistory(sourceWord, sourceLang, targetLang);
if (history) return history.result; if (history) return history.result;
const result = getSettings("translationApi") === "google" ? const result = translationApi === "google"
await sendRequestToGoogle(sourceWord, sourceLang, targetLang) : ? await sendRequestToGoogle(sourceWord, sourceLang, targetLang)
await sendRequestToDeepL(sourceWord, sourceLang, targetLang); : (translationApi === "deepl"
? await sendRequestToDeepL(sourceWord, sourceLang, targetLang)
: await sendRequestToSonaveeb(sourceWord)
);
setHistory(sourceWord, sourceLang, targetLang, translationApi, result); setHistory(sourceWord, sourceLang, targetLang, translationApi, result);
return result; return result;
}; };

View file

@ -206,15 +206,17 @@ export default class TranslatePanel extends Component {
<p className="simple-translate-error"> <p className="simple-translate-error">
{errorMessage} {errorMessage}
<br /> <br />
<a href={translationApi === "google" ? {(translationApi === "google" || translationApi === "deepl") && (
`https://translate.google.com/?sl=auto&tl=${currentLang}&text=${encodeURIComponent(selectedText)}` : <a href={translationApi === "google" ?
`https://www.deepl.com/translator#auto/${currentLang}/${encodeURIComponent(selectedText)}` `https://translate.google.com/?sl=auto&tl=${currentLang}&text=${encodeURIComponent(selectedText)}` :
} `https://www.deepl.com/translator#auto/${currentLang}/${encodeURIComponent(selectedText)}`
target="_blank"> }
{translationApi === "google" ? target="_blank">
browser.i18n.getMessage("openInGoogleLabel") : {translationApi === "google" ?
browser.i18n.getMessage("openInDeeplLabel")} browser.i18n.getMessage("openInGoogleLabel") :
</a> browser.i18n.getMessage("openInDeeplLabel")}
</a>
)}
</p> </p>
)} )}
</div> </div>

View file

@ -45,10 +45,12 @@ export default class PopupPage extends Component {
targetLang: "", targetLang: "",
inputText: "", inputText: "",
resultText: "", resultText: "",
rawHTML: false,
candidateText: "", candidateText: "",
sourceLang: "", sourceLang: "",
isError: false, isError: false,
errorMessage: "", errorMessage: "",
translationApi: "google",
langList: [], langList: [],
tabUrl: "", tabUrl: "",
isConnected: true, isConnected: true,
@ -73,10 +75,12 @@ export default class PopupPage extends Component {
langHistory = [targetLang, secondLang]; langHistory = [targetLang, secondLang];
setSettings("langHistory", langHistory); setSettings("langHistory", langHistory);
} }
const translationApi = getSettings("translationApi");
this.setState({ this.setState({
targetLang: targetLang, targetLang: targetLang,
langHistory: langHistory, langHistory: langHistory,
langList: generateLangOptions(getSettings("translationApi")) translationApi: translationApi,
langList: generateLangOptions(translationApi)
}); });
const tabInfo = await getTabInfo(); const tabInfo = await getTabInfo();
@ -123,6 +127,7 @@ export default class PopupPage extends Component {
const result = await translate(text, "auto", targetLang); const result = await translate(text, "auto", targetLang);
this.setState({ this.setState({
resultText: result.resultText, resultText: result.resultText,
rawHTML: result.rawHTML,
candidateText: result.candidateText, candidateText: result.candidateText,
sourceLang: result.sourceLanguage, sourceLang: result.sourceLanguage,
isError: result.isError, isError: result.isError,
@ -172,6 +177,7 @@ export default class PopupPage extends Component {
render() { render() {
return ( return (
<div className={rtlLanguageClassName}> <div className={rtlLanguageClassName}>
{this.state.translationApi === "sonaveeb" && ( <link rel="stylesheet" href="https://sonaveeb.ee/view/css/styles.css" /> )}
<Header <Header
toggleEnabledOnPage={this.toggleEnabledOnPage} toggleEnabledOnPage={this.toggleEnabledOnPage}
isEnabledOnPage={this.state.isEnabledOnPage} isEnabledOnPage={this.state.isEnabledOnPage}
@ -187,6 +193,7 @@ export default class PopupPage extends Component {
inputText={this.state.inputText} inputText={this.state.inputText}
targetLang={this.state.targetLang} targetLang={this.state.targetLang}
resultText={this.state.resultText} resultText={this.state.resultText}
rawHTML={this.state.rawHTML}
candidateText={this.state.candidateText} candidateText={this.state.candidateText}
isError={this.state.isError} isError={this.state.isError}
errorMessage={this.state.errorMessage} errorMessage={this.state.errorMessage}

View file

@ -12,7 +12,7 @@ const splitLine = text => {
}; };
export default props => { export default props => {
const { resultText, candidateText, isError, errorMessage, targetLang } = props; const { resultText, rawHTML, candidateText, isError, errorMessage, targetLang } = props;
const shouldShowCandidate = getSettings("ifShowCandidate"); const shouldShowCandidate = getSettings("ifShowCandidate");
const translationApi = getSettings("translationApi"); const translationApi = getSettings("translationApi");
@ -28,10 +28,13 @@ export default props => {
return ( return (
<div id="resultArea"> <div id="resultArea">
<p className="resultText" dir="auto">{splitLine(resultText)}</p> {rawHTML
? ( <p className="resultText" dir="auto" dangerouslySetInnerHTML={{__html: 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">{errorMessage}</p>} {isError && <p className="error">{errorMessage}</p>}
{isError && ( {isError && (translationApi === "google" || translationApi === "deepl") && (
<p className="translateLink"> <p className="translateLink">
<a onClick={handleLinkClick}> <a onClick={handleLinkClick}>
{translationApi === "google" ? {translationApi === "google" ?

View file

@ -115,7 +115,15 @@ export default [
default: "", default: "",
placeholder: "00000000-0000-0000-0000-00000000000000:fx", placeholder: "00000000-0000-0000-0000-00000000000000:fx",
shouldShow: () => (getSettings("translationApi") === "deepl"), shouldShow: () => (getSettings("translationApi") === "deepl"),
} },
{
id: "translationApi",
title: "sonaveebApiLabel",
captions: ["sonaveebApiCaptionLabel"],
type: "radio",
value: "sonaveeb",
handleChange: () => updateLangsWhenChangeTranslationApi()
},
] ]
}, },
{ {