...
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-10-25 08:52:23 +08:00
parent e6d6096636
commit 0900ac26f7
9 changed files with 607 additions and 29 deletions

View File

@@ -49,10 +49,18 @@ export default function Alphabet() {
<div className="border border-gray-200 m-4 mt-4 flex flex-col justify-center items-center p-4 rounded-2xl gap-2">
<span className="text-2xl md:text-3xl"></span>
<div className="flex gap-1 flex-wrap">
<Button label="日语假名" onClick={() => setChosenAlphabet('japanese')}></Button>
<Button label="英文字母" onClick={() => setChosenAlphabet('english')}></Button>
<Button label="维吾尔字母" onClick={() => setChosenAlphabet('uyghur')}></Button>
<Button label="世界语字母" onClick={() => setChosenAlphabet('esperanto')}></Button>
<Button onClick={() => setChosenAlphabet('japanese')}>
</Button>
<Button onClick={() => setChosenAlphabet('english')}>
</Button>
<Button onClick={() => setChosenAlphabet('uyghur')}>
</Button>
<Button onClick={() => setChosenAlphabet('esperanto')}>
</Button>
</div>
</div>
</>

148
src/app/memorize/page.tsx Normal file
View File

@@ -0,0 +1,148 @@
'use client';
import Button from "@/components/Button";
import { Select, Option } from "@material-tailwind/react";
import { ChangeEvent, useState } from "react";
interface ACardProps {
children?: React.ReactNode,
className?: string
}
function ACard({ children, className }: ACardProps) {
return (
<div className={`w-[61vw] h-96 p-2 shadow-2xl bg-[#00BCD4] rounded-xl ${className}`}>
{children}
</div>);
}
interface BCard {
children?: React.ReactNode,
className?: string
}
function BCard({ children, className }: BCard) {
return (
<div className={`border border-[#0097A7] rounded-xl p-2 ${className}`}>
{children}
</div>);
}
interface WordData {
locale1: string,
locale2: string,
data: Record<string, string>
}
export default function Memorize() {
const [pageState, setPageState] = useState<'choose' | 'start' | 'main' | 'edit'>('edit');
const [wordData, setWordData] = useState<WordData>({
locale1: 'en-US',
locale2: 'zh-CN',
data: { 'hello': '你好' }
});
if (pageState === 'main') {
return (<>
<div className="w-full h-screen flex justify-center items-center">
<ACard>
<h1 className="text-center font-extrabold text-4xl text-white m-2 mb-4">
Memorize
</h1>
<div className="w-full text-white">
<BCard>
<p>Lang1: {wordData.locale1}</p>
<p>Lang2: {wordData.locale2}</p>
<p>Total Words: {Object.keys(wordData.data).length}</p>
</BCard>
</div>
<div className="w-full flex items-center justify-center">
<BCard className="flex gap-2 justify-center items-center w-fit">
<Button>Start</Button>
<Button>Load</Button>
<Button>Save</Button>
<Button onClick={() => setPageState('edit')}>Edit</Button>
</BCard>
</div>
</ACard>
</div>
</>);
}
if (pageState === 'choose') {
return (<>
</>);
}
if (pageState === 'start') {
return (<>
</>);
}
if (pageState === 'edit') {
const convertIntoWordData = (text: string) => {
const t1 = text.split('\n').map(v => v.trim()).filter(v => v.includes(','));
const t2 = t1.map(v => {
const [left, right] = v.split(',', 2).map(v => v.trim());
if (left && right)
return {
[left]: right
};
else return {};
});
const new_data = {
locale1: wordData.locale1,
locale2: wordData.locale2,
data: Object.assign({}, ...t2)
};
setWordData(new_data);
}
const convertFromWordData = () => {
let result = '';
for (const k in wordData.data) {
result += `${k}, ${wordData.data[k]}\n`;
}
return result;
}
let input = convertFromWordData();
const handleSave = () => {
convertIntoWordData(input);
setPageState('main');
}
const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
input = e.target.value;
}
return (<>
<div className="w-full h-screen flex flex-col justify-center items-center">
<ACard className="">
<textarea className="text-white border-gray-200 border rounded-2xl w-full h-50 resize-none outline-0 p-2"
defaultValue={input}
onChange={handleChange}></textarea>
<div className="w-full flex items-center justify-center">
<BCard className="flex gap-2 justify-center items-center w-fit">
<Button>choose locale1</Button>
<Button>choose locale2</Button>
<Button onClick={() => setPageState('main')}>Cancel</Button>
<Button onClick={handleSave}>Save</Button>
<button className="inline-flex items-center justify-center border align-middle select-none font-sans font-medium text-center transition-all duration-300 ease-in disabled:opacity-50 disabled:shadow-none disabled:cursor-not-allowed data-[shape=pill]:rounded-full data-[width=full]:w-full focus:shadow-none text-sm rounded-md py-2 px-4 shadow-sm hover:shadow-md bg-slate-800 border-slate-800 text-slate-50 hover:bg-slate-700 hover:border-slate-700">
Button
</button>
</BCard>
</div>
<div className="w-48">
</div>
</ACard>
</div>
{/* <Select
label="选择语言"
placeholder="请选择语言"
onResize={undefined}
onResizeCapture={undefined}
onPointerEnterCapture={undefined}
onPointerLeaveCapture={undefined}
>
<Option>Material Tailwind HTML</Option>
<Option>Material Tailwind React</Option>
<Option>Material Tailwind Vue</Option>
<Option>Material Tailwind Angular</Option>
<Option>Material Tailwind Svelte</Option>
</Select> */}
</>);
}
}

