diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d3a39cd3..42274836 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -29,14 +29,17 @@ model Locale { } model Text { - id Int @id @default(autoincrement()) - created_at DateTime @default(now()) - updated_at DateTime @updatedAt - language_id Int - text String - language Language @relation(fields: [language_id], references: [id]) + id Int @id @default(autoincrement()) + created_at DateTime @default(now()) + updated_at DateTime @updatedAt + language_id Int + text String + language Language @relation(fields: [language_id], references: [id]) + TextToText1 TextToText[] @relation("TextToText1") + TextToText2 TextToText[] @relation("TextToText2") @@unique([language_id, text]) + @@index([language_id]) } model Sound { @@ -44,8 +47,22 @@ model Sound { created_at DateTime @default(now()) updated_at DateTime @updatedAt locale_id Int - sound_text String + sound_text String locale Locale @relation(fields: [locale_id], references: [id]) @@unique([locale_id, sound_text]) } + +model TextToText { + id Int @id @default(autoincrement()) + created_at DateTime @default(now()) + updated_at DateTime @updatedAt + text_id_1 Int + text_id_2 Int + text_1 Text @relation(name: "TextToText1", fields: [text_id_1], references: [id]) + text_2 Text @relation(name: "TextToText2", fields: [text_id_2], references: [id]) + + @@unique([text_id_1, text_id_2]) + @@index([text_id_1]) + @@index([text_id_2]) +} diff --git a/src/lib/api.ts b/src/lib/api.ts index 20d0a6ab..a77e0d4d 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -41,10 +41,21 @@ export class Api { return result } - public async add_text(text: string, language_code: string): Promise { - return await this._fetch(`/api/add-text/${text}/${language_code}`) + public async add_text(language_code: string, text: string): Promise { + return await this._fetch(`/api/add-text/${language_code}/${text}`) } + public async add_translation(text_id: number, language_to_code: string, translation: string): Promise { + return await this._fetch( + `/api/add-translation/${text_id}/${language_to_code}/${translation}` + ) + } + + public async find_translation(text_id: number, language_to_code: string): Promise { + return await this._fetch(`/api/find-translation/${text_id}/${language_to_code}`) + } + + // HACK: 結合方法不明のため保留 // async function split_sentences(text: string, url: URL): Promise { // const split_response = await fetch(`${url.origin}/api/split-sentence/${text}`) diff --git a/src/lib/database.ts b/src/lib/database.ts index 9acc9cc7..8aedcf84 100644 --- a/src/lib/database.ts +++ b/src/lib/database.ts @@ -3,12 +3,15 @@ import { PrismaClient, type Language, type Locale, type Sound, type Text } from export const db = new PrismaClient() export class Database { public static async get_texts(language_code: string): Promise { - const texts = await db.text.findMany({ where: { language: { code: language_code } }, orderBy: { updated_at: 'desc' } }) + const texts = await db.text.findMany({ + where: { language: { code: language_code } }, + orderBy: { updated_at: 'desc' }, + }) return texts } - public static async sound_upsert(sound_text: string, locale_code: string): Promise { + public static async sound_upsert(locale_code: string, sound_text: string): Promise { const locale = await db.locale.findUnique({ where: { code: locale_code } }) if (!locale) throw new Error('locale not found') @@ -52,8 +55,20 @@ export class Database { return locales } - public static async text_upsert(text: string, language_code: string): Promise { - const language = await db.language.findUnique({ where: { code: language_code } }) + public static async language_find_by_code(code: string): Promise { + const language = await db.language.findUnique({ where: { code } }) + + return language + } + + public static async text_find_by_id(id: number): Promise { + const text = await db.text.findUnique({ where: { id } }) + + return text + } + + public static async text_upsert(language_code: string, text: string): Promise { + const language = await this.language_find_by_code(language_code) if (!language) throw new Error('language not found') @@ -72,4 +87,72 @@ export class Database { return result } + + public static async find_translation( + text_id: number, + language_code: string + ): Promise { + const text = await this.text_find_by_id(text_id) + const language = await this.language_find_by_code(language_code) + + if (!text) throw new Error('text not found') + if (!language) throw new Error('language not found') + + const text_ids: number[] = [] + + const translation_to = await db.textToText.findMany({ + where: { + text_id_1: text_id, + text_2: { language_id: language.id }, + }, + }) + + translation_to.forEach((t) => text_ids.push(t.text_id_2)) + + const translation_from = await db.textToText.findMany({ + where: { + text_id_2: text_id, + text_1: { language_id: language.id }, + }, + }) + + translation_from.forEach((t) => text_ids.push(t.text_id_1)) + + const texts = await db.text.findMany({ + where: { + id: { + in: text_ids, + }, + }, + orderBy: { updated_at: 'desc' }, + }) + + return texts + } + + public static async add_translation(text_id: number, language_code: string, translation: string): Promise { + const text = await this.text_find_by_id(text_id) + const language = await this.language_find_by_code(language_code) + + if (!text) throw new Error('text not found') + if (!language) throw new Error('language not found') + + const translation_text = await this.text_upsert(language_code, translation) + + await db.textToText.upsert({ + where: { + text_id_1_text_id_2: { + text_id_1: text.id, + text_id_2: translation_text.id, + }, + }, + update: {}, + create: { + text_id_1: text.id, + text_id_2: translation_text.id, + }, + }) + + return translation_text + } } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 762d5cc2..cafb9455 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -23,11 +23,12 @@ let audio_element: HTMLAudioElement let texts: Text[] = [] - let selected_text = '' - let translated_text = '' + let selected_text: Text | undefined + let translations: string[] = [] let language_from_code = '' let locale_code = '' let language_to_code = '' + let add_translation_string = '' function init_language_select(): void { const languages = JSON.parse(data.languages) as Language[] @@ -53,7 +54,7 @@ const locales = JSON.parse(data.locales) as Locale[] - selected_text = '' + selected_text = undefined Html.append_locale_select_options(locale_select_element, locales, language_from_code) on_change_locale_select(store_language) @@ -84,7 +85,7 @@ } function on_change_locale_select(store_locale = true): void { - console.log('on_change_locale_select') + // console.log('on_change_locale_select') if (!store_locale) { const locale = localStorage.getItem('locale') @@ -98,16 +99,16 @@ } } - function on_click_text(text: string): void { + function on_click_text(text: Text): void { // const language_code = // from_language_select.selectedOptions[0].getAttribute('language_code') ?? '' if (text === selected_text) { - console.log('same text') + // console.log('same text') audio_element.play() } else { selected_text = text - translated_text = '' + translations = [] } // const voice_name = language_code === 'ja-JP' ? 'Google 日本語' : 'Google US English' @@ -115,26 +116,60 @@ // speech(selected_text, language_code, voice_name) } - function add_translation(): void { - // TODO: + async function find_translation(): Promise { + if (!selected_text) return [] + + const translation_texts = await new Api().find_translation(selected_text.id, language_to_code) + const translations = translation_texts.map((translation_text) => translation_text.text) + + return translations } async function show_translation(): Promise { if (language_from_code === language_to_code) { - translated_text = `(${$_('select_different_language')})` + translations = [(`(${$_('select_different_language')})`)] return } if (!selected_text) { - translated_text = `(${$_('select_text_first')})` + translations = [(`(${$_('select_text_first')})`)] return } - translated_text = await new Api().translate_by_google(selected_text, language_to_code) + const find_translation_result = await find_translation() + + if (find_translation_result.length > 0) { + translations = find_translation_result + // console.info('translations found.', translations) + } else { + const translation = await new Api().translate_by_google(selected_text.text, language_to_code) + + await new Api().add_translation(selected_text.id, language_to_code, translation) + + translations = await find_translation() + // console.info('translated', translation) + } + } + + async function add_translation(): Promise { + if (!selected_text) return + if (!add_translation_string) return + + // console.log('add_translation', selected_text) + // console.log('language_to_code', language_to_code) + + await new Api().add_translation(selected_text.id, language_to_code, add_translation_string) + + add_translation_string = '' + + await show_translation() + // TODO: 選択されているテキストを探す + // TODO: 翻訳を登録する + // TODO: 選択されているテキストと翻訳を関連付ける } function init(): void { - translated_text = '' + translations = [] speech_text_element.textContent = `(${$_('lets_talk')})` } @@ -151,7 +186,7 @@ if (!new_text_element.value) return - await new Api().add_text(new_text_element.value, language_from_code) + await new Api().add_text(language_from_code, new_text_element.value) // console.info('add_text', text) @@ -205,7 +240,7 @@ {#each texts as text}
on_click_text(text.text)} + on:click={() => on_click_text(text)} on:keydown > {text.text} @@ -217,7 +252,7 @@
- + diff --git a/src/routes/api/add-text/[text]/[language_code]/+server.ts b/src/routes/api/add-text/[language_code]/[text]/+server.ts similarity index 82% rename from src/routes/api/add-text/[text]/[language_code]/+server.ts rename to src/routes/api/add-text/[language_code]/[text]/+server.ts index da1f461c..4214ca78 100644 --- a/src/routes/api/add-text/[text]/[language_code]/+server.ts +++ b/src/routes/api/add-text/[language_code]/[text]/+server.ts @@ -1,24 +1,21 @@ import { Database } from '$lib/database' import { json, type RequestHandler } from '@sveltejs/kit' - - export const GET: RequestHandler = async ({ url, params }) => { - console.log(url.href) + console.info(url.href) - const text = (params.text ?? '').trim() const language_code = (params.language_code ?? '').trim() + const text = (params.text ?? '').trim() if (text === '' || language_code === '') { return new Response('text or language_code is empty', { status: 400 }) } try { - const result = await Database.text_upsert(text, language_code) + const result = await Database.text_upsert(language_code, text) return json(result) - } - catch (e) { + } catch (e) { console.error(e) return new Response((e as Error).message, { status: 400 }) } diff --git a/src/routes/api/add-translation/[text_id]/[language_code]/[translation]/+server.ts b/src/routes/api/add-translation/[text_id]/[language_code]/[translation]/+server.ts new file mode 100644 index 00000000..f89e1ff9 --- /dev/null +++ b/src/routes/api/add-translation/[text_id]/[language_code]/[translation]/+server.ts @@ -0,0 +1,23 @@ +import { Database } from '$lib/database' +import { json, type RequestHandler } from '@sveltejs/kit' + +export const GET: RequestHandler = async ({ url, params }) => { + console.info(url.href) + + const text_id = Number((params.text_id ?? '').trim()) + const language_code = (params.language_code ?? '').trim() + const translation = (params.translation ?? '').trim() + + if (isNaN(text_id) || language_code === '' || translation === '') { + return new Response('text_id or language_to_code is empty', { status: 400 }) + } + + try { + const result = await Database.add_translation(text_id, language_code, translation) + + return json(result) + } catch (e) { + console.error(e) + return new Response((e as Error).message, { status: 400 }) + } +} diff --git a/src/routes/api/find-translation/[text_id]/[language_code]/+server.ts b/src/routes/api/find-translation/[text_id]/[language_code]/+server.ts new file mode 100644 index 00000000..ae61d751 --- /dev/null +++ b/src/routes/api/find-translation/[text_id]/[language_code]/+server.ts @@ -0,0 +1,22 @@ +import { Database } from '$lib/database' +import { json, type RequestHandler } from '@sveltejs/kit' + +export const GET: RequestHandler = async ({ url, params }) => { + console.info(url.href) + + const text_id = Number((params.text_id ?? '').trim()) + const language_code = (params.language_code ?? '').trim() + + if (isNaN(text_id) || language_code === '') { + return new Response('text_id or language_to_code is empty', { status: 400 }) + } + + try { + const result = await Database.find_translation(text_id, language_code) + + return json(result) + } catch (e) { + console.error(e) + return new Response((e as Error).message, { status: 400 }) + } +} diff --git a/src/routes/api/text-to-speech/[text]/[locale_code]/+server.ts b/src/routes/api/text-to-speech/[text]/[locale_code]/+server.ts index e687eda3..40828187 100644 --- a/src/routes/api/text-to-speech/[text]/[locale_code]/+server.ts +++ b/src/routes/api/text-to-speech/[text]/[locale_code]/+server.ts @@ -23,7 +23,7 @@ async function get_buffers(sentences: string[], locale_code: string): Promise { - console.log(url.href) + console.info(url.href) const text = params.text ?? '' const locale_code = params.locale_code ?? '' diff --git a/src/routes/api/translate-by-google/[text]/[target_lang]/+server.ts b/src/routes/api/translate-by-google/[text]/[target_lang]/+server.ts index 5e02d946..e21739f7 100644 --- a/src/routes/api/translate-by-google/[text]/[target_lang]/+server.ts +++ b/src/routes/api/translate-by-google/[text]/[target_lang]/+server.ts @@ -4,7 +4,7 @@ import { json, type RequestHandler } from "@sveltejs/kit"; export const GET: RequestHandler = async ({ url, params }) => { - console.log(url.href) + console.info(url.href) const trimmed_text = params.text?.trim() ?? '' const target_lang = params.target_lang?.trim() ?? 'en' @@ -15,7 +15,7 @@ export const GET: RequestHandler = async ({ url, params }) => { const translate = new Translate() const [translations] = await translate.translate(trimmed_text, target_lang2) - console.log(translations) + // console.log(translations) return json(translations) } \ No newline at end of file diff --git a/src/routes/api/translate_by_deepl/[text]/[target_lang]/+server.ts b/src/routes/api/translate_by_deepl/[text]/[target_lang]/+server.ts index 3fd57efb..ee71933a 100644 --- a/src/routes/api/translate_by_deepl/[text]/[target_lang]/+server.ts +++ b/src/routes/api/translate_by_deepl/[text]/[target_lang]/+server.ts @@ -4,7 +4,7 @@ import { json, type RequestHandler } from '@sveltejs/kit' import type { TargetLanguageCode } from 'deepl-node' export const GET: RequestHandler = async ({ url, params }) => { - console.log(url.href) + console.info(url.href) const trimmed_text = params.text?.trim() ?? '' // TODO: Translate to selected language #77