forked from akai/readest
feat: Added Yandex Translator (#1652)
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
| **File Association and Open With** | Quickly open files in Readest in your file browser with one-click. | ✅ |
|
||||
| **Sync across Platforms** | Synchronize book files, reading progress, notes, and bookmarks across all supported platforms. | ✅ |
|
||||
| **Translate with DeepL** | From a single sentence to the entire book—translate instantly with DeepL. | ✅ |
|
||||
| **Translate with Yandex** | Instantly translate text or books using Yandex Translate. | ✅ |
|
||||
| **Text-to-Speech (TTS) Support** | Enjoy smooth, multilingual narration—even within a single book. | ✅ |
|
||||
| **Library Management** | Organize, sort, and manage your entire ebook library. | ✅ |
|
||||
| **Code Syntax Highlighting** | Read software manuals with rich coloring of code examples. | ✅ |
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
{
|
||||
"url": "https://edge.microsoft.com"
|
||||
},
|
||||
{
|
||||
"url": "https://translate.toil.cc"
|
||||
},
|
||||
{
|
||||
"url": "https://*.microsofttranslator.com"
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"security": {
|
||||
"csp": {
|
||||
"default-src": "'self' 'unsafe-inline' blob: data: customprotocol: asset: http://asset.localhost ipc: http://ipc.localhost",
|
||||
"connect-src": "'self' blob: data: asset: http://asset.localhost ipc: http://ipc.localhost https://*.sentry.io https://*.posthog.com https://*.deepl.com https://*.wikipedia.org https://*.wiktionary.org https://*.supabase.co https://*.readest.com wss://speech.platform.bing.com https://*.cloudflarestorage.com https://translate.googleapis.com https://*.microsofttranslator.com https://edge.microsoft.com https://*.googleusercontent.com",
|
||||
"connect-src": "'self' blob: data: asset: http://asset.localhost ipc: http://ipc.localhost https://*.sentry.io https://*.posthog.com https://*.deepl.com https://*.wikipedia.org https://*.wiktionary.org https://*.supabase.co https://*.readest.com wss://speech.platform.bing.com https://*.cloudflarestorage.com https://translate.googleapis.com https://translate.toil.cc https://*.microsofttranslator.com https://edge.microsoft.com https://*.googleusercontent.com",
|
||||
"img-src": "'self' blob: data: asset: http://asset.localhost https://*",
|
||||
"style-src": "'self' 'unsafe-inline' blob: asset: http://asset.localhost https://cdn.jsdelivr.net https://fonts.googleapis.com https://ik.imagekit.io",
|
||||
"font-src": "'self' blob: data: asset: http://asset.localhost tauri: https://db.onlinewebfonts.com https://cdn.jsdelivr.net https://fonts.gstatic.com https://ik.imagekit.io",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { TranslationProvider } from '../types';
|
||||
import { deeplProvider } from './deepl';
|
||||
import { azureProvider } from './azure';
|
||||
import { googleProvider } from './google';
|
||||
import { yandexProvider } from './yandex';
|
||||
|
||||
function createTranslator<T extends string>(
|
||||
name: T,
|
||||
@@ -18,11 +19,13 @@ function createTranslator<T extends string>(
|
||||
const deeplTranslator = createTranslator('deepl', deeplProvider);
|
||||
const azureTranslator = createTranslator('azure', azureProvider);
|
||||
const googleTranslator = createTranslator('google', googleProvider);
|
||||
const yandexTranslator = createTranslator('yandex', yandexProvider);
|
||||
|
||||
const availableTranslators = [
|
||||
deeplTranslator,
|
||||
azureTranslator,
|
||||
googleTranslator,
|
||||
yandexTranslator,
|
||||
// Add more translators here
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { stubTranslation as _ } from '@/utils/misc';
|
||||
import { fetch as tauriFetch } from '@tauri-apps/plugin-http';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { normalizeToShortLang } from '@/utils/lang';
|
||||
import { TranslationProvider } from '../types';
|
||||
|
||||
/**
|
||||
* Based on https://translate.toil.cc/v2/docs API specification
|
||||
*/
|
||||
async function translateSingleTextForService(
|
||||
text: string,
|
||||
lang: string,
|
||||
service: string,
|
||||
): Promise<string[]> {
|
||||
const fetchImpl = isTauriAppPlatform() ? tauriFetch : window.fetch;
|
||||
const url = 'https://translate.toil.cc/v2/translate/';
|
||||
|
||||
const request = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
lang: lang,
|
||||
service: service,
|
||||
text: text,
|
||||
})
|
||||
};
|
||||
|
||||
const response = await fetchImpl(url, request);
|
||||
|
||||
if (!response.ok) {
|
||||
const response_json = JSON.stringify(await response.json());
|
||||
throw new Error(`${service} failed with status ${response.status}\n${text.length}\n${JSON.stringify(request)}\n${response_json}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (
|
||||
data &&
|
||||
Array.isArray(data.translations)
|
||||
) {
|
||||
return data.translations;
|
||||
} else {
|
||||
// fallback: return original texts if translation failed
|
||||
return [text];
|
||||
}
|
||||
};
|
||||
|
||||
export const yandexProvider: TranslationProvider = {
|
||||
name: 'yandex',
|
||||
label: _('Yandex Translate'),
|
||||
authRequired: false,
|
||||
translate: async (texts: string[], sourceLang: string, targetLang: string): Promise<string[]> => {
|
||||
if (!texts.length) return [];
|
||||
|
||||
/**
|
||||
Possible options:
|
||||
- yandexcloud: often returns 500: {"error":"The text couldn't be translated, because Forbidden"}
|
||||
- yandexgpt: often better than others
|
||||
- yandextranslate
|
||||
- yandexbrowser
|
||||
*/
|
||||
const service = "yandexgpt";
|
||||
|
||||
// Yandex does not accept "auto" language
|
||||
const source_lang = sourceLang == "AUTO" ? "en" : normalizeToShortLang(sourceLang).toLowerCase();
|
||||
const target_lang = normalizeToShortLang(targetLang).toLowerCase();
|
||||
const lang = `${source_lang}-${target_lang}`;
|
||||
|
||||
const responses = await Promise.all(texts.map(async text => {
|
||||
return await translateSingleTextForService(text, lang, service)
|
||||
}));
|
||||
|
||||
const translatedTexts = responses.flat();
|
||||
return translatedTexts;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user