View File

@@ -287,13 +287,15 @@ export default function TextSpeaker() {
alt="save"
className={`${saving ? 'bg-gray-200' : ''}`}></IconClick>
<div className="w-full flex flex-row flex-wrap gap-2 justify-center items-center">
<Button label="生成IPA"
<Button
selected={ipaEnabled}
onClick={() => setIPAEnabled(!ipaEnabled)}>
IPA
</Button>
<Button label="查看保存项"
<Button
onClick={() => { setShowSaveList(!showSaveList) }}
selected={showSaveList}>
</Button>
</div>
</div>

View File

@@ -206,7 +206,7 @@ export default function Translator() {
</div>
<div className="option1 w-full flex flex-row justify-between items-center">
<span>detect language</span>
<Button label="generate ipa" selected={ipaEnabled} onClick={() => setIPAEnabled(!ipaEnabled)}></Button>
<Button selected={ipaEnabled} onClick={() => setIPAEnabled(!ipaEnabled)}>generate ipa</Button>
</div>
</div>
<div className="card2 w-full md:w-1/2 flex flex-col-reverse gap-2">
@@ -227,10 +227,10 @@ export default function Translator() {
</div>
<div className="option2 w-full flex gap-1 items-center flex-wrap">
<span>translate into</span>
<Button onClick={() => { setTargetLang('English') }} label="English" selected={targetLang === 'English'}></Button>
<Button onClick={() => { setTargetLang('Italian') }} label="Italian" selected={targetLang === 'Italian'}></Button>
<Button onClick={() => { setTargetLang('Japanese') }} label="Japanese" selected={targetLang === 'Japanese'}></Button>
<Button onClick={inputLanguage} label={'Other' + (tl.includes(targetLang) ? '' : ': ' + targetLang)} selected={!(tl.includes(targetLang))}></Button>
<Button onClick={() => { setTargetLang('English') }} selected={targetLang === 'English'}>English</Button>
<Button onClick={() => { setTargetLang('Italian') }} selected={targetLang === 'Italian'}>Italian</Button>
<Button onClick={() => { setTargetLang('Japanese') }} selected={targetLang === 'Japanese'}>Japanese</Button>
<Button onClick={inputLanguage} selected={!(tl.includes(targetLang))}>{'Other' + (tl.includes(targetLang) ? '' : ': ' + targetLang)}</Button>
</div>
</div>
</div>

View File

@@ -147,12 +147,12 @@ export default function WordBoard() {
<TheBoard selectWord={selectWord} words={words as [Word]} setWords={setWords} />
<div className="flex justify-center rounded mt-3 gap-1">
<input ref={inputRef} placeholder="word to operate" type="text" className="focus:outline-none border-b-2 border-black" />
<Button label="插入" onClick={insertWord}></Button>
<Button label="删除" onClick={deleteWord}></Button>
<Button label="搜索" onClick={searchWord}></Button>
<Button label="导入" onClick={importWords}></Button>
<Button label="导出" onClick={exportWords}></Button>
<Button label="删光" onClick={deleteAll}></Button>
<Button onClick={insertWord}></Button>
<Button onClick={deleteWord}></Button>
<Button onClick={searchWord}></Button>
<Button onClick={importWords}></Button>
<Button onClick={exportWords}></Button>
<Button onClick={deleteAll}></Button>
{/* <Button label="朗读" onClick={readWordAloud}></Button> */}
</div>
<input type="file" ref={inputFileRef} className="hidden" accept="application/json" onChange={handleFileChange}></input>

View File

@@ -1,21 +1,20 @@
export default function Button({
label,
onClick,
className = '',
selected = false
className,
selected,
children
}: {
label:
string,
onClick?: () => void,
className?: string,
selected?: boolean
selected?: boolean,
children?: React.ReactNode
}) {
return (
<button
onClick={onClick}
className={`px-2 py-1 rounded shadow-2xs font-bold hover:bg-gray-300 hover:cursor-pointer ${selected ? 'bg-gray-300' : "bg-white"} ${className}`}
>
{label}
{children}
</button>
);
}

144
src/config/locales.ts Normal file
View File

@@ -0,0 +1,144 @@
const locales: string[] = [
"af-ZA",
"sq-AL",
"am-ET",
"ar-DZ",
"ar-BH",
"ar-EG",
"ar-IQ",
"ar-JO",
"ar-KW",
"ar-LB",
"ar-LY",
"ar-MA",
"ar-OM",
"ar-QA",
"ar-SA",
"ar-SY",
"ar-TN",
"ar-AE",
"ar-YE",
"az-AZ",
"bn-BD",
"bn-IN",
"bs-BA",
"bg-BG",
"my-MM",
"ca-ES",
"zh-HK",
"zh-CN",
"zh-CN-liaoning",
"zh-TW",
"zh-CN-shaanxi",
"hr-HR",
"cs-CZ",
"da-DK",
"nl-BE",
"nl-NL",
"en-AU",
"en-CA",
"en-HK",
"en-IN",
"en-IE",
"en-KE",
"en-NZ",
"en-NG",
"en-PH",
"en-SG",
"en-ZA",
"en-TZ",
"en-GB",
"en-US",
"et-EE",
"fil-PH",
"fi-FI",
"fr-BE",
"fr-CA",
"fr-FR",
"fr-CH",
"gl-ES",
"ka-GE",
"de-AT",
"de-DE",
"de-CH",
"el-GR",
"gu-IN",
"he-IL",
"hi-IN",
"hu-HU",
"is-IS",
"id-ID",
"ga-IE",
"it-IT",
"ja-JP",
"jv-ID",
"kn-IN",
"kk-KZ",
"km-KH",
"ko-KR",
"lo-LA",
"lv-LV",
"lt-LT",
"mk-MK",
"ms-MY",
"ml-IN",
"mt-MT",
"mr-IN",
"mn-MN",
"ne-NP",
"nb-NO",
"ps-AF",
"fa-IR",
"pl-PL",
"pt-BR",
"pt-PT",
"ro-RO",
"ru-RU",
"sr-RS",
"si-LK",
"sk-SK",
"sl-SI",
"so-SO",
"es-AR",
"es-BO",
"es-CL",
"es-CO",
"es-CR",
"es-CU",
"es-DO",
"es-EC",
"es-SV",
"es-GQ",
"es-GT",
"es-HN",
"es-MX",
"es-NI",
"es-PA",
"es-PY",
"es-PE",
"es-PR",
"es-ES",
"es-US",
"es-UY",
"es-VE",
"su-ID",
"sw-KE",
"sw-TZ",
"sv-SE",
"ta-IN",
"ta-MY",
"ta-SG",
"ta-LK",
"te-IN",
"th-TH",
"tr-TR",
"uk-UA",
"ur-IN",
"ur-PK",
"uz-UZ",
"vi-VN",
"cy-GB",
"zu-ZA"
];
export default locales;