import React from "react" ; import DeeplLanguages from "./deepl.json" ; import { ITranslationError , ITranslationResult , TranslateParams , Translator , TranslatorLanguages } from "./translator" ; import { createStorageHelper } from "../extension/storage" ; import { ProxyRequestInit } from "../extension" ; import { getMessage } from "../i18n" ; import { Icon } from "../components/icon" ; import { prevDefault } from "../utils" ; class Deepl extends Translator { public name = "deepl" ; public title = "Deepl" ; public publicUrl = "https://www.deepl.com/translator" ; constructor ( ) { super ( DeeplLanguages ) ; } get apiUrl ( ) { const authKey = this . authKey . get ( ) ; const isFreeKey = authKey ?. endsWith ( ":fx" ) ; if ( isFreeKey || ! authKey ) { return "https://api-free.deepl.com/v2" ; } return "https://api.deepl.com/v2" ; } protected authKey = createStorageHelper ( "deepl_api_auth_key" , { defaultValue : "b05afc95-d4ea-2bee-07e6-e81469c588f2:fx" , } ) ; protected setupAuthApiKey = ( ) => { const newKey = window . prompt ( "DeepL API Key" , this . authKey . get ( ) ) ; if ( newKey === null ) return ; this . authKey . set ( newKey || this . authKey . defaultValue ) ; } ; renderSettingsListWidget ( ) { const authKey = this . authKey . get ( ) ; const isDefaultAuthKey = authKey === this . authKey . defaultValue ; return ( < div className = "flex gaps align-center" > { isDefaultAuthKey && ( < Icon small material = "error_outline" tooltip = { getMessage ( "deepl_get_own_key_info" ) } / > ) } < a href = "#" onClick = { prevDefault ( this . setupAuthApiKey ) } > < small > { isDefaultAuthKey && < em > { getMessage ( "deepl_insert_auth_key" ) } < /em>} { ! isDefaultAuthKey && < > / key: <em>{authKey}</em > < />} < /small> < /a> < /div>); } async translate ( params ) { const { from : langFrom , to : langTo , text } = params ; const reqInit = { method : "POST" , headers : { "Authorization" : `DeepL-Auth-Key ${ this . authKey . get ( ) }` , "Content-type" : "application/x-www-form-urlencoded" , } , body : new URLSearchParams ( { text , source_lang : langFrom == "auto" ? "" : langFrom , target_lang : langTo , } as DeeplTranslationRequestParams ) . toString ( ) , } ; try { const { translations } = await this . request ( { url : `${ this . apiUrl }/translate` , requestInit : reqInit , } ) ; return { langDetected : translations [ 0 ] . detected_source_language . toLowerCase ( ) , translation : translations [ 0 ] . text , } ; } catch ( error ) { const { message } = error ; if ( message . startsWith ( `"` ) && message . endsWith ( `"` ) ) { error . message = JSON . parse ( message ) ; } throw error ; } } async getDataUsage ( ) { const url = `${ this . apiUrl }/usage?auth_key=${ this . authKey . get ( ) }` ; return this . request ( { url } ) ; } async getSupportedLanguages ( type ) { const url = `${ this . apiUrl }/languages?type=${ type }&auth_key=${ this . authKey . get ( ) }` ; return this . request ( { url } ) ; } } export interface DeeplUsageResponse { character_count : number ; character_limit : number ; } export interface DeeplTranslationRequestParams { [ param ] : string ; text : string ; source_lang ? : string ; target_lang : string ; split_sentences ? : "0" | "1" | "nonewlines" ; preserve_formatting ? : "0" | "1" ; formality ? : "default" | "more" | "less" ; glossary_id ? : string ; } export interface DeeplTranslation { detected_source_language : string ; text : string ; } export interface DeeplTranslationResponse { translations : DeeplTranslation [ ] ; } export interface DeeplErrorResponse extends ITranslationError { message : string ; } export const enum DeeplErrorCode { BAD_REQUEST = 400 , AUTH_FAILED = 403 , NOT_FOUND = 404 , REQUEST_EXCEED_LIMIT = 413 , REQUEST_TOO_LONG = 414 , TOO_MANY_REQUESTS = 429 , QUOTA_EXCEED = 456 , SERVICE_BREAK = 503 } export interface DeeplSupportedLanguage { language : string ; name : string ; supports_formality ? : boolean ; } export async function dump_deepl_json ( ) { const supportedLanguages = { from : { "auto" : "Auto-detect" } , to : { } , } ; const from = await deepl . getSupportedLanguages ( "source" ) ; const to = await deepl . getSupportedLanguages ( "target" ) ; from . forEach ( ( { name , language } ) => supportedLanguages . from [ language . toLowerCase ( ) ] = name ) ; to . forEach ( ( { name , language } ) => supportedLanguages . to [ language . toLowerCase ( ) ] = name ) ; console . log ( JSON . stringify ( supportedLanguages ) ) ; } const deepl = new Deepl ( ) ; Translator . vendors . set ( deepl . name , deepl ) ;