feat: more translation

This commit is contained in:
Tristan Yang
2022-11-25 11:27:01 +08:00
parent 4c85d50f0e
commit 79832fefe3
8 changed files with 68 additions and 31 deletions
+24 -1
View File
@@ -5,5 +5,28 @@
"start_by_channel": "Create a Channel to Start a Conversation",
"start_by_dm": "Send a Direct Message",
"download": "Download Mobile apps",
"help": "Got questions? Visit our help center"
"help": "Got questions? Visit our help center",
"onboarding": {
"title": "VoceChat Setup",
"welcome": "Welcome to your VoceChat!",
"welcome_desc": "Everything in this space is owned by you. Lets set up your space!",
"start": "Start",
"new_server": "Create a new server",
"server_desc": "Servers are shared environments where teams can work on projects and chat.",
"placeholder_server": "Enter server name",
"create_server": "Create Server",
"admin_title": "Now lets set up your admin account",
"admin_desc": "You are the 1st user and admin of your space!",
"sign": "Sign Up",
"invite_title": "Last step: invite others!",
"invite_desc": "Firstly, who can sign up to this server?",
"confirm": "Confirm",
"done_welcome": "Welcome to {{serverName}}",
"done_title": "Proudly presented by VoceChat",
"done_desc": "More settings, including domain resolution, privileges, securities, and invites are available in <0>Settings</0>",
"enter": "Enter",
"last_tip": "Now lets invite others!",
"last_desc": "Send invitation link to your future community members:",
"done": "Done"
}
}
+6 -5
View File
@@ -10,6 +10,7 @@ import InviteLink from "./steps/inviteLink";
import DonePage from "./steps/donePage";
import useServerSetup, { steps } from "./useServerSetup";
import StyledOnboardingPage from "./styled";
import { useTranslation } from "react-i18next";
interface Props {
step: string;
@@ -17,6 +18,7 @@ interface Props {
}
const Navigator: FC<Props> = ({ step, setStep }) => {
const index = steps.map((value) => value.name).indexOf(step);
const canJumpTo = steps.find((value) => value.name === step)?.canJumpTo || [];
@@ -24,9 +26,8 @@ const Navigator: FC<Props> = ({ step, setStep }) => {
<div className="navigator">
{steps.map((stepToRender, indexToRender) => {
const clickable = canJumpTo.includes(stepToRender.name);
const nodeCls = `node ${indexToRender === index ? "emphasized" : ""} ${
indexToRender > index ? "disabled" : ""
} ${clickable ? "clickable" : ""}`;
const nodeCls = `node ${indexToRender === index ? "emphasized" : ""} ${indexToRender > index ? "disabled" : ""
} ${clickable ? "clickable" : ""}`;
const arrowCls = `arrow ${indexToRender >= index ? "disabled" : ""}`;
return (
<React.Fragment key={indexToRender}>
@@ -49,12 +50,12 @@ const Navigator: FC<Props> = ({ step, setStep }) => {
};
export default function OnboardingPage() {
const { t } = useTranslation("welcome");
const serverSetup = useServerSetup();
return (
<>
<Helmet>
<title>VoceChat Setup</title>
<title>{t("onboarding.title")}</title>
</Helmet>
<StyledOnboardingPage>
<Navigator {...serverSetup} />
+5 -3
View File
@@ -12,6 +12,7 @@ import {
import { useLoginMutation } from "../../../app/services/auth";
import { updateInitialized } from "../../../app/slices/auth.data";
import { useAppSelector } from "../../../app/store";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -68,6 +69,7 @@ type Props = {
nextStep: () => void;
};
const AdminAccount: FC<Props> = ({ serverName, nextStep }) => {
const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
const loggedIn = useAppSelector((store) => !!store.authData.token);
const dispatch = useDispatch();
@@ -112,8 +114,8 @@ const AdminAccount: FC<Props> = ({ serverName, nextStep }) => {
return (
<StyledWrapper>
<span className="primaryText">Now lets set up your admin account</span>
<span className="secondaryText">You are the 1st user and admin of your space!</span>
<span className="primaryText">{t("admin_title")}</span>
<span className="secondaryText">{t("admin_desc")}</span>
<StyledInput
className="input"
placeholder="Enter your email"
@@ -161,7 +163,7 @@ const AdminAccount: FC<Props> = ({ serverName, nextStep }) => {
});
}}
>
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? "Sign Up" : "..."}
{!(isSigningUp || isLoggingIn || isUpdatingServer) ? t("sign") : "..."}
</StyledButton>
</StyledWrapper>
);
+8 -5
View File
@@ -2,6 +2,7 @@ import styled from "styled-components";
import { useNavigate } from "react-router-dom";
import StyledButton from "../../../common/component/styled/Button";
import PlayIcon from "../../../assets/icons/play.svg?url";
import { Trans, useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -58,19 +59,21 @@ const StyledWrapper = styled.div`
`;
export default function DonePage({ serverName }: { serverName: string }) {
const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
const navigate = useNavigate();
return (
<StyledWrapper>
<span className="primaryText">Welcome to {serverName}</span>
<span className="secondaryText">Proudly presented by VoceChat</span>
<span className="primaryText">{t("done_welcome", { serverName })}</span>
<span className="secondaryText">{t("done_title")}</span>
<span className="tip">
More settings, including domain resolution, privileges, securities, and invites are
available in <span className="strong">Settings</span>
<Trans i18nKey={"onboarding.done_desc"} ns={"welcome"}>
<span className="strong" />
</Trans>
</span>
<StyledButton className="startButton" onClick={() => navigate("/")}>
<img src={PlayIcon} alt="play icon" />
<span>Enter</span>
<span>{t("enter")}</span>
</StyledButton>
</StyledWrapper>
);
+8 -6
View File
@@ -2,6 +2,7 @@ import styled from "styled-components";
import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
import useInviteLink from "../../../common/hook/useInviteLink";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -74,21 +75,22 @@ const StyledWrapper = styled.div`
`;
export default function InviteLink({ nextStep }: { nextStep: () => void }) {
const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
const { t: ct } = useTranslation();
const { link, linkCopied, copyLink } = useInviteLink();
return (
<StyledWrapper>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Now lets invite others!</span>
<span className="tip">Send invitation link to your future community members:</span>
<span className="primaryText">{t("invite_title")}</span>
<span className="secondaryText">{t("last_tip")}</span>
<span className="tip">{t("last_desc")}</span>
<div className="link">
<StyledInput className="large" readOnly placeholder="Generating" value={link} />
<StyledButton onClick={copyLink} className="ghost small border_less">
{linkCopied ? "Copied" : `Copy`}
{linkCopied ? "Copied" : ct("action.copy")}
</StyledButton>
</div>
<StyledButton className="button" onClick={nextStep}>
Done
{t("done")}
</StyledButton>
</StyledWrapper>
);
+6 -4
View File
@@ -3,6 +3,7 @@ import styled from "styled-components";
import toast from "react-hot-toast";
import StyledInput from "../../../common/component/styled/Input";
import StyledButton from "../../../common/component/styled/Button";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -51,15 +52,16 @@ type Props = {
nextStep: () => void;
};
const ServerName: FC<Props> = ({ serverName, setServerName, nextStep }) => {
const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
return (
<StyledWrapper>
<span className="primaryText">Create a new server</span>
<span className="primaryText">{t("new_server")}</span>
<span className="secondaryText">
Servers are shared environments where teams can work on projects and chat.
{t("server_desc")}
</span>
<StyledInput
className="input"
placeholder="Enter server name"
placeholder={t("placeholder_server")}
value={serverName}
onChange={(e) => setServerName(e.target.value)}
/>
@@ -74,7 +76,7 @@ const ServerName: FC<Props> = ({ serverName, setServerName, nextStep }) => {
nextStep();
}}
>
Create Server
{t("create_server")}
</StyledButton>
</StyledWrapper>
);
+5 -3
View File
@@ -1,6 +1,7 @@
import styled from "styled-components";
import StyledButton from "../../../common/component/styled/Button";
import PlayIcon from "../../../assets/icons/play.svg?url";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -44,15 +45,16 @@ const StyledWrapper = styled.div`
`;
export default function WelcomePage({ nextStep }: { nextStep: () => void }) {
const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
return (
<StyledWrapper>
<span className="primaryText">Welcome to your VoceChat!</span>
<span className="primaryText">{t("welcome")}</span>
<span className="secondaryText">
Everything in this space is owned by you. Lets set up your space!
{t("welcome_desc")}
</span>
<StyledButton className="startButton" onClick={nextStep}>
<img src={PlayIcon} alt="play icon" />
<span>Start</span>
<span>{t("start")}</span>
</StyledButton>
</StyledWrapper>
);
+6 -4
View File
@@ -5,6 +5,7 @@ import StyledRadio from "../../../common/component/styled/Radio";
import StyledButton from "../../../common/component/styled/Button";
import { useGetLoginConfigQuery, useUpdateLoginConfigMutation } from "../../../app/services/server";
import { WhoCanSignUp } from "../../../types/server";
import { useTranslation } from "react-i18next";
const StyledWrapper = styled.div`
height: 100%;
@@ -40,6 +41,7 @@ const StyledWrapper = styled.div`
`;
export default function SignUpSetting({ nextStep }: { nextStep: () => void }) {
const { t } = useTranslation("welcome");
const { data: loginConfig } = useGetLoginConfigQuery();
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
@@ -65,10 +67,10 @@ export default function SignUpSetting({ nextStep }: { nextStep: () => void }) {
return (
<StyledWrapper>
<span className="primaryText">Last step: invite others!</span>
<span className="secondaryText">Firstly, who can sign up to this server?</span>
<span className="primaryText">{t("onboarding.invite_title")}</span>
<span className="secondaryText">{t("onboarding.invite_desc")}</span>
<StyledRadio
options={["Everyone", "Invitation link only"]}
options={[t("overview.sign_up.everyone", { ns: "setting" }), t("overview.sign_up.invite", { ns: "setting" })]}
values={["EveryOne", "InvitationOnly"]}
value={value}
onChange={setValue}
@@ -85,7 +87,7 @@ export default function SignUpSetting({ nextStep }: { nextStep: () => void }) {
}
}}
>
Confirm
{t("onboarding.confirm")}
</StyledButton>
</StyledWrapper>
);