This commit is contained in:
181
messages/en-US.json
Normal file
181
messages/en-US.json
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
{
|
||||||
|
"alphabet": {
|
||||||
|
"chooseCharacters": "Please select the characters you want to learn",
|
||||||
|
"japanese": "Japanese Kana",
|
||||||
|
"english": "English Alphabet",
|
||||||
|
"uyghur": "Uyghur Alphabet",
|
||||||
|
"esperanto": "Esperanto Alphabet",
|
||||||
|
"loading": "Loading...",
|
||||||
|
"loadFailed": "Loading failed, please try again",
|
||||||
|
"hideLetter": "Hide Letter",
|
||||||
|
"showLetter": "Show Letter",
|
||||||
|
"hideIPA": "Hide IPA",
|
||||||
|
"showIPA": "Show IPA"
|
||||||
|
},
|
||||||
|
"folders": {
|
||||||
|
"title": "Folders",
|
||||||
|
"subtitle": "Manage your collections",
|
||||||
|
"newFolder": "New Folder",
|
||||||
|
"creating": "Creating...",
|
||||||
|
"noFoldersYet": "No folders yet",
|
||||||
|
"folderInfo": "{id}. {name} ({totalPairs})",
|
||||||
|
"enterFolderName": "Enter folder name:",
|
||||||
|
"confirmDelete": "Type \"{name}\" to delete:",
|
||||||
|
"createFolderSuccess": "Folder created successfully",
|
||||||
|
"deleteFolderSuccess": "Folder deleted successfully",
|
||||||
|
"createFolderError": "Failed to create folder",
|
||||||
|
"deleteFolderError": "Failed to delete folder"
|
||||||
|
},
|
||||||
|
"folder_id": {
|
||||||
|
"unauthorized": "You are not the owner of this folder",
|
||||||
|
"back": "Back",
|
||||||
|
"textPairs": "Text Pairs",
|
||||||
|
"itemsCount": "{count} items",
|
||||||
|
"memorize": "Memorize",
|
||||||
|
"loadingTextPairs": "Loading text pairs...",
|
||||||
|
"noTextPairs": "No text pairs in this folder",
|
||||||
|
"addNewTextPair": "Add New Text Pair",
|
||||||
|
"add": "Add",
|
||||||
|
"updateTextPair": "Update Text Pair",
|
||||||
|
"update": "Update",
|
||||||
|
"text1": "Text 1",
|
||||||
|
"text2": "Text 2",
|
||||||
|
"locale1": "Locale 1",
|
||||||
|
"locale2": "Locale 2",
|
||||||
|
"edit": "Edit",
|
||||||
|
"delete": "Delete"
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"title": "Learn Languages",
|
||||||
|
"description": "Here is a very useful website to help you learn almost every language in the world, including constructed ones.",
|
||||||
|
"explore": "Explore",
|
||||||
|
"fortune": {
|
||||||
|
"quote": "Stay hungry, stay foolish.",
|
||||||
|
"author": "— Steve Jobs"
|
||||||
|
},
|
||||||
|
"translator": {
|
||||||
|
"name": "Translator",
|
||||||
|
"description": "Translate to any language and annotate with International Phonetic Alphabet (IPA)"
|
||||||
|
},
|
||||||
|
"textSpeaker": {
|
||||||
|
"name": "Text Speaker",
|
||||||
|
"description": "Recognize and read text aloud, supports loop playback and speed adjustment"
|
||||||
|
},
|
||||||
|
"srtPlayer": {
|
||||||
|
"name": "SRT Video Player",
|
||||||
|
"description": "Play videos sentence by sentence based on SRT subtitle files to mimic native speaker pronunciation"
|
||||||
|
},
|
||||||
|
"alphabet": {
|
||||||
|
"name": "Memorize Alphabet",
|
||||||
|
"description": "Start learning a new language from the alphabet"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"name": "Memorize Words",
|
||||||
|
"description": "Language A to Language B, Language B to Language A, supports dictation"
|
||||||
|
},
|
||||||
|
"moreFeatures": {
|
||||||
|
"name": "More Features",
|
||||||
|
"description": "Under development, stay tuned"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"loading": "Loading...",
|
||||||
|
"githubLogin": "GitHub Login"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"choose": {
|
||||||
|
"back": "Back",
|
||||||
|
"choose": "Choose"
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"back": "Back",
|
||||||
|
"save": "Save Word Pairs",
|
||||||
|
"locale1": "Locale 1",
|
||||||
|
"locale2": "Locale 2"
|
||||||
|
},
|
||||||
|
"folder_selector": {
|
||||||
|
"selectFolder": "Select a folder",
|
||||||
|
"noFolders": "No folders found",
|
||||||
|
"folderInfo": "{id}. {name} ({count})"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"title": "Memorize",
|
||||||
|
"locale1": "Your selected locale 1 is {locale}",
|
||||||
|
"locale2": "Your selected locale 2 is {locale}",
|
||||||
|
"total": "There are {total} word pairs in total",
|
||||||
|
"start": "Start",
|
||||||
|
"import": "Import",
|
||||||
|
"export": "Export",
|
||||||
|
"edit": "Edit"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"showAnswer": "Show Answer",
|
||||||
|
"next": "Next",
|
||||||
|
"reverse": "Reverse",
|
||||||
|
"dictation": "Dictation",
|
||||||
|
"noTextPairs": "No text pairs available",
|
||||||
|
"progress": "{current}/{total}"
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"unauthorized": "You are not authorized to access this folder"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"show": "Show",
|
||||||
|
"reverse": "Reverse",
|
||||||
|
"dictation": "Dictation",
|
||||||
|
"back": "Back",
|
||||||
|
"next": "Next"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"title": "learn-languages",
|
||||||
|
"about": "About",
|
||||||
|
"sourceCode": "GitHub",
|
||||||
|
"login": "Login",
|
||||||
|
"profile": "Profile",
|
||||||
|
"folders": "Folders"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"myProfile": "My Profile",
|
||||||
|
"email": "Email: {email}",
|
||||||
|
"logout": "Logout"
|
||||||
|
},
|
||||||
|
"srt_player": {
|
||||||
|
"uploadVideo": "Upload Video",
|
||||||
|
"uploadSubtitle": "Upload Subtitle",
|
||||||
|
"pause": "Pause",
|
||||||
|
"play": "Play",
|
||||||
|
"previous": "Previous",
|
||||||
|
"next": "Next",
|
||||||
|
"restart": "Restart",
|
||||||
|
"autoPause": "Auto Pause ({enabled})"
|
||||||
|
},
|
||||||
|
"text_speaker": {
|
||||||
|
"generateIPA": "Generate IPA",
|
||||||
|
"viewSavedItems": "View Saved Items",
|
||||||
|
"confirmDeleteAll": "Are you sure you want to delete everything? (Y/N)"
|
||||||
|
},
|
||||||
|
"translator": {
|
||||||
|
"detectLanguage": "detect language",
|
||||||
|
"generateIPA": "generate ipa",
|
||||||
|
"translateInto": "translate into",
|
||||||
|
"chinese": "Chinese",
|
||||||
|
"english": "English",
|
||||||
|
"italian": "Italian",
|
||||||
|
"other": "Other",
|
||||||
|
"translating": "translating...",
|
||||||
|
"translate": "translate",
|
||||||
|
"inputLanguage": "Input a language.",
|
||||||
|
"history": "History",
|
||||||
|
"enterLanguage": "Enter language",
|
||||||
|
"add_to_folder": {
|
||||||
|
"notAuthenticated": "You are not authenticated",
|
||||||
|
"chooseFolder": "Choose a Folder to Add to",
|
||||||
|
"noFolders": "No folders found",
|
||||||
|
"folderInfo": "{id}. {name}",
|
||||||
|
"close": "Close",
|
||||||
|
"success": "Text pair added to folder",
|
||||||
|
"error": "Failed to add text pair to folder"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
181
messages/zh-CN.json
Normal file
181
messages/zh-CN.json
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
{
|
||||||
|
"alphabet": {
|
||||||
|
"chooseCharacters": "请选择您想学习的字符",
|
||||||
|
"japanese": "日语假名",
|
||||||
|
"english": "英文字母",
|
||||||
|
"uyghur": "维吾尔字母",
|
||||||
|
"esperanto": "世界语字母",
|
||||||
|
"loading": "加载中...",
|
||||||
|
"loadFailed": "加载失败,请重试",
|
||||||
|
"hideLetter": "隐藏字母",
|
||||||
|
"showLetter": "显示字母",
|
||||||
|
"hideIPA": "隐藏IPA",
|
||||||
|
"showIPA": "显示IPA"
|
||||||
|
},
|
||||||
|
"folders": {
|
||||||
|
"title": "文件夹",
|
||||||
|
"subtitle": "管理您的集合",
|
||||||
|
"newFolder": "新建文件夹",
|
||||||
|
"creating": "创建中...",
|
||||||
|
"noFoldersYet": "还没有文件夹",
|
||||||
|
"folderInfo": "{id}. {name} ({totalPairs})",
|
||||||
|
"enterFolderName": "输入文件夹名称:",
|
||||||
|
"confirmDelete": "输入 \"{name}\" 以删除:",
|
||||||
|
"createFolderSuccess": "文件夹创建成功",
|
||||||
|
"deleteFolderSuccess": "文件夹删除成功",
|
||||||
|
"createFolderError": "创建文件夹失败",
|
||||||
|
"deleteFolderError": "删除文件夹失败"
|
||||||
|
},
|
||||||
|
"folder_id": {
|
||||||
|
"unauthorized": "您不是此文件夹的所有者",
|
||||||
|
"back": "返回",
|
||||||
|
"textPairs": "文本对",
|
||||||
|
"itemsCount": "{count} 个项目",
|
||||||
|
"memorize": "记忆",
|
||||||
|
"loadingTextPairs": "加载文本对中...",
|
||||||
|
"noTextPairs": "此文件夹中没有文本对",
|
||||||
|
"addNewTextPair": "添加新文本对",
|
||||||
|
"add": "添加",
|
||||||
|
"updateTextPair": "更新文本对",
|
||||||
|
"update": "更新",
|
||||||
|
"text1": "文本1",
|
||||||
|
"text2": "文本2",
|
||||||
|
"locale1": "语言1",
|
||||||
|
"locale2": "语言2",
|
||||||
|
"edit": "编辑",
|
||||||
|
"delete": "删除"
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"title": "学语言",
|
||||||
|
"description": "这里是一个非常有用的网站,可以帮助您学习世界上几乎每一种语言,包括人造语言。",
|
||||||
|
"explore": "探索网站",
|
||||||
|
"fortune": {
|
||||||
|
"quote": "求知若饥,虚心若愚。",
|
||||||
|
"author": "—— 史蒂夫·乔布斯"
|
||||||
|
},
|
||||||
|
"translator": {
|
||||||
|
"name": "翻译器",
|
||||||
|
"description": "翻译到任何语言,并标注国际音标(IPA)"
|
||||||
|
},
|
||||||
|
"textSpeaker": {
|
||||||
|
"name": "朗读器",
|
||||||
|
"description": "识别并朗读文本,支持循环朗读、朗读速度调节"
|
||||||
|
},
|
||||||
|
"srtPlayer": {
|
||||||
|
"name": "逐句视频播放器",
|
||||||
|
"description": "基于SRT字幕文件,逐句播放视频以模仿母语者的发音"
|
||||||
|
},
|
||||||
|
"alphabet": {
|
||||||
|
"name": "背字母",
|
||||||
|
"description": "从字母表开始新语言的学习"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"name": "背单词",
|
||||||
|
"description": "语言A到语言B,语言B到语言A,支持听写"
|
||||||
|
},
|
||||||
|
"moreFeatures": {
|
||||||
|
"name": "更多功能",
|
||||||
|
"description": "开发中,敬请期待"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"loading": "加载中...",
|
||||||
|
"githubLogin": "GitHub登录"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"choose": {
|
||||||
|
"back": "返回",
|
||||||
|
"choose": "选择"
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"back": "返回",
|
||||||
|
"save": "保存单词对",
|
||||||
|
"locale1": "区域1",
|
||||||
|
"locale2": "区域2"
|
||||||
|
},
|
||||||
|
"folder_selector": {
|
||||||
|
"selectFolder": "选择文件夹",
|
||||||
|
"noFolders": "未找到文件夹",
|
||||||
|
"folderInfo": "{id}. {name} ({count})"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"title": "记忆",
|
||||||
|
"locale1": "您选择的区域一是{locale}",
|
||||||
|
"locale2": "您选择的区域二是{locale}",
|
||||||
|
"total": "总计有{total}个单词对",
|
||||||
|
"start": "开始",
|
||||||
|
"import": "导入",
|
||||||
|
"export": "导出",
|
||||||
|
"edit": "编辑"
|
||||||
|
},
|
||||||
|
"memorize": {
|
||||||
|
"showAnswer": "显示答案",
|
||||||
|
"next": "下一个",
|
||||||
|
"reverse": "反向",
|
||||||
|
"dictation": "听写",
|
||||||
|
"noTextPairs": "没有可用的文本对",
|
||||||
|
"progress": "{current}/{total}"
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"unauthorized": "您无权访问该文件夹"
|
||||||
|
},
|
||||||
|
"start": {
|
||||||
|
"show": "显示",
|
||||||
|
"reverse": "反向",
|
||||||
|
"dictation": "听写",
|
||||||
|
"back": "返回",
|
||||||
|
"next": "下个"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"navbar": {
|
||||||
|
"title": "学语言",
|
||||||
|
"about": "关于",
|
||||||
|
"sourceCode": "源码",
|
||||||
|
"login": "登录",
|
||||||
|
"profile": "个人资料",
|
||||||
|
"folders": "文件夹"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"myProfile": "我的个人资料",
|
||||||
|
"email": "邮箱:{email}",
|
||||||
|
"logout": "退出登录"
|
||||||
|
},
|
||||||
|
"srt_player": {
|
||||||
|
"uploadVideo": "上传视频",
|
||||||
|
"uploadSubtitle": "上传字幕",
|
||||||
|
"pause": "暂停",
|
||||||
|
"play": "播放",
|
||||||
|
"previous": "上句",
|
||||||
|
"next": "下句",
|
||||||
|
"restart": "句首",
|
||||||
|
"autoPause": "自动暂停({enabled})"
|
||||||
|
},
|
||||||
|
"text_speaker": {
|
||||||
|
"generateIPA": "生成IPA",
|
||||||
|
"viewSavedItems": "查看保存项",
|
||||||
|
"confirmDeleteAll": "确定删光吗?(Y/N)"
|
||||||
|
},
|
||||||
|
"translator": {
|
||||||
|
"detectLanguage": "检测语言",
|
||||||
|
"generateIPA": "生成国际音标",
|
||||||
|
"translateInto": "翻译为",
|
||||||
|
"chinese": "中文",
|
||||||
|
"english": "英文",
|
||||||
|
"italian": "意大利语",
|
||||||
|
"other": "其他",
|
||||||
|
"translating": "翻译中...",
|
||||||
|
"translate": "翻译",
|
||||||
|
"inputLanguage": "请输入语言。",
|
||||||
|
"history": "历史记录",
|
||||||
|
"enterLanguage": "输入语言",
|
||||||
|
"add_to_folder": {
|
||||||
|
"notAuthenticated": "您未通过身份验证",
|
||||||
|
"chooseFolder": "选择要添加到的文件夹",
|
||||||
|
"noFolders": "未找到文件夹",
|
||||||
|
"folderInfo": "{id}. {name}",
|
||||||
|
"close": "关闭",
|
||||||
|
"success": "文本对已添加到文件夹",
|
||||||
|
"error": "添加文本对到文件夹失败"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"chooseCharacters": "Please select the characters you want to learn",
|
|
||||||
"japanese": "Japanese Kana",
|
|
||||||
"english": "English Alphabet",
|
|
||||||
"uyghur": "Uyghur Alphabet",
|
|
||||||
"esperanto": "Esperanto Alphabet",
|
|
||||||
"loading": "Loading...",
|
|
||||||
"loadFailed": "Loading failed, please try again",
|
|
||||||
"hideLetter": "Hide Letter",
|
|
||||||
"showLetter": "Show Letter",
|
|
||||||
"hideIPA": "Hide IPA",
|
|
||||||
"showIPA": "Show IPA"
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"unauthorized": "You are not the owner of this folder",
|
|
||||||
"back": "Back",
|
|
||||||
"backToFolders": "Back to folders",
|
|
||||||
"folderName": "Folder: {name}",
|
|
||||||
"textPairs": "Text Pairs",
|
|
||||||
"itemsCount": "{count} items",
|
|
||||||
"memorize": "Memorize",
|
|
||||||
"loadingTextPairs": "Loading text pairs...",
|
|
||||||
"noTextPairs": "No text pairs in this folder",
|
|
||||||
"addTextPair": "Add Text Pair",
|
|
||||||
"addNewTextPair": "Add New Text Pair",
|
|
||||||
"text1": "Text 1",
|
|
||||||
"text2": "Text 2",
|
|
||||||
"locale1": "Locale 1",
|
|
||||||
"locale2": "Locale 2",
|
|
||||||
"save": "Save",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"edit": "Edit",
|
|
||||||
"delete": "Delete",
|
|
||||||
"confirmDelete": "Are you sure you want to delete this text pair?",
|
|
||||||
"updateTextPair": "Update Text Pair",
|
|
||||||
"update": "Update",
|
|
||||||
"textPairSaved": "Text pair saved successfully",
|
|
||||||
"textPairUpdated": "Text pair updated successfully",
|
|
||||||
"textPairDeleted": "Text pair deleted successfully",
|
|
||||||
"errorSavingTextPair": "Failed to save text pair",
|
|
||||||
"errorUpdatingTextPair": "Failed to update text pair",
|
|
||||||
"errorDeletingTextPair": "Failed to delete text pair"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Folders",
|
|
||||||
"subtitle": "Manage your collections",
|
|
||||||
"newFolder": "New Folder",
|
|
||||||
"creating": "Creating...",
|
|
||||||
"noFoldersYet": "No folders yet",
|
|
||||||
"folderInfo": "{id}. {name} ({totalPairs})",
|
|
||||||
"enterFolderName": "Enter folder name:",
|
|
||||||
"confirmDelete": "Type \"{name}\" to delete:",
|
|
||||||
"createFolderError": "Failed to create folder",
|
|
||||||
"deleteFolderError": "Failed to delete folder",
|
|
||||||
"createFolderSuccess": "Folder created successfully",
|
|
||||||
"deleteFolderSuccess": "Folder deleted successfully"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Learn Languages",
|
|
||||||
"description": "Here is a very useful website to help you learn almost every language in the world, including constructed ones.",
|
|
||||||
"explore": "Explore",
|
|
||||||
"fortune": {
|
|
||||||
"quote": "Stay hungry, stay foolish.",
|
|
||||||
"author": "— Steve Jobs"
|
|
||||||
},
|
|
||||||
"translator": {
|
|
||||||
"name": "Translator",
|
|
||||||
"description": "Translate to any language and annotate with International Phonetic Alphabet (IPA)"
|
|
||||||
},
|
|
||||||
"textSpeaker": {
|
|
||||||
"name": "Text Speaker",
|
|
||||||
"description": "Recognize and read text aloud, supports loop playback and speed adjustment"
|
|
||||||
},
|
|
||||||
"srtPlayer": {
|
|
||||||
"name": "SRT Video Player",
|
|
||||||
"description": "Play videos sentence by sentence based on SRT subtitle files to mimic native speaker pronunciation"
|
|
||||||
},
|
|
||||||
"alphabet": {
|
|
||||||
"name": "Memorize Alphabet",
|
|
||||||
"description": "Start learning a new language from the alphabet"
|
|
||||||
},
|
|
||||||
"memorize": {
|
|
||||||
"name": "Memorize Words",
|
|
||||||
"description": "Language A to Language B, Language B to Language A, supports dictation"
|
|
||||||
},
|
|
||||||
"moreFeatures": {
|
|
||||||
"name": "More Features",
|
|
||||||
"description": "Under development, stay tuned"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"loading": "Loading...",
|
|
||||||
"githubLogin": "GitHub Login"
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"back": "Back",
|
|
||||||
"choose": "Choose"
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"back": "Back",
|
|
||||||
"save": "Save Word Pairs",
|
|
||||||
"locale1": "Locale 1",
|
|
||||||
"locale2": "Locale 2"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Select a folder",
|
|
||||||
"noFolders": "No folders found",
|
|
||||||
"folderInfo": "{id}. {name} ({count})"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "Memorize",
|
|
||||||
"locale1": "Your selected locale 1 is {locale}",
|
|
||||||
"locale2": "Your selected locale 2 is {locale}",
|
|
||||||
"total": "There are {total} word pairs in total",
|
|
||||||
"start": "Start",
|
|
||||||
"import": "Import",
|
|
||||||
"export": "Export",
|
|
||||||
"edit": "Edit"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"showAnswer": "Show Answer",
|
|
||||||
"next": "Next",
|
|
||||||
"reverse": "Reverse",
|
|
||||||
"dictation": "Dictation",
|
|
||||||
"noTextPairs": "No text pairs available",
|
|
||||||
"progress": "{index}/{total}"
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"unauthorized": "Unauthorized access to this folder"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"show": "Show",
|
|
||||||
"reverse": "Reverse",
|
|
||||||
"dictation": "Dictation",
|
|
||||||
"back": "Back",
|
|
||||||
"next": "Next"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "learn-languages",
|
|
||||||
"about": "About",
|
|
||||||
"sourceCode": "GitHub",
|
|
||||||
"login": "Login",
|
|
||||||
"profile": "Profile",
|
|
||||||
"folders": "Folders"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"myProfile": "My Profile",
|
|
||||||
"email": "Email: {email}",
|
|
||||||
"logout": "Logout"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"uploadVideo": "Upload Video",
|
|
||||||
"uploadSubtitle": "Upload Subtitle",
|
|
||||||
"pause": "Pause",
|
|
||||||
"play": "Play",
|
|
||||||
"previous": "Previous",
|
|
||||||
"next": "Next",
|
|
||||||
"restart": "Restart",
|
|
||||||
"autoPause": "Auto Pause ({enabled})"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"generateIPA": "Generate IPA",
|
|
||||||
"viewSavedItems": "View Saved Items",
|
|
||||||
"confirmDeleteAll": "Are you sure you want to delete everything? (Y/N)"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"detectLanguage": "detect language",
|
|
||||||
"generateIPA": "generate ipa",
|
|
||||||
"translateInto": "translate into",
|
|
||||||
"chinese": "Chinese",
|
|
||||||
"english": "English",
|
|
||||||
"italian": "Italian",
|
|
||||||
"other": "Other",
|
|
||||||
"translating": "translating...",
|
|
||||||
"translate": "translate",
|
|
||||||
"inputLanguage": "Input a language.",
|
|
||||||
"history": "History",
|
|
||||||
"enterLanguage": "Enter language"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"chooseFolder": "Choose a Folder to Add to",
|
|
||||||
"notAuthenticated": "You are not authenticated",
|
|
||||||
"noFoldersFound": "No folders found",
|
|
||||||
"close": "Close",
|
|
||||||
"addToFolderSuccess": "Text pair added to folder",
|
|
||||||
"addToFolderError": "Failed to add text pair to folder"
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"chooseCharacters": "请选择您想学习的字符",
|
|
||||||
"japanese": "日语假名",
|
|
||||||
"english": "英文字母",
|
|
||||||
"uyghur": "维吾尔字母",
|
|
||||||
"esperanto": "世界语字母",
|
|
||||||
"loading": "加载中...",
|
|
||||||
"loadFailed": "加载失败,请重试",
|
|
||||||
"hideLetter": "隐藏字母",
|
|
||||||
"showLetter": "显示字母",
|
|
||||||
"hideIPA": "隐藏IPA",
|
|
||||||
"showIPA": "显示IPA"
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"unauthorized": "您不是此文件夹的所有者",
|
|
||||||
"back": "返回",
|
|
||||||
"backToFolders": "返回文件夹",
|
|
||||||
"folderName": "文件夹:{name}",
|
|
||||||
"textPairs": "文本对",
|
|
||||||
"itemsCount": "{count} 项",
|
|
||||||
"memorize": "记忆",
|
|
||||||
"loadingTextPairs": "正在加载文本对...",
|
|
||||||
"noTextPairs": "此文件夹中没有文本对",
|
|
||||||
"addTextPair": "添加文本对",
|
|
||||||
"addNewTextPair": "添加新文本对",
|
|
||||||
"text1": "文本1",
|
|
||||||
"text2": "文本2",
|
|
||||||
"locale1": "语言1",
|
|
||||||
"locale2": "语言2",
|
|
||||||
"save": "保存",
|
|
||||||
"cancel": "取消",
|
|
||||||
"add": "添加",
|
|
||||||
"edit": "编辑",
|
|
||||||
"delete": "删除",
|
|
||||||
"confirmDelete": "确定要删除这个文本对吗?",
|
|
||||||
"updateTextPair": "更新文本对",
|
|
||||||
"update": "更新",
|
|
||||||
"textPairSaved": "文本对保存成功",
|
|
||||||
"textPairUpdated": "文本对更新成功",
|
|
||||||
"textPairDeleted": "文本对删除成功",
|
|
||||||
"errorSavingTextPair": "保存文本对失败",
|
|
||||||
"errorUpdatingTextPair": "更新文本对失败",
|
|
||||||
"errorDeletingTextPair": "删除文本对失败"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "文件夹",
|
|
||||||
"subtitle": "管理您的集合",
|
|
||||||
"newFolder": "新建文件夹",
|
|
||||||
"creating": "创建中...",
|
|
||||||
"noFoldersYet": "还没有文件夹",
|
|
||||||
"folderInfo": "{id}. {name} ({totalPairs})",
|
|
||||||
"enterFolderName": "输入文件夹名称:",
|
|
||||||
"confirmDelete": "输入 \"{name}\" 以删除:",
|
|
||||||
"createFolderError": "创建文件夹失败",
|
|
||||||
"deleteFolderError": "删除文件夹失败",
|
|
||||||
"createFolderSuccess": "文件夹创建成功",
|
|
||||||
"deleteFolderSuccess": "文件夹删除成功"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "学语言",
|
|
||||||
"description": "这里是一个非常有用的网站,可以帮助你学习世界上几乎每一种语言,包括人造语言。",
|
|
||||||
"explore": "探索网站",
|
|
||||||
"fortune": {
|
|
||||||
"quote": "求知若饥,虚心若愚。",
|
|
||||||
"author": "—— 史蒂夫·乔布斯"
|
|
||||||
},
|
|
||||||
"translator": {
|
|
||||||
"name": "翻译器",
|
|
||||||
"description": "翻译到任何语言,并标注国际音标(IPA)"
|
|
||||||
},
|
|
||||||
"textSpeaker": {
|
|
||||||
"name": "朗读器",
|
|
||||||
"description": "识别并朗读文本,支持循环朗读、朗读速度调节"
|
|
||||||
},
|
|
||||||
"srtPlayer": {
|
|
||||||
"name": "逐句视频播放器",
|
|
||||||
"description": "基于SRT字幕文件,逐句播放视频以模仿母语者的发音"
|
|
||||||
},
|
|
||||||
"alphabet": {
|
|
||||||
"name": "背字母",
|
|
||||||
"description": "从字母表开始新语言的学习"
|
|
||||||
},
|
|
||||||
"memorize": {
|
|
||||||
"name": "背单词",
|
|
||||||
"description": "语言A到语言B,语言B到语言A,支持听写"
|
|
||||||
},
|
|
||||||
"moreFeatures": {
|
|
||||||
"name": "更多功能",
|
|
||||||
"description": "开发中,敬请期待"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"loading": "加载中...",
|
|
||||||
"githubLogin": "GitHub 登录"
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"back": "返回",
|
|
||||||
"choose": "选择"
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"back": "返回",
|
|
||||||
"save": "保存单词对",
|
|
||||||
"locale1": "区域1",
|
|
||||||
"locale2": "区域2"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "选择文件夹",
|
|
||||||
"noFolders": "未找到文件夹",
|
|
||||||
"folderInfo": "{id}. {name} ({count})"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "记忆",
|
|
||||||
"locale1": "您选择的区域一是{locale}",
|
|
||||||
"locale2": "您选择的区域二是{locale}",
|
|
||||||
"total": "总计有{total}个单词对",
|
|
||||||
"start": "开始",
|
|
||||||
"import": "导入",
|
|
||||||
"export": "导出",
|
|
||||||
"edit": "编辑"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"showAnswer": "显示答案",
|
|
||||||
"next": "下一个",
|
|
||||||
"reverse": "反向",
|
|
||||||
"dictation": "听写",
|
|
||||||
"noTextPairs": "没有可用的文本对",
|
|
||||||
"progress": "{index}/{total}"
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"unauthorized": "您无权访问该文件夹"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"show": "显示",
|
|
||||||
"reverse": "反向",
|
|
||||||
"dictation": "听写",
|
|
||||||
"back": "返回",
|
|
||||||
"next": "下个"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"title": "学语言",
|
|
||||||
"about": "关于",
|
|
||||||
"sourceCode": "源码",
|
|
||||||
"login": "登录",
|
|
||||||
"profile": "个人资料",
|
|
||||||
"folders": "文件夹"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"myProfile": "我的个人资料",
|
|
||||||
"email": "邮箱:{email}",
|
|
||||||
"logout": "退出登录"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"uploadVideo": "上传视频",
|
|
||||||
"uploadSubtitle": "上传字幕",
|
|
||||||
"pause": "暂停",
|
|
||||||
"play": "播放",
|
|
||||||
"previous": "上句",
|
|
||||||
"next": "下句",
|
|
||||||
"restart": "句首",
|
|
||||||
"autoPause": "自动暂停({enabled})"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"generateIPA": "生成IPA",
|
|
||||||
"viewSavedItems": "查看保存项",
|
|
||||||
"confirmDeleteAll": "确定删光吗?(Y/N)"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"detectLanguage": "检测语言",
|
|
||||||
"generateIPA": "生成国际音标",
|
|
||||||
"translateInto": "翻译为",
|
|
||||||
"chinese": "中文",
|
|
||||||
"english": "英文",
|
|
||||||
"italian": "意大利语",
|
|
||||||
"other": "其他",
|
|
||||||
"translating": "翻译中...",
|
|
||||||
"translate": "翻译",
|
|
||||||
"inputLanguage": "请输入语言。",
|
|
||||||
"history": "历史记录",
|
|
||||||
"enterLanguage": "输入语言"
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"chooseFolder": "选择要添加到的文件夹",
|
|
||||||
"notAuthenticated": "您未登录",
|
|
||||||
"noFoldersFound": "未找到文件夹",
|
|
||||||
"close": "关闭",
|
|
||||||
"addToFolderSuccess": "文本对已添加到文件夹",
|
|
||||||
"addToFolderError": "添加文本对到文件夹失败"
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ interface FolderSelectorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
|
const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
|
||||||
const t = useTranslations("memorize/folder-selector");
|
const t = useTranslations("memorize.folder_selector");
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<Center>
|
<Center>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function UploadArea({
|
|||||||
setVideoUrl: (url: string | null) => void;
|
setVideoUrl: (url: string | null) => void;
|
||||||
setSrtUrl: (url: string | null) => void;
|
setSrtUrl: (url: string | null) => void;
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations("srt-player");
|
const t = useTranslations("srt_player");
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const uploadVideo = () => {
|
const uploadVideo = () => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type VideoPanelProps = {
|
|||||||
|
|
||||||
const VideoPanel = forwardRef<HTMLVideoElement, VideoPanelProps>(
|
const VideoPanel = forwardRef<HTMLVideoElement, VideoPanelProps>(
|
||||||
({ videoUrl, srtUrl }, videoRef) => {
|
({ videoUrl, srtUrl }, videoRef) => {
|
||||||
const t = useTranslations("srt-player");
|
const t = useTranslations("srt_player");
|
||||||
videoRef = videoRef as React.RefObject<HTMLVideoElement>;
|
videoRef = videoRef as React.RefObject<HTMLVideoElement>;
|
||||||
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
||||||
const [srtLength, setSrtLength] = useState<number>(0);
|
const [srtLength, setSrtLength] = useState<number>(0);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ interface SaveListProps {
|
|||||||
handleUse: (item: z.infer<typeof TextSpeakerItemSchema>) => void;
|
handleUse: (item: z.infer<typeof TextSpeakerItemSchema>) => void;
|
||||||
}
|
}
|
||||||
export default function SaveList({ show = false, handleUse }: SaveListProps) {
|
export default function SaveList({ show = false, handleUse }: SaveListProps) {
|
||||||
const t = useTranslations("text-speaker");
|
const t = useTranslations("text_speaker");
|
||||||
const { get: getFromLocalStorage, set: setIntoLocalStorage } =
|
const { get: getFromLocalStorage, set: setIntoLocalStorage } =
|
||||||
getLocalStorageOperator<typeof TextSpeakerArraySchema>(
|
getLocalStorageOperator<typeof TextSpeakerArraySchema>(
|
||||||
"text-speaker",
|
"text-speaker",
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import LightButton from "@/components/buttons/LightButton";
|
|||||||
import IconClick from "@/components/IconClick";
|
import IconClick from "@/components/IconClick";
|
||||||
import IMAGES from "@/config/images";
|
import IMAGES from "@/config/images";
|
||||||
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
|
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
|
||||||
import { TextSpeakerArraySchema, TextSpeakerItemSchema } from "@/lib/interfaces";
|
import {
|
||||||
|
TextSpeakerArraySchema,
|
||||||
|
TextSpeakerItemSchema,
|
||||||
|
} from "@/lib/interfaces";
|
||||||
import { getLocalStorageOperator, getTTSAudioUrl } from "@/lib/utils";
|
import { getLocalStorageOperator, getTTSAudioUrl } from "@/lib/utils";
|
||||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
@@ -14,7 +17,7 @@ import { VOICES } from "@/config/locales";
|
|||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export default function TextSpeakerPage() {
|
export default function TextSpeakerPage() {
|
||||||
const t = useTranslations("text-speaker");
|
const t = useTranslations("text_speaker");
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
const [showSpeedAdjust, setShowSpeedAdjust] = useState(false);
|
const [showSpeedAdjust, setShowSpeedAdjust] = useState(false);
|
||||||
const [showSaveList, setShowSaveList] = useState(false);
|
const [showSaveList, setShowSaveList] = useState(false);
|
||||||
@@ -30,9 +33,11 @@ export default function TextSpeakerPage() {
|
|||||||
const [processing, setProcessing] = useState(false);
|
const [processing, setProcessing] = useState(false);
|
||||||
const { play, stop, load, audioRef } = useAudioPlayer();
|
const { play, stop, load, audioRef } = useAudioPlayer();
|
||||||
|
|
||||||
const { get: getFromLocalStorage, set: setIntoLocalStorage } = getLocalStorageOperator<
|
const { get: getFromLocalStorage, set: setIntoLocalStorage } =
|
||||||
typeof TextSpeakerArraySchema
|
getLocalStorageOperator<typeof TextSpeakerArraySchema>(
|
||||||
>("text-speaker", TextSpeakerArraySchema);
|
"text-speaker",
|
||||||
|
TextSpeakerArraySchema,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const audio = audioRef.current;
|
const audio = audioRef.current;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ interface AddToFolderProps {
|
|||||||
const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
const [folders, setFolders] = useState<folder[]>([]);
|
const [folders, setFolders] = useState<folder[]>([]);
|
||||||
const t = useTranslations("translator.add-to-folder");
|
const t = useTranslations("translator.add_to_folder");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const username = session.data!.user!.name as string;
|
const username = session.data!.user!.name as string;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default function AddTextPairModal({
|
|||||||
onClose,
|
onClose,
|
||||||
onAdd,
|
onAdd,
|
||||||
}: AddTextPairModalProps) {
|
}: AddTextPairModalProps) {
|
||||||
const t = useTranslations("folders.folder_id");
|
const t = useTranslations("folder_id");
|
||||||
const input1Ref = useRef<HTMLInputElement>(null);
|
const input1Ref = useRef<HTMLInputElement>(null);
|
||||||
const input2Ref = useRef<HTMLInputElement>(null);
|
const input2Ref = useRef<HTMLInputElement>(null);
|
||||||
const input3Ref = useRef<HTMLInputElement>(null);
|
const input3Ref = useRef<HTMLInputElement>(null);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function InFolder({ folderId }: { folderId: number }) {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [openAddModal, setAddModal] = useState(false);
|
const [openAddModal, setAddModal] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const t = useTranslations("folders.folder_id");
|
const t = useTranslations("folder_id");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchTextPairs = async () => {
|
const fetchTextPairs = async () => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { updateTextPairById } from "@/lib/services/textPairService";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { text_pairUpdateInput } from "../../../../generated/prisma/models";
|
import { text_pairUpdateInput } from "../../../../generated/prisma/models";
|
||||||
import UpdateTextPairModal from "./UpdateTextPairModal";
|
import UpdateTextPairModal from "./UpdateTextPairModal";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
interface TextPairCardProps {
|
interface TextPairCardProps {
|
||||||
textPair: TextPair;
|
textPair: TextPair;
|
||||||
@@ -17,6 +18,7 @@ export default function TextPairCard({
|
|||||||
refreshTextPairs,
|
refreshTextPairs,
|
||||||
}: TextPairCardProps) {
|
}: TextPairCardProps) {
|
||||||
const [openUpdateModal, setOpenUpdateModal] = useState(false);
|
const [openUpdateModal, setOpenUpdateModal] = useState(false);
|
||||||
|
const t = useTranslations("folder_id");
|
||||||
return (
|
return (
|
||||||
<div className="group border-b border-gray-100 hover:bg-gray-50 transition-colors">
|
<div className="group border-b border-gray-100 hover:bg-gray-50 transition-colors">
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
@@ -35,11 +37,16 @@ export default function TextPairCard({
|
|||||||
<button
|
<button
|
||||||
className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-md transition-colors"
|
className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-md transition-colors"
|
||||||
onClick={() => setOpenUpdateModal(true)}
|
onClick={() => setOpenUpdateModal(true)}
|
||||||
|
title={t("edit")}
|
||||||
>
|
>
|
||||||
<Edit size={14} />
|
<Edit size={14} />
|
||||||
</button>
|
</button>
|
||||||
<button className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-md transition-colors">
|
<button
|
||||||
<Trash2 size={14} onClick={onDel} />
|
className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-md transition-colors"
|
||||||
|
onClick={onDel}
|
||||||
|
title={t("delete")}
|
||||||
|
>
|
||||||
|
<Trash2 size={14} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function UpdateTextPairModal({
|
|||||||
onUpdate,
|
onUpdate,
|
||||||
textPair,
|
textPair,
|
||||||
}: UpdateTextPairModalProps) {
|
}: UpdateTextPairModalProps) {
|
||||||
const t = useTranslations("folders.folder_id");
|
const t = useTranslations("folder_id");
|
||||||
const input1Ref = useRef<HTMLInputElement>(null);
|
const input1Ref = useRef<HTMLInputElement>(null);
|
||||||
const input2Ref = useRef<HTMLInputElement>(null);
|
const input2Ref = useRef<HTMLInputElement>(null);
|
||||||
const input3Ref = useRef<HTMLInputElement>(null);
|
const input3Ref = useRef<HTMLInputElement>(null);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default async function FoldersPage({
|
|||||||
const session = await getServerSession();
|
const session = await getServerSession();
|
||||||
const { folder_id } = await params;
|
const { folder_id } = await params;
|
||||||
const id = Number(folder_id);
|
const id = Number(folder_id);
|
||||||
const t = await getTranslations("folders.folder_id");
|
const t = await getTranslations("folder_id");
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
redirect("/folders");
|
redirect("/folders");
|
||||||
|
|||||||
@@ -1,39 +1,6 @@
|
|||||||
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from "@/config/i18n";
|
import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from "@/config/i18n";
|
||||||
import { getRequestConfig } from "next-intl/server";
|
import { getRequestConfig } from "next-intl/server";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import { readFileSync, readdirSync, statSync } from "fs";
|
|
||||||
import { join } from "path";
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
function loadMessagesFromDir(dirPath: string): Record<string, any> {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const messages: Record<string, any> = {};
|
|
||||||
try {
|
|
||||||
const items = readdirSync(dirPath);
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
const fullPath = join(dirPath, item);
|
|
||||||
const stat = statSync(fullPath);
|
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
|
||||||
const dirMessages = loadMessagesFromDir(fullPath);
|
|
||||||
Object.assign(messages, { [item]: dirMessages });
|
|
||||||
} else if (item.endsWith(".json")) {
|
|
||||||
try {
|
|
||||||
const content = readFileSync(fullPath, "utf-8");
|
|
||||||
const jsonContent = JSON.parse(content);
|
|
||||||
Object.assign(messages, { [item.replace(".json", "")]: jsonContent });
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Failed to load JSON file ${fullPath}:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`Failed to read directory ${dirPath}:`, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default getRequestConfig(async () => {
|
export default getRequestConfig(async () => {
|
||||||
const store = await cookies();
|
const store = await cookies();
|
||||||
@@ -43,11 +10,8 @@ export default getRequestConfig(async () => {
|
|||||||
return locale;
|
return locale;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const messagesPath = join(process.cwd(), "public/messages", locale);
|
|
||||||
const messages = loadMessagesFromDir(messagesPath);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
locale,
|
locale,
|
||||||
messages,
|
messages: (await import(`../../messages/${locale}.json`)).default,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user