diff --git a/.env.template b/.env.template index 2d681f8a..2fde52af 100644 --- a/.env.template +++ b/.env.template @@ -5,11 +5,10 @@ BASE_URL= # OpenAI API URL WEB_PORT=3000 # Front-end port SERVER_PORT=3001 # Backend port -STATIC_PATH=/static # Static file path -LANGUAGE=zh-CN # Output SRT file and then translate the language -TRANSLATE_DELAY=1500 # Delay between calling translation interface -TRANSLATE_GROUP=4 # Translate sentences for grouping translation, how many sentences can be translated at most at a time +STATIC_PATH=/static # Static file path +TRANSLATE_DELAY=1500 # Delay between calling translation interface +TRANSLATE_GROUP=4 # Translate sentences for grouping translation, how many sentences can be translated at most at a time REDIS_PORT=6379 # Redis port REDIS_HOST=subtitle_redis # Redis address @@ -31,4 +30,5 @@ AUTH_SECRET = YOUR_KEY_HERE # JWT secret you can run `openssl rand -base64 32` t # System Setting # You can edit in Setting OUTPUT_SRT_THEN_TRANSLATE=true # Whether to output the SRT file first and then translate it -TranslateModel=google # google or gpt3 \ No newline at end of file +TranslateModel=google # google or gpt3 +LANGUAGE=zh-CN # Output SRT file and then translate the language diff --git a/apps/server/src/auth/auth.service.ts b/apps/server/src/auth/auth.service.ts index b6d5b127..589e2e16 100644 --- a/apps/server/src/auth/auth.service.ts +++ b/apps/server/src/auth/auth.service.ts @@ -108,7 +108,7 @@ export class AuthService { async updateProfile( user, - { username, password, OUTPUT_SRT_THEN_TRANSLATE, TranslateModel } + { username, password, OUTPUT_SRT_THEN_TRANSLATE, TranslateModel, LANGUAGE } ) { if (typeof OUTPUT_SRT_THEN_TRANSLATE === "boolean") { this.configService.set( @@ -120,6 +120,10 @@ export class AuthService { this.configService.set("TranslateModel", TranslateModel); } + if (LANGUAGE) { + this.configService.set("LANGUAGE", LANGUAGE); + } + return this.usersService.updateProfile(user.id, { username, password, diff --git a/apps/server/src/translate/translate.service.ts b/apps/server/src/translate/translate.service.ts index 6058e87b..6825aa1a 100644 --- a/apps/server/src/translate/translate.service.ts +++ b/apps/server/src/translate/translate.service.ts @@ -8,6 +8,7 @@ import { staticPath } from "utils"; import { TranslateResult } from "shared-types"; import { FilesService } from "@/files/files.service"; import { CustomConfigService } from "@/config/custom-config.service"; +import { TranslateLanguage } from "shared-types"; @Injectable() export class TranslateService { @@ -42,10 +43,10 @@ export class TranslateService { } } - private translateFileName(fileName) { + private async translateFileName(fileName) { const fileObj = path.parse(fileName); - const translateName = - fileObj.name + "." + (process.env.LANGUAGE ?? "Chinese") + fileObj.ext; + const language = await this.getTranslateLanguage(); + const translateName = fileObj.name + "." + language + fileObj.ext; return translateName; } @@ -57,6 +58,14 @@ export class TranslateService { return translateModel; } + private async getTranslateLanguage() { + const translateModel = + ((await this.customConfigService.get( + "LANGUAGE" + )) as TranslateLanguage) ?? TranslateLanguage.SimplifiedChinese; + + return translateModel; + } translateFile( filename, @@ -67,8 +76,8 @@ export class TranslateService { path: string; }> { return new Promise(async (resolve, reject) => { - const translateName = this.translateFileName(filename); - + const translateName = await this.translateFileName(filename); + const language = await this.getTranslateLanguage(); // const existUrl = this.existFile(translateName, dir); // if (existUrl) { // resolve({ @@ -89,7 +98,7 @@ export class TranslateService { .translateSrtStreamGroup( path.join(this.staticDir, dir, filename), path.join(this.staticDir, dir, translateName), - process.env.LANGUAGE ?? "zh-CN", + language, process.env.TRANSLATE_GROUP ? Number(process.env.TRANSLATE_GROUP) : 4, process.env.TRANSLATE_DELAY ? Number(process.env.TRANSLATE_DELAY) @@ -121,7 +130,7 @@ export class TranslateService { ): Promise { return new Promise(async (resolve, reject) => { const subtitle = await this.filesService.findSubtitleFile(id); - const translateName = this.translateFileName(subtitle.fileName); + const translateName = await this.translateFileName(subtitle.fileName); const translatePath = this.translateFilePath( subtitle.filePath, translateName @@ -130,7 +139,7 @@ export class TranslateService { path.relative(this.staticDir, translatePath) ); console.debug("translatePath", translatePath); - console.debug("translateLanguage", process.env.LANGUAGE ?? "Chinese"); + // console.debug("relativePath", path.dirname(relativePath)); const existUrl = fs.existsSync(translatePath); if (existUrl && !forceTranslate) { @@ -144,6 +153,9 @@ export class TranslateService { } const translateModel = await this.getTranslateModel(); + const language = await this.getTranslateLanguage(); + + console.debug("translateLanguage", language); const model = new TranslateModel(translateModel, { baseUrl: process.env.BASE_URL, @@ -153,7 +165,7 @@ export class TranslateService { .translateSrtStreamGroup( subtitle.filePath, translatePath, - process.env.LANGUAGE ?? "zh-CN", + language, process.env.TRANSLATE_GROUP ? Number(process.env.TRANSLATE_GROUP) : 4, process.env.TRANSLATE_DELAY ? Number(process.env.TRANSLATE_DELAY) diff --git a/apps/web/app/preview/tasks/data/data.tsx b/apps/web/app/preview/tasks/data/data.tsx index 90465ca5..8e345e70 100644 --- a/apps/web/app/preview/tasks/data/data.tsx +++ b/apps/web/app/preview/tasks/data/data.tsx @@ -72,8 +72,9 @@ export const priorities = [ }, ]; -export const languages = Object.keys(LanguageEnum).map((key) => ({ - value: LanguageEnum[key as keyof typeof LanguageEnum], - label: key, - icon: Globe2, -})); +export const languages = Object.keys(LanguageEnum) + .map((key) => ({ + value: LanguageEnum[key as keyof typeof LanguageEnum], + label: key, + icon: Globe2, + })); diff --git a/apps/web/app/settings/profile-form.tsx b/apps/web/app/settings/profile-form.tsx index c33771be..0ae617ee 100644 --- a/apps/web/app/settings/profile-form.tsx +++ b/apps/web/app/settings/profile-form.tsx @@ -28,7 +28,7 @@ import { toast } from "@/components/ui/use-toast"; import { Switch } from "@/components/ui/switch"; import { useSession } from "next-auth/react"; import { useRouter } from "next/navigation"; -import { TranslateType } from "shared-types"; +import { TranslateType, TranslateLanguage } from "shared-types"; const profileFormSchema = z.object({ username: z @@ -47,6 +47,7 @@ const profileFormSchema = z.object({ .optional(), OUTPUT_SRT_THEN_TRANSLATE: z.boolean().optional(), TranslateModel: z.nativeEnum(TranslateType).optional(), + LANGUAGE: z.nativeEnum(TranslateLanguage).optional(), }); type ProfileFormValues = z.infer; @@ -180,6 +181,39 @@ export function ProfileForm({ )} /> + ( + +
+ + Translate Language + + + Choose the translation language you need + +
+ +
+ )} + /> diff --git a/apps/web/components/LanguageSelect.tsx b/apps/web/components/LanguageSelect.tsx index 8056bfb3..82b151fe 100644 --- a/apps/web/components/LanguageSelect.tsx +++ b/apps/web/components/LanguageSelect.tsx @@ -25,7 +25,7 @@ export const LanguageSelect = ({ - + Language {languages?.map((option) => ( diff --git a/packages/shared-types/src/index.ts b/packages/shared-types/src/index.ts index 7fb53348..d78822d2 100644 --- a/packages/shared-types/src/index.ts +++ b/packages/shared-types/src/index.ts @@ -51,13 +51,125 @@ export type TranslateResult = { }; export enum LanguageEnum { + Auto = "auto", English = "en", + Chinese = "zh", + German = "de", + Spanish = "es", + Russian = "ru", + Korean = "ko", + French = "fr", Japanese = "ja", - Chinese = "cn", - Auto = "auto", + Portuguese = "pt", + Turkish = "tr", + Polish = "pl", + Catalan = "ca", + Dutch = "nl", + Arabic = "ar", + Swedish = "sv", + Italian = "it", + Indonesian = "id", + Hindi = "hi", + Finnish = "fi", + Vietnamese = "vi", + Hebrew = "iw", + Ukrainian = "uk", + Greek = "el", + Malay = "ms", + Czech = "cs", + Romanian = "ro", + Danish = "da", + Hungarian = "hu", + Tamil = "ta", + Norwegian = "no", + Thai = "th", + Urdu = "ur", + Croatian = "hr", + Bulgarian = "bg", + Lithuanian = "lt", + Latin = "la", + Maori = "mi", + Malayalam = "ml", + Welsh = "cy", + Slovak = "sk", + Telugu = "te", + Persian = "fa", + Latvian = "lv", + Bengali = "bn", + Serbian = "sr", + Azerbaijani = "az", + Slovenian = "sl", + Kannada = "kn", + Estonian = "et", + Macedonian = "mk", + Breton = "br", + Basque = "eu", + Icelandic = "is", + Armenian = "hy", + Nepali = "ne", + Mongolian = "mn", + Bosnian = "bs", + Kazakh = "kk", + Albanian = "sq", + Swahili = "sw", + Galician = "gl", + Marathi = "mr", + Punjabi = "pa", + Sinhala = "si", + Khmer = "km", + Shona = "sn", + Yoruba = "yo", + Somali = "so", + Afrikaans = "af", + Occitan = "oc", + Georgian = "ka", + Belarusian = "be", + Tajik = "tg", + Sindhi = "sd", + Gujarati = "gu", + Amharic = "am", + Yiddish = "yi", + Lao = "lo", + Uzbek = "uz", + Faroese = "fo", + HaitianCreole = "ht", + Pashto = "ps", + Turkmen = "tk", + Nynorsk = "nn", + Maltese = "mt", + Sanskrit = "sa", + Luxembourgish = "lb", + Myanmar = "my", + Tibetan = "bo", + Tagalog = "tl", + Malagasy = "mg", + Assamese = "as", + Tatar = "tt", + Hawaiian = "haw", + Lingala = "ln", + Hausa = "ha", + Bashkir = "ba", + Javanese = "jw", + Sundanese = "su", } export enum TranslateType { GOOGLE = "google", GPT3 = "gpt3", } + +export enum TranslateLanguage { + SimplifiedChinese = "zh-CN", + TraditionalChinese = "zh-TW", + English = "en", + Japanese = "ja", + Korean = "ko", + French = "fr", + Spanish = "es", + Portuguese = "pt", + Italian = "it", + German = "de", + Russian = "ru", + Arabic = "ar", + Indonesian = "id", +}