Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,40 @@ 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 {
id Int @id @default(autoincrement())
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])
}
15 changes: 13 additions & 2 deletions src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,21 @@ export class Api {
return result
}

public async add_text(text: string, language_code: string): Promise<Text> {
return await this._fetch<Text>(`/api/add-text/${text}/${language_code}`)
public async add_text(language_code: string, text: string): Promise<Text> {
return await this._fetch<Text>(`/api/add-text/${language_code}/${text}`)
}

public async add_translation(text_id: number, language_to_code: string, translation: string): Promise<Text> {
return await this._fetch<Text>(
`/api/add-translation/${text_id}/${language_to_code}/${translation}`
)
}

public async find_translation(text_id: number, language_to_code: string): Promise<Text[]> {
return await this._fetch<Text[]>(`/api/find-translation/${text_id}/${language_to_code}`)
}


// HACK: 結合方法不明のため保留
// async function split_sentences(text: string, url: URL): Promise<string[]> {
// const split_response = await fetch(`${url.origin}/api/split-sentence/${text}`)
Expand Down
91 changes: 87 additions & 4 deletions src/lib/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Text[]> {
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<Sound> {
public static async sound_upsert(locale_code: string, sound_text: string): Promise<Sound> {
const locale = await db.locale.findUnique({ where: { code: locale_code } })

if (!locale) throw new Error('locale not found')
Expand Down Expand Up @@ -52,8 +55,20 @@ export class Database {
return locales
}

public static async text_upsert(text: string, language_code: string): Promise<Text> {
const language = await db.language.findUnique({ where: { code: language_code } })
public static async language_find_by_code(code: string): Promise<Language | null> {
const language = await db.language.findUnique({ where: { code } })

return language
}

public static async text_find_by_id(id: number): Promise<Text | null> {
const text = await db.text.findUnique({ where: { id } })

return text
}

public static async text_upsert(language_code: string, text: string): Promise<Text> {
const language = await this.language_find_by_code(language_code)

if (!language) throw new Error('language not found')

Expand All @@ -72,4 +87,72 @@ export class Database {

return result
}

public static async find_translation(
text_id: number,
language_code: string
): Promise<Text[]> {
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<Text> {
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
}
}
76 changes: 58 additions & 18 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand All @@ -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)
Expand Down Expand Up @@ -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')
Expand All @@ -98,43 +99,77 @@
}
}

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'

// speech(selected_text, language_code, voice_name)
}

function add_translation(): void {
// TODO:
async function find_translation(): Promise<string[]> {
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<void> {
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<void> {
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')})`
}

Expand All @@ -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)

Expand Down Expand Up @@ -205,7 +240,7 @@
{#each texts as text}
<div
class="padding_10px_16px cursor_pointer hover"
on:click={() => on_click_text(text.text)}
on:click={() => on_click_text(text)}
on:keydown
>
{text.text}
Expand All @@ -217,7 +252,7 @@
<div class="footer flex_column gap_16px">
<div>
<audio
src={new Api().get_speech_to_text_url(selected_text, locale_code)}
src={new Api().get_speech_to_text_url(selected_text?.text ?? '', locale_code)}
controls
autoplay
bind:this={audio_element}
Expand Down Expand Up @@ -250,11 +285,16 @@
lang={Lang.to_text_language_code(language_to_code)}
class="flex_1 overflow_wrap_anywhere"
>
{translated_text}
{@html translations.join('<br />')}
</div>
</div>
<div class="flex_row gap_8px align_items_center">
<input type="text" class="flex_1" placeholder={$_('enter_new_translation')} />
<input
type="text"
class="flex_1"
placeholder={$_('enter_new_translation')}
bind:value={add_translation_string}
/>
<button on:click={add_translation}>
<div class="flex_row justify_content_center height_24px"><AddIcon /></div>
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -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 })
}
Expand Down
Loading