diff --git a/public/images/tutorial-grammar-check-example.png b/public/images/tutorial-grammar-check-example.png index 1af16de..f0edbea 100644 Binary files a/public/images/tutorial-grammar-check-example.png and b/public/images/tutorial-grammar-check-example.png differ diff --git a/src/app/chat/components/tutorial-message.tsx b/src/app/chat/components/tutorial-message.tsx index 795ee67..151af0c 100644 --- a/src/app/chat/components/tutorial-message.tsx +++ b/src/app/chat/components/tutorial-message.tsx @@ -8,6 +8,7 @@ import { useAppDispatch } from "@/app/hooks"; import { TutorialStateIDs } from "./tutorial-input"; import { setTutorialState } from "./tutorial-input"; import Image from "next/image"; +import { useRef, useEffect } from 'react'; abstract class TutorialMessageBase extends Message { @@ -53,11 +54,17 @@ export class NonInteractiveTutorialMessage extends TutorialMessageBase { function NonInteractiveTutorialMessageComponent({ message: unTypedMsg, className }: { message: Message, messageID: number, updateMessage: (messageID: number, message: Message) => void, className?: string }) { const message = unTypedMsg as NonInteractiveTutorialMessage + const scrollRef = useRef(null) + + useEffect(() => { + scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) + }, []) return
') }} /> +
} @@ -134,6 +141,11 @@ function NextStepTutorialMessageComponent({ message: unTypedMsg, className }: { const { t } = useTranslation() const dispatch = useAppDispatch(); const tutorialState = useAppSelector(state => state.tutorialState); + const scrollRef = useRef(null) + + useEffect(() => { + scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) + }, []) const message = unTypedMsg as NextStepTutorialMessage @@ -152,13 +164,19 @@ function NextStepTutorialMessageComponent({ message: unTypedMsg, className }: { {t('Next Step')} } +
} // message for indicating users to click on Translation icon -function QueClickOnTranslationMsgComponent({ className }: { className?: string }) { +function IndicateClickOnTranslationMsgComponent({ className }: { className?: string }) { const { t } = useTranslation() + const scrollRef = useRef(null) + + useEffect(() => { + scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) + }, []) const tutorialMsg1 = t("假设你正在练习线上会议中的常用表达,这时 AI 问了你一个问题:") const aiMsg = t("What do you think about these suggestions?") @@ -187,8 +205,9 @@ function QueClickOnTranslationMsgComponent({ className }: { className?: string }
') }} />
') }} /> - tutorial-2-2 + tutorial-2-2
+
@@ -202,7 +221,7 @@ export class QueClickOnTranslationMsg extends TutorialMessageBase { } component() { - return QueClickOnTranslationMsgComponent + return IndicateClickOnTranslationMsgComponent } static deserialize(): QueClickOnTranslationMsg { diff --git a/src/app/i18n/i18n.tsx b/src/app/i18n/i18n.tsx index 72cad07..ef50727 100644 --- a/src/app/i18n/i18n.tsx +++ b/src/app/i18n/i18n.tsx @@ -301,19 +301,19 @@ i18n '这里可以用 extract 吗?': '这里可以用 extract 吗?', 'extract 虽然也有"提取"的意思,但在这个会议场景下不是最佳选择。让我解释一下原因:\n……(略)': 'extract 虽然也有"提取"的意思,但在这个会议场景下不是最佳选择。让我解释一下原因:\n……(略)', '就像上面这样,并且在子对话中的讨论不会影响上一层对话。\n\n现在我们要结束子对话,点击下左侧的 ">" 按钮,即可返回上一层对话。': '就像上面这样,并且在子对话中的讨论不会影响上一层对话。\n\n现在我们要结束子对话,点击下左侧的 ">" 按钮,即可返回上一层对话。', - "BabelDuck 是一款面向各水平层次语言学习者的 AI 口语对话练习应用。除了普通的 AI 对话聊天能力外,我们还提供了一系列为口语练习场景而设计的工具,本教程将为你简单介绍如何使用它们。若你更倾向于自行摸索,可以点击左下角「新建对话」,即可开始体验,之后你依然随时可以回来继续该教程。": "BabelDuck 是一款面向各水平层次语言学习者的 AI 口语对话练习应用。除了普通的 AI 对话聊天能力外,我们还提供了一系列为口语练习场景而设计的工具,本教程将为你简单介绍如何使用它们。若你更倾向于自行摸索,可以点击左下角「新建对话」,即可开始体验,之后你依然随时可以回来继续该教程。", - "BabelDuck 提供了一系列快捷指令,协助用户在口语表达上遇到困难时更流畅地推进对话。\n比如有些人练习初期很容易遇到\"卡壳\"的情况,完全不知道某句话该如何表达时,不得不切出去寻求其他工具的帮助。为此系统内置了一个快捷指令,作为初期过渡工具用,允许你先用母语表达一遍,然后帮你转换为对应语言。\n\n接下来我们简单演示下使用方法": "BabelDuck 提供了一系列快捷指令,协助用户在口语表达上遇到困难时更流畅地推进对话。\n比如有些人练习初期很容易遇到\"卡壳\"的情况,完全不知道某句话该如何表达时,不得不切出去寻求其他工具的帮助。为此系统内置了一个快捷指令,作为初期过渡工具用,允许你先用母语表达一遍,然后帮你转换为对应语言。\n\n接下来我们简单演示下使用方法", + "BabelDuck 是一款面向各水平层次语言学习者的 AI 口语对话练习应用。除了普通的 AI 对话聊天能力外,我们还提供了一系列为口语练习场景而设计的工具,本教程将为你简单介绍如何使用它们。若你更倾向于自行摸索,可以点击左下角「新建对话」,即可开始体验,之后你依然随时可以回来继续该教程。": "BabelDuck 是一款 AI 口语对话练习应用,在这个基础上我们还提供了一系列为口语练习辅助工具,本教程将为你简单介绍如何使用它们。\n或者你也可以直接点击左下角「新建对话」,直接开始体验。", + "BabelDuck 提供了一系列快捷指令,协助用户在口语表达上遇到困难时更流畅地推进对话。\n比如有些人练习初期很容易遇到\"卡壳\"的情况,完全不知道某句话该如何表达时,不得不切出去寻求其他工具的帮助。为此系统内置了一个快捷指令,作为初期过渡工具用,允许你先用母语表达一遍,然后帮你转换为对应语言。\n\n接下来我们简单演示下使用方法": "BabelDuck 提供了一系列快捷指令,协助用户在口语表达上遇到困难时更流畅地推进对话。\n\n接下来我们简单演示下使用方法。", "在子对话中,你可以在当前对话的基础上,向 AI 追问更多问题。": "在子对话中,你可以在当前对话的基础上,向 AI 追问更多问题。", - "以上便是 BabelDuck 中其中一个快捷指令的基本使用流程,除此之外,我们还提供了其他一系列快捷指令。": "以上便是 BabelDuck 中其中一个快捷指令的基本使用流程,除此之外,我们还提供了其他一系列快捷指令。", + "以上便是 BabelDuck 中其中一个快捷指令的基本使用流程,除此之外,我们还提供了其他一系列快捷指令。": "以上便是快捷指令的基本使用流程,除了翻译指令,我们还提供了其他一系列快捷指令。", "比如常见的语法纠正需求,也有对应的内置指令,效果如下:\n": "比如常见的语法纠正需求,也有对应的内置指令,效果如下:\n", - "\n除此之外,除了内置的快捷指令,你还可以根据自身需求自定义指令。": "\n除此之外,除了内置的快捷指令,你还可以根据自身需求自定义指令。", + "\n除此之外,除了内置的快捷指令,你还可以根据自身需求自定义指令。": "\n并且除了内置的快捷指令,你还可以根据自身需求自定义指令。", "比如说你的口语水平已经达到了一定的流畅度,只是偶尔有些词汇的表达方式不够地道,那么你可以自定义一个快捷指令:\n": "比如说你的口语水平已经达到了一定的流畅度,只是偶尔有些词汇的表达方式不够地道,那么你可以自定义一个快捷指令:\n", "\n鉴于自定义指令的使用流程与内置指令类似,我们就不再详细演示整个流程了。": "\n鉴于自定义指令的使用流程与内置指令类似,我们就不再详细演示整个流程了。", "假设你正在练习线上会议中的常用表达,这时 AI 问了你一个问题:": "假设你正在练习线上会议中的常用表达,这时 AI 问了你一个问题:", "What do you think about these suggestions?": "What do you think about these suggestions?", "假设你想回复 \"东西有点多,我晚点提炼一下\",但不知道如何表达,那么就可以通过快捷指令求助另一个 AI\n": "假设你想回复 \"东西有点多,我晚点提炼一下\",但不知道如何表达,那么就可以通过快捷指令求助另一个 AI\n", "现在点一下这个图标试试": "现在点一下这个图标试试", - "tutorialEndingSummary": `有了自定义快捷指令,你便可以根据自身需求,打造一套属于自己的工具链:\n\n- 比如在模拟面试中让 AI 协助回答不会的问题,无需切换到其他窗口查询资料;\n- 或者让 AI 提炼句子中的短语,并提供一些同义词,扩充自己的词汇量;\n- 甚至在未来的更新中,你还将能够通过快捷指令与外部系统进行联动,例如自动将词汇添加到生词本,等等。\n\n至此,我们便完成了对快捷指令功能的基本介绍,另外为了简化教程,我们在教程中还省略了语音输入、消息编辑、对话配置等功能的介绍,你现在可以尝试新建一个普通的对话,来体验这些功能了。\n\n本教程到此便结束了,希望你能有所收获,并期待你的反馈!`, + "tutorialEndingSummary": `有了自定义快捷指令,你便可以根据自身需求,打造一套属于自己的工具链:\n\n- 比如在模拟面试中让 AI 协助回答不会的问题;\n- 或者让 AI 提炼句子中的短语,并提供一些同义词,扩充自己的词汇量;\n- 甚至在未来的更新中,你还将能够通过快捷指令与外部系统进行联动,例如自动将词汇添加到生词本,等等。\n\n以上便是对快捷指令功能的基本介绍,除此之外 BabelDuck 还包含语音录入、自动播放语音、消息编辑等更多功能,你现在可以新建一个对话自由探索这些功能了!`, 'tooltip.diffViewText': '弹窗中即 AI 提供的翻译结果,与普通网页翻译工具不同的是,快捷指令会结合对话上下文,给出更符合当前语境的建议。', 'tooltip.diffViewText2': '例如在这个场景下,你不需要担心 AI 会以为你说的是什么化学物质的提炼,而是根据"会议"这个上下文来翻译。', 'tooltip.approveButton': '现在,点击 「采纳」 按钮,采纳 AI 提供的结果。',