106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
import { Cache } from "react-native-cache";
|
|
import { LIBRETRANSLATE_BASE_URL } from "@/constants/api";
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { Settings } from "../lib/settings";
|
|
|
|
type language_t = string;
|
|
|
|
const cache = new Cache({
|
|
namespace: "translation_terrace",
|
|
policy: {
|
|
maxEntries: 50000, // if unspecified, it can have unlimited entries
|
|
stdTTL: 0 // the standard ttl as number in seconds, default: 0 (unlimited)
|
|
},
|
|
backend: AsyncStorage
|
|
});
|
|
|
|
export type language_matrix_entry = {
|
|
code: string,
|
|
name: string,
|
|
targets: string []
|
|
}
|
|
|
|
export type language_matrix = {
|
|
[key:string] : language_matrix_entry
|
|
}
|
|
|
|
export class LanguageServer {
|
|
constructor(public baseUrl : string) {}
|
|
|
|
async fetchLanguages() : Promise<language_matrix> {
|
|
let data = {};
|
|
const res = await fetch(this.baseUrl + "/languages", {
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
}
|
|
});
|
|
try {
|
|
data = await res.json();
|
|
} catch (e) {
|
|
throw new Error(`Parsing data from ${await res.text()}: ${e}`)
|
|
}
|
|
try {
|
|
return Object.fromEntries(
|
|
Object.values(data as language_matrix_entry []).map((obj : language_matrix_entry) => {
|
|
return [
|
|
obj["code"],
|
|
obj,
|
|
]
|
|
})
|
|
)
|
|
} catch(e) {
|
|
throw new Error(`Can't extract values from data: ${JSON.stringify(data)}`)
|
|
}
|
|
}
|
|
|
|
static async getDefault() {
|
|
const settings = await Settings.getDefault();
|
|
return new LanguageServer(await settings.getLibretranslateBaseUrl());
|
|
}
|
|
}
|
|
|
|
export class Translator {
|
|
constructor(public source : language_t, public defaultTarget : string = "en", private languageServer : LanguageServer) {
|
|
}
|
|
|
|
async translate(text : string, target : string|undefined = undefined) {
|
|
const url = this.languageServer.baseUrl + `/translate`;
|
|
const res = await fetch(url, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
q: text,
|
|
source: this.source,
|
|
target: target || this.defaultTarget,
|
|
format: "text",
|
|
alternatives: 3,
|
|
api_key: ""
|
|
}),
|
|
headers: { "Content-Type": "application/json" }
|
|
});
|
|
|
|
|
|
const data = await res.json();
|
|
console.log(data)
|
|
return data.translatedText
|
|
}
|
|
|
|
static async getDefault(defaultTarget: string | undefined = undefined) {
|
|
const settings = await Settings.getDefault();
|
|
const source = await settings.getHostLanguage();
|
|
return new Translator(source, defaultTarget, await LanguageServer.getDefault())
|
|
}
|
|
}
|
|
|
|
export class CachedTranslator extends Translator {
|
|
async translate (text : string, target : string|undefined = undefined) {
|
|
const targetKey = target || this.defaultTarget;
|
|
// console.debug(`Translating from ${this.source} -> ${targetKey}`)
|
|
const key1 = `${this.source}::${targetKey}::${text}`
|
|
const tr1 = await cache.get(key1);
|
|
if (tr1) return tr1;
|
|
const tr2 = await super.translate(text, target);
|
|
const key2 = `${this.source}::${targetKey}::${text}`
|
|
await cache.set(key2, tr2);
|
|
return tr2;
|
|
}
|
|
} |