diff --git a/website/public/locales/en/common.json b/website/public/locales/en/common.json index d18e5d91..8f35eaab 100644 --- a/website/public/locales/en/common.json +++ b/website/public/locales/en/common.json @@ -14,5 +14,6 @@ "sign_in": "Sign In", "sign_out": "Sign Out", "terms_of_service": "Terms of Service", - "title": "Open Assistant" + "title": "Open Assistant", + "more_information": "More Information" } diff --git a/website/public/locales/en/dashboard.json b/website/public/locales/en/dashboard.json new file mode 100644 index 00000000..0427fb0d --- /dev/null +++ b/website/public/locales/en/dashboard.json @@ -0,0 +1,8 @@ +{ + "grab_a_task": "Grab a task!", + "create": "Create", + "evaluate": "Evaluate", + "label": "Label", + "dashboard": "Dashboard", + "go": "Go" +} diff --git a/website/public/locales/en/tasks.json b/website/public/locales/en/tasks.json new file mode 100644 index 00000000..553a26d2 --- /dev/null +++ b/website/public/locales/en/tasks.json @@ -0,0 +1,79 @@ +{ + "write_initial_prompt": "Write your prompt here...", + "default": { + "unchanged_title": "No changes", + "unchanged_message": "Are you sure you would like to continue?" + }, + "random": { + "label": "I'm feeling lucky", + "desc": "Help us improve Open Assistant by starting a random task." + }, + "create_initial_prompt": { + "label": "Create Initial Prompts", + "desc": "Write initial prompts to help Open Assistant to try replying to diverse messages.", + "overview": "Create an initial message to send to the assistant", + "instruction": "Provide the initial prompts" + }, + "reply_as_user": { + "label": "Reply as User", + "desc": "Chat with Open Assistant and help improve it's responses as you interact with it.", + "overview": "Given the following conversation, provide an adequate reply", + "instruction": "Provide the user's reply" + }, + "reply_as_assistant": { + "label": "Reply as Assistant", + "desc": "Help Open Assistant improve its responses to conversations with other users.", + "overview": "Given the following conversation, provide an adequate reply" + }, + "rank_user_replies": { + "label": "Rank User Replies", + "desc": "Help Open Assistant improve its responses to conversations with other users.", + "overview": "Given the following User replies, sort them from best to worst, best being first, worst being last.", + "unchanged_title": "Order Unchanged", + "unchanged_message": "You have not changed the order of the prompts. Are you sure you would like to continue?" + }, + "rank_assistant_replies": { + "label": "Rank Assistant Replies", + "desc": "Score prompts given by Open Assistant based on their accuracy and readability.", + "overview": "Given the following Assistant replies, sort them from best to worst, best being first, worst being last.", + "unchanged_title": "Order Unchanged", + "unchanged_message": "You have not changed the order of the prompts. Are you sure you would like to continue?" + }, + "rank_initial_prompts": { + "label": "Rank Initial Prompts", + "desc": "Score prompts given by Open Assistant based on their accuracy and readability.", + "overview": "Given the following initial prompts, sort them from best to worst, best being first, worst being last.", + "unchanged_title": "Order Unchanged", + "unchanged_message": "You have not changed the order of the prompts. Are you sure you would like to continue?" + }, + "label_initial_prompt": { + "label": "Label Initial Prompt", + "desc": "Provide labels for a prompt.", + "overview": "Provide labels for the following prompt" + }, + "label_prompter_reply": { + "label": "Label Prompter Reply", + "desc": "Provide labels for a prompt.", + "overview": "Given the following discussion, provide labels for the final prompt." + }, + "label_assistant_reply": { + "label": "Label Assistant Reply", + "desc": "Provide labels for a prompt.", + "overview": "Given the following discussion, provide labels for the final prompt." + }, + "classify_initial_prompt": { + "label": "Classify Initial Prompt", + "desc": "Provide labels for a prompt.", + "overview": "Read the following prompt and then answer the question about it." + }, + "classify_prompter_reply": { + "label": "Classify Prompter Reply", + "desc": "Provide labels for a prompt.", + "overview": "Read the following conversation and then answer the question about the last reply in the discussion." + }, + "classify_assistant_reply": { + "label": "Classify Assistant Reply", + "desc": "Provide labels for a prompt.", + "overview": "Read the following conversation and then answer the question about the last reply in the discussion." + } +} diff --git a/website/src/components/Dashboard/TaskOption.tsx b/website/src/components/Dashboard/TaskOption.tsx index fd4bef2b..3497d14c 100644 --- a/website/src/components/Dashboard/TaskOption.tsx +++ b/website/src/components/Dashboard/TaskOption.tsx @@ -12,7 +12,9 @@ import { } from "@chakra-ui/react"; import { HelpCircle } from "lucide-react"; import Link from "next/link"; +import { useTranslation } from "next-i18next"; import { useMemo } from "react"; +import { getTypeSafei18nKey } from "src/lib/i18n"; import { TaskType } from "src/types/Task"; import { TaskCategory, TaskCategoryLabels, TaskInfo, TaskInfos } from "../Tasks/TaskTypes"; @@ -22,6 +24,7 @@ export interface TasksOptionProps { } export const TaskOption = ({ content }: TasksOptionProps) => { + const { t } = useTranslation(["dashboard", "tasks"]); const backgroundColor = useColorModeValue("white", "gray.700"); const taskInfoMap = useMemo( @@ -41,7 +44,7 @@ export const TaskOption = ({ content }: TasksOptionProps) => {
- {TaskCategoryLabels[category]} + {t(TaskCategoryLabels[category])} @@ -52,7 +55,7 @@ export const TaskOption = ({ content }: TasksOptionProps) => { {taskTypes .map((taskType) => taskInfoMap[taskType]) .map((item) => ( - + { className="flex flex-col justify-between h-full" > - {item.label} - {item.desc} + {t(getTypeSafei18nKey(`tasks:${item.id}.label`))} + {t(getTypeSafei18nKey(`tasks:${item.id}.desc`))} { borderBottomRadius="xl" className="px-6 py-2 transition-colors duration-300 bg-blue-500 hover:bg-blue-600" > - Go -> + {t("go")} -> diff --git a/website/src/components/Tasks/CreateTask.tsx b/website/src/components/Tasks/CreateTask.tsx index 647bed4f..36493e27 100644 --- a/website/src/components/Tasks/CreateTask.tsx +++ b/website/src/components/Tasks/CreateTask.tsx @@ -1,10 +1,12 @@ import { Box, Stack, Text, useColorModeValue } from "@chakra-ui/react"; +import { useTranslation } from "next-i18next"; import { useState } from "react"; import { MessageTable } from "src/components/Messages/MessageTable"; import { TrackedTextarea } from "src/components/Survey/TrackedTextarea"; import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards"; import { TaskSurveyProps } from "src/components/Tasks/Task"; import { TaskHeader } from "src/components/Tasks/TaskHeader"; +import { getTypeSafei18nKey } from "src/lib/i18n"; export const CreateTask = ({ task, @@ -14,14 +16,15 @@ export const CreateTask = ({ onReplyChanged, onValidityChanged, }: TaskSurveyProps<{ text: string }>) => { + const { t, i18n } = useTranslation(["tasks", "common"]); const cardColor = useColorModeValue("gray.50", "gray.800"); const titleColor = useColorModeValue("gray.800", "gray.300"); - const [inputText, setInputText] = useState(""); + const textChangeHandler = (event: React.ChangeEvent) => { const text = event.target.value; - const isTextBlank = !text || /^\s*$/.test(text) ? true : false; onReplyChanged({ text }); + const isTextBlank = !text || /^\s*$/.test(text); if (!isTextBlank) { onValidityChanged("VALID"); setInputText(text); @@ -36,22 +39,24 @@ export const CreateTask = ({ <> - {task.conversation ? ( + {!!task.conversation && ( - ) : null} + )} <> - - {taskType.instruction} - + {!!i18n.exists(`task.${taskType.id}.instruction`) && ( + + {t(getTypeSafei18nKey(`${taskType.id}.instruction`))} + + )} diff --git a/website/src/components/Tasks/Task/Task.tsx b/website/src/components/Tasks/Task/Task.tsx index b16711e6..ae82ef97 100644 --- a/website/src/components/Tasks/Task/Task.tsx +++ b/website/src/components/Tasks/Task/Task.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from "next-i18next"; import { useRef, useState } from "react"; import { TaskControls } from "src/components/Survey/TaskControls"; import { CreateTask } from "src/components/Tasks/CreateTask"; @@ -6,6 +7,7 @@ import { LabelTask } from "src/components/Tasks/LabelTask"; import { TaskCategory, TaskInfo, TaskInfos } from "src/components/Tasks/TaskTypes"; import { UnchangedWarning } from "src/components/Tasks/UnchangedWarning"; import { post } from "src/lib/api"; +import { getTypeSafei18nKey } from "src/lib/i18n"; import { TaskContent, TaskReplyValidity } from "src/types/Task"; import useSWRMutation from "swr/mutation"; @@ -23,6 +25,7 @@ export interface TaskSurveyProps { } export const Task = ({ frontendId, task, trigger, mutate }) => { + const { t } = useTranslation("tasks"); const [taskStatus, setTaskStatus] = useState("NOT_SUBMITTABLE"); const replyContent = useRef(null); const [showUnchangedWarning, setShowUnchangedWarning] = useState(false); @@ -111,7 +114,6 @@ export const Task = ({ frontendId, task, trigger, mutate }) => { case TaskCategory.Create: return ( { case TaskCategory.Evaluate: return ( { case TaskCategory.Label: return ( { /> setShowUnchangedWarning(false)} onContinueAnyway={() => { diff --git a/website/src/components/Tasks/TaskHeader/TaskHeader.tsx b/website/src/components/Tasks/TaskHeader/TaskHeader.tsx index b2dbd817..c4095eb8 100644 --- a/website/src/components/Tasks/TaskHeader/TaskHeader.tsx +++ b/website/src/components/Tasks/TaskHeader/TaskHeader.tsx @@ -1,6 +1,8 @@ import { HStack, IconButton, Link, Stack, Text, useColorModeValue } from "@chakra-ui/react"; import { HelpCircle } from "lucide-react"; +import { useTranslation } from "next-i18next"; import type { TaskInfo } from "src/components/Tasks/TaskTypes"; +import { getTypeSafei18nKey } from "src/lib/i18n"; interface TaskHeaderProps { /** @@ -13,20 +15,21 @@ interface TaskHeaderProps { * Presents the Task label, instructions, and help link */ const TaskHeader = ({ taskType }: TaskHeaderProps) => { + const { t } = useTranslation(["tasks", "common"]); const labelColor = useColorModeValue("gray.600", "gray.400"); const titleColor = useColorModeValue("gray.800", "gray.300"); return ( - {taskType.label} + {t(getTypeSafei18nKey(`${taskType.id}.label`))} } /> - {taskType.overview} + {t(getTypeSafei18nKey(`${taskType.id}.overview`))} ); diff --git a/website/src/components/Tasks/TaskTypes.tsx b/website/src/components/Tasks/TaskTypes.tsx index cfa5982a..e2a53d23 100644 --- a/website/src/components/Tasks/TaskTypes.tsx +++ b/website/src/components/Tasks/TaskTypes.tsx @@ -1,181 +1,150 @@ +import { TaskType } from "src/types/Task"; + export enum TaskCategory { - Random = "Random", Create = "Create", Evaluate = "Evaluate", Label = "Label", + Random = "Random", +} + +export enum TaskUpdateType { + MessageRanking = "message_ranking", + Random = "random", + TextLabels = "text_labels", + TextReplyToMessage = "text_reply_to_message", } export interface TaskInfo { - label: string; - desc: string; category: TaskCategory; + help_link: string; + id: string; + mode?: string; pathname: string; type: string; - help_link: string; - mode?: string; - overview?: string; - instruction?: string; update_type: string; - unchanged_title?: string; - unchanged_message?: string; } export const TaskCategoryLabels: { [key in TaskCategory]: string } = { - [TaskCategory.Random]: "Grab a task!", - [TaskCategory.Create]: "Create", - [TaskCategory.Evaluate]: "Evaluate", - [TaskCategory.Label]: "Label", + [TaskCategory.Random]: "grab_a_task", + [TaskCategory.Create]: "create", + [TaskCategory.Evaluate]: "evaluate", + [TaskCategory.Label]: "label", }; export const TaskInfos: TaskInfo[] = [ // general/random { - label: "I'm feeling lucky", - desc: "Help us improve Open Assistant by starting a random task.", + id: "random", category: TaskCategory.Random, pathname: "/tasks/random", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - type: "random", - update_type: "random", + type: TaskType.random, + update_type: TaskUpdateType.Random, }, // create { - label: "Create Initial Prompts", - desc: "Write initial prompts to help Open Assistant to try replying to diverse messages.", + id: "create_initial_prompt", category: TaskCategory.Create, pathname: "/create/initial_prompt", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - type: "initial_prompt", - overview: "Create an initial message to send to the assistant", - instruction: "Provide the initial prompt", - update_type: "text_reply_to_message", + type: TaskType.initial_prompt, + update_type: TaskUpdateType.TextReplyToMessage, }, { - label: "Reply as User", - desc: "Chat with Open Assistant and help improve it’s responses as you interact with it.", + id: "reply_as_user", category: TaskCategory.Create, pathname: "/create/user_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/tasks/reply_as_user", - type: "prompter_reply", - overview: "Given the following conversation, provide an adequate reply", - instruction: "Provide the user's reply", - update_type: "text_reply_to_message", + type: TaskType.prompter_reply, + update_type: TaskUpdateType.TextReplyToMessage, }, { - label: "Reply as Assistant", - desc: "Help Open Assistant improve its responses to conversations with other users.", + id: "reply_as_assistant", category: TaskCategory.Create, pathname: "/create/assistant_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/tasks/reply_as_assistant", - type: "assistant_reply", - overview: "Given the following conversation, provide an adequate reply", - instruction: "Provide the assistant's reply", - update_type: "text_reply_to_message", + type: TaskType.assistant_reply, + update_type: TaskUpdateType.TextReplyToMessage, }, // evaluate { - label: "Rank User Replies", + id: "rank_user_replies", category: TaskCategory.Evaluate, - desc: "Help Open Assistant improve its responses to conversations with other users.", pathname: "/evaluate/rank_user_replies", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Given the following User replies, sort them from best to worst, best being first, worst being last.", - type: "rank_prompter_replies", - update_type: "message_ranking", - unchanged_title: "Order Unchanged", - unchanged_message: "You have not changed the order of the prompts. Are you sure you would like to continue?", + type: TaskType.rank_prompter_replies, + update_type: TaskUpdateType.MessageRanking, }, { - label: "Rank Assistant Replies", - desc: "Score prompts given by Open Assistant based on their accuracy and readability.", + id: "rank_assistant_replies", category: TaskCategory.Evaluate, pathname: "/evaluate/rank_assistant_replies", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: - "Given the following Assistant replies, sort them from best to worst, best being first, worst being last.", - type: "rank_assistant_replies", - update_type: "message_ranking", - unchanged_title: "Order Unchanged", - unchanged_message: "You have not changed the order of the prompts. Are you sure you would like to continue?", + type: TaskType.rank_assistant_replies, + update_type: TaskUpdateType.MessageRanking, }, { - label: "Rank Initial Prompts", - desc: "Score prompts given by Open Assistant based on their accuracy and readability.", + id: "rank_initial_prompts", category: TaskCategory.Evaluate, pathname: "/evaluate/rank_initial_prompts", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Given the following initial prompts, sort them from best to worst, best being first, worst being last.", - type: "rank_initial_prompts", - update_type: "message_ranking", - unchanged_title: "Order Unchanged", - unchanged_message: "You have not changed the order of the prompts. Are you sure you would like to continue?", + type: TaskType.rank_initial_prompts, + update_type: TaskUpdateType.MessageRanking, }, // label (full) { - label: "Label Initial Prompt", - desc: "Provide labels for a prompt.", + id: "label_initial_prompt", category: TaskCategory.Label, pathname: "/label/label_initial_prompt", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Provide labels for the following prompt", - type: "label_initial_prompt", + type: TaskType.label_initial_prompt, mode: "full", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, { - label: "Label Prompter Reply", - desc: "Provide labels for a prompt.", + id: "label_prompter_reply", category: TaskCategory.Label, pathname: "/label/label_prompter_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/tasks/label_prompter_reply", - overview: "Given the following discussion, provide labels for the final prompt.", - type: "label_prompter_reply", + type: TaskType.label_prompter_reply, mode: "full", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, { - label: "Label Assistant Reply", - desc: "Provide labels for a prompt.", + id: "label_assistant_reply", category: TaskCategory.Label, pathname: "/label/label_assistant_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/tasks/label_assistant_reply", - overview: "Given the following discussion, provide labels for the final prompt.", - type: "label_assistant_reply", + type: TaskType.label_assistant_reply, mode: "full", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, // label (simple) { - label: "Classify Initial Prompt", - desc: "Provide labels for a prompt.", + id: "classify_initial_prompt", category: TaskCategory.Label, pathname: "/label/label_initial_prompt", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Read the following prompt and then answer the question about it.", - type: "label_initial_prompt", + type: TaskType.label_initial_prompt, mode: "simple", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, { - label: "Classify Prompter Reply", - desc: "Provide labels for a prompt.", + id: "classify_prompter_reply", category: TaskCategory.Label, pathname: "/label/label_prompter_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Read the following conversation and then answer the question about the last reply in the discussion.", - type: "label_prompter_reply", + type: TaskType.label_prompter_reply, mode: "simple", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, { - label: "Classify Assistant Reply", - desc: "Provide labels for a prompt.", + id: "classify_assistant_reply", category: TaskCategory.Label, pathname: "/label/label_assistant_reply", help_link: "https://projects.laion.ai/Open-Assistant/docs/guides/prompting", - overview: "Read the following conversation and then answer the question about the last reply in the discussion.", - type: "label_assistant_reply", + type: TaskType.label_assistant_reply, mode: "simple", - update_type: "text_labels", + update_type: TaskUpdateType.TextLabels, }, ]; diff --git a/website/src/lib/i18n.ts b/website/src/lib/i18n.ts new file mode 100644 index 00000000..72712d27 --- /dev/null +++ b/website/src/lib/i18n.ts @@ -0,0 +1 @@ +export const getTypeSafei18nKey = (key: string) => key as unknown as TemplateStringsArray; diff --git a/website/src/pages/dashboard.tsx b/website/src/pages/dashboard.tsx index 17e04c8a..35c254a4 100644 --- a/website/src/pages/dashboard.tsx +++ b/website/src/pages/dashboard.tsx @@ -12,8 +12,9 @@ import useSWR from "swr"; const Dashboard = () => { const { + t, i18n: { language }, - } = useTranslation(); + } = useTranslation(["dashboard", "common", "tasks"]); const [activeLang, setLang] = useState(null); const { data, mutate: fetchTasks } = useSWR("/api/available_tasks", get, { refreshInterval: 2 * 60 * 1000, //2 minutes @@ -36,7 +37,7 @@ const Dashboard = () => { return ( <> - Dashboard - Open Assistant + {`${t("dashboard")} - ${t("common:title")}`} @@ -54,6 +55,6 @@ export default Dashboard; const filterAvailableTasks = (availableTasks: Partial) => Object.entries(availableTasks) - .filter(([_, count]) => count > 0) + .filter(([, count]) => count > 0) .sort((a, b) => b[1] - a[1]) .map(([taskType]) => taskType) as TaskType[]; diff --git a/website/src/pages/leaderboard.tsx b/website/src/pages/leaderboard.tsx index 18f64bac..c4d317b1 100644 --- a/website/src/pages/leaderboard.tsx +++ b/website/src/pages/leaderboard.tsx @@ -11,23 +11,22 @@ const Leaderboard = () => { return ( <> - {`${t("leaderboard:leaderboard")} - ${t("common:title")}`} + {`${t("leaderboard")} - ${t("common:title")}`} - {t("leaderboard:leaderboard")} + {t("leaderboard")} - {t("leaderboard:daily")} - {t("leaderboard:weekly")} - {t("leaderboard:monthly")} - {t("leaderboard:overall")} + {t("daily")} + {t("weekly")} + {t("monthly")} + {t("overall")} - diff --git a/website/types/i18next.d.ts b/website/types/i18next.d.ts index 9c447c2c..873101fd 100644 --- a/website/types/i18next.d.ts +++ b/website/types/i18next.d.ts @@ -1,15 +1,19 @@ import "i18next"; -import type common from "../public/locales/en/common.json"; -import type index from "../public/locales/en/index.json"; -import type leaderboard from "../public/locales/en/leaderboard.json"; +import type common from "public/locales/en/common.json"; +import type dashboard from "public/locales/en/dashboard.json"; +import type index from "public/locales/en/index.json"; +import type leaderboard from "public/locales/en/leaderboard.json"; +import type tasks from "public/locales/en/tasks.json"; declare module "i18next" { interface CustomTypeOptions { resources: { common: typeof common; + dashboard: typeof dashboard; index: typeof index; leaderboard: typeof leaderboard; + tasks: typeof tasks; }; } }