From d22979eae2257887fba44886bbc89f1436817c03 Mon Sep 17 00:00:00 2001 From: goddonebianu Date: Tue, 30 Sep 2025 17:12:14 +0800 Subject: [PATCH] ... --- src/app/api/ipa/route.ts | 14 +++++++++++ src/app/api/route.ts | 9 +++++++ src/app/ipa-reader/layout.tsx | 33 +++++++++++++++++++++++++ src/app/ipa-reader/page.tsx | 46 +++++++++++++++++++++++++++++++++++ src/utils.ts | 43 ++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 src/app/api/ipa/route.ts create mode 100644 src/app/api/route.ts create mode 100644 src/app/ipa-reader/layout.tsx create mode 100644 src/app/ipa-reader/page.tsx create mode 100644 src/utils.ts diff --git a/src/app/api/ipa/route.ts b/src/app/api/ipa/route.ts new file mode 100644 index 0000000..5bb1668 --- /dev/null +++ b/src/app/api/ipa/route.ts @@ -0,0 +1,14 @@ +import { getIPA } from "@/utils"; +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + + const text = searchParams.get('text'); + if (!text) return NextResponse.json({ 'error': 400 }, { status: 400 }); + + const r = await getIPA(text); + if (r === null) return NextResponse.json({ 'error': 424 }, { status: 424 }); + + return NextResponse.json({ r }, { status: 200 }); +} diff --git a/src/app/api/route.ts b/src/app/api/route.ts new file mode 100644 index 0000000..352f57f --- /dev/null +++ b/src/app/api/route.ts @@ -0,0 +1,9 @@ +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const url = request.url; + return NextResponse.json({ + message: "Hello World", + url: url + }, { status: 200 }); +} diff --git a/src/app/ipa-reader/layout.tsx b/src/app/ipa-reader/layout.tsx new file mode 100644 index 0000000..65594bd --- /dev/null +++ b/src/app/ipa-reader/layout.tsx @@ -0,0 +1,33 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "IPA Reader", + description: "read ipa aloud", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/src/app/ipa-reader/page.tsx b/src/app/ipa-reader/page.tsx new file mode 100644 index 0000000..a95ded8 --- /dev/null +++ b/src/app/ipa-reader/page.tsx @@ -0,0 +1,46 @@ +"use client"; + +import Button from "@/components/Button"; +import { getIPA, urlGoto } from "@/utils"; +import { useRef, useState } from "react"; + +export default function Home() { + const respref = useRef(null); + const inputref = useRef(null); + const [ipa_result, set_ipa_result] = useState<{ lang: string, ipa: string } | null>(null); + + const generateIPA = () => { + const text = inputref.current!.value.trim(); + if (text.length === 0) return; + getIPA(text).then((result: { lang: string, ipa: string } | null) => { + set_ipa_result(result); + }); + } + const readIPA = () => { + const text = inputref.current!.value.trim(); + if (text.length === 0) return; + // urlGoto(`https://fanyi.baidu.com/gettts?lan=uk&text=${text}&spd=3`); + respref.current!.innerText = '暂不支持朗读'; + } + return ( +
+
+

IPA Reader

+
+ +
+
+ + +
+
+ 语言:{ipa_result?.lang}{'\n'} + IPA:{ipa_result?.ipa} +
+
+
+ ); +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..a8e956b --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,43 @@ +import { GoogleGenAI } from "@google/genai"; + +export function inspect(word: string) { + const goto = (url: string) => { + window.open(url, '_blank'); + } + return () => { + word = word.toLowerCase(); + goto(`https://www.youdao.com/result?word=${word}&lang=en`); + } +} + +export function urlGoto(url: string) { + window.open(url, '_blank'); +} + +const ai = new GoogleGenAI({}); +const prompt = `[TEXT] +请推断以上文本的语言,并返回其宽式国际音标(IPA),以JSON格式 +如: +{ +"lang": "german", +"ipa": "[ˈɡuːtn̩ ˈtaːk]" +} +注意:直接返回json文本, +不要带markdown记号, +ipa一定要加[], +lang的值是小写英语的语言名称`; +export async function getIPA(text: string) { + const response = await ai.models.generateContent({ + model: "gemini-2.5-flash", + contents: prompt.replace("[TEXT]", text), + }); + if (response.text === undefined) return null; + return JSON.parse(response.text); +} + +export async function ggetIPA(text: string): Promise<{ lang: string, ipa: string } | null> { + return { + lang: `(这是的${text}的lang)`, + ipa: `(这是的${text}的ipa)` + }; +}