Merge pull request 'Add Libre Translate support' (#9961) from supakaity/hajkey:hk/libre-translate into develop
Reviewed-on: https://codeberg.org/calckey/calckey/pulls/9961
This commit is contained in:
commit
6a9b0e961b
9 changed files with 150 additions and 4 deletions
23
packages/backend/migration/1682777547198-LibreTranslate.js
Normal file
23
packages/backend/migration/1682777547198-LibreTranslate.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
export class LibreTranslate1682777547198 {
|
||||
name = "LibreTranslate1682777547198";
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiUrl" character varying(512)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta"
|
||||
ADD "libreTranslateApiKey" character varying(128)
|
||||
`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiKey"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE "meta" DROP COLUMN "libreTranslateApiUrl"
|
||||
`);
|
||||
}
|
||||
}
|
|
@ -89,6 +89,11 @@ export type Source = {
|
|||
authKey?: string;
|
||||
isPro?: boolean;
|
||||
};
|
||||
libreTranslate: {
|
||||
managed?: boolean;
|
||||
apiUrl?: string;
|
||||
apiKey?: string;
|
||||
};
|
||||
email: {
|
||||
managed?: boolean;
|
||||
address?: string;
|
||||
|
|
|
@ -386,6 +386,18 @@ export class Meta {
|
|||
})
|
||||
public deeplIsPro: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiUrl: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 128,
|
||||
nullable: true,
|
||||
})
|
||||
public libreTranslateApiKey: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512,
|
||||
nullable: true,
|
||||
|
|
|
@ -30,6 +30,17 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
set.deeplIsPro = config.deepl.isPro;
|
||||
}
|
||||
}
|
||||
if (
|
||||
config.libreTranslate.managed != null &&
|
||||
config.libreTranslate.managed === true
|
||||
) {
|
||||
if (typeof config.libreTranslate.apiUrl === "string") {
|
||||
set.libreTranslateApiUrl = config.libreTranslate.apiUrl;
|
||||
}
|
||||
if (typeof config.libreTranslate.apiKey === "string") {
|
||||
set.libreTranslateApiKey = config.libreTranslate.apiKey;
|
||||
}
|
||||
}
|
||||
if (config.email.managed != null && config.email.managed === true) {
|
||||
set.enableEmail = true;
|
||||
if (typeof config.email.address === "string") {
|
||||
|
|
|
@ -512,7 +512,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
enableGithubIntegration: instance.enableGithubIntegration,
|
||||
enableDiscordIntegration: instance.enableDiscordIntegration,
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
pinnedPages: instance.pinnedPages,
|
||||
pinnedClipId: instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
|
@ -564,6 +565,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
objectStorageS3ForcePathStyle: instance.objectStorageS3ForcePathStyle,
|
||||
deeplAuthKey: instance.deeplAuthKey,
|
||||
deeplIsPro: instance.deeplIsPro,
|
||||
libreTranslateApiUrl: instance.libreTranslateApiUrl,
|
||||
libreTranslateApiKey: instance.libreTranslateApiKey,
|
||||
enableIpLogging: instance.enableIpLogging,
|
||||
enableActiveEmailValidation: instance.enableActiveEmailValidation,
|
||||
};
|
||||
|
|
|
@ -124,6 +124,8 @@ export const paramDef = {
|
|||
summalyProxy: { type: "string", nullable: true },
|
||||
deeplAuthKey: { type: "string", nullable: true },
|
||||
deeplIsPro: { type: "boolean" },
|
||||
libreTranslateApiUrl: { type: "string", nullable: true },
|
||||
libreTranslateApiKey: { type: "string", nullable: true },
|
||||
enableTwitterIntegration: { type: "boolean" },
|
||||
twitterConsumerKey: { type: "string", nullable: true },
|
||||
twitterConsumerSecret: { type: "string", nullable: true },
|
||||
|
@ -515,6 +517,22 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
set.deeplIsPro = ps.deeplIsPro;
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiUrl !== undefined) {
|
||||
if (ps.libreTranslateApiUrl === "") {
|
||||
set.libreTranslateApiUrl = null;
|
||||
} else {
|
||||
set.libreTranslateApiUrl = ps.libreTranslateApiUrl;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.libreTranslateApiKey !== undefined) {
|
||||
if (ps.libreTranslateApiKey === "") {
|
||||
set.libreTranslateApiKey = null;
|
||||
} else {
|
||||
set.libreTranslateApiKey = ps.libreTranslateApiKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableIpLogging !== undefined) {
|
||||
set.enableIpLogging = ps.enableIpLogging;
|
||||
}
|
||||
|
|
|
@ -482,7 +482,8 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
translatorAvailable:
|
||||
instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null,
|
||||
defaultReaction: instance.defaultReaction,
|
||||
|
||||
...(ps.detail
|
||||
|
|
|
@ -51,15 +51,54 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
|
||||
const instance = await fetchMeta();
|
||||
|
||||
if (instance.deeplAuthKey == null) {
|
||||
if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) {
|
||||
return 204; // TODO: 良い感じのエラー返す
|
||||
}
|
||||
|
||||
let targetLang = ps.targetLang;
|
||||
if (targetLang.includes("-")) targetLang = targetLang.split("-")[0];
|
||||
|
||||
if (instance.libreTranslateApiUrl != null) {
|
||||
const jsonBody = {
|
||||
q: note.text,
|
||||
source: "auto",
|
||||
target: targetLang,
|
||||
format: "text",
|
||||
api_key: instance.libreTranslateApiKey ?? "",
|
||||
};
|
||||
|
||||
const url = new URL(instance.libreTranslateApiUrl);
|
||||
if (url.pathname.endsWith("/")) {
|
||||
url.pathname = url.pathname.slice(0, -1);
|
||||
}
|
||||
if (!url.pathname.endsWith("/translate")) {
|
||||
url.pathname += "/translate";
|
||||
}
|
||||
const res = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(jsonBody),
|
||||
agent: getAgentByUrl,
|
||||
});
|
||||
|
||||
const json = (await res.json()) as {
|
||||
detectedLanguage?: {
|
||||
confidence: number;
|
||||
language: string;
|
||||
};
|
||||
translatedText: string;
|
||||
};
|
||||
|
||||
return {
|
||||
sourceLang: json.detectedLanguage?.language,
|
||||
text: json.translatedText,
|
||||
};
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append("auth_key", instance.deeplAuthKey);
|
||||
params.append("auth_key", instance.deeplAuthKey ?? "");
|
||||
params.append("text", note.text);
|
||||
params.append("target_lang", targetLang);
|
||||
|
||||
|
|
|
@ -371,6 +371,34 @@
|
|||
<template #label>Pro account</template>
|
||||
</FormSwitch>
|
||||
</FormSection>
|
||||
|
||||
<FormSection>
|
||||
<template #label>Libre Translate</template>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiUrl"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-link ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API URL</template
|
||||
>
|
||||
</FormInput>
|
||||
|
||||
<FormInput
|
||||
v-model="libreTranslateApiKey"
|
||||
class="_formBlock"
|
||||
>
|
||||
<template #prefix
|
||||
><i class="ph-key ph-bold ph-lg"></i
|
||||
></template>
|
||||
<template #label
|
||||
>Libre Translate API Key</template
|
||||
>
|
||||
</FormInput>
|
||||
</FormSection>
|
||||
</div>
|
||||
</FormSuspense>
|
||||
</MkSpacer>
|
||||
|
@ -422,6 +450,8 @@ let swPublicKey: any = $ref(null);
|
|||
let swPrivateKey: any = $ref(null);
|
||||
let deeplAuthKey: string = $ref("");
|
||||
let deeplIsPro: boolean = $ref(false);
|
||||
let libreTranslateApiUrl: string = $ref("");
|
||||
let libreTranslateApiKey: string = $ref("");
|
||||
let defaultReaction: string = $ref("");
|
||||
let defaultReactionCustom: string = $ref("");
|
||||
|
||||
|
@ -456,6 +486,8 @@ async function init() {
|
|||
swPrivateKey = meta.swPrivateKey;
|
||||
deeplAuthKey = meta.deeplAuthKey;
|
||||
deeplIsPro = meta.deeplIsPro;
|
||||
libreTranslateApiUrl = meta.libreTranslateApiUrl;
|
||||
libreTranslateApiKey = meta.libreTranslateApiKey;
|
||||
defaultReaction = ["⭐", "👍", "❤️"].includes(meta.defaultReaction)
|
||||
? meta.defaultReaction
|
||||
: "custom";
|
||||
|
@ -498,6 +530,8 @@ function save() {
|
|||
swPrivateKey,
|
||||
deeplAuthKey,
|
||||
deeplIsPro,
|
||||
libreTranslateApiUrl,
|
||||
libreTranslateApiKey,
|
||||
defaultReaction,
|
||||
}).then(() => {
|
||||
fetchInstance();
|
||||
|
|
Loading…
Reference in a new issue