feat: add typescript support to i18next
This commit is contained in:
@@ -3,10 +3,11 @@ import "dayjs/locale/zh-cn";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import isToday from "dayjs/plugin/isToday";
|
||||
import isYesterday from "dayjs/plugin/isYesterday";
|
||||
import i18n from '../i18n';
|
||||
// import i18n from '../i18n';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
dayjs.extend(isToday);
|
||||
dayjs.extend(isYesterday);
|
||||
|
||||
dayjs.locale(i18n.language == "en" ? "en" : "zh-cn");
|
||||
// console.log("dddd", i18n.resolvedLanguage);
|
||||
// if(i18n.language)
|
||||
// dayjs.locale(i18n.language == "en" ? "en" : "zh-cn");
|
||||
|
||||
@@ -100,7 +100,7 @@ const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder={t("search_user_placeholder") || ""}
|
||||
placeholder={t("search_user_placeholder")}
|
||||
/>
|
||||
</div>
|
||||
{users && (
|
||||
|
||||
@@ -97,7 +97,7 @@ const InviteByEmail: FC<Props> = ({ cid }) => {
|
||||
onChange={handleEmail}
|
||||
disabled={!enableSMTP}
|
||||
type="email"
|
||||
placeholder={enableSMTP ? "Enter Email" : t("enable_smtp") || ""}
|
||||
placeholder={enableSMTP ? "Enter Email" : t("enable_smtp")}
|
||||
/>
|
||||
<Button disabled={!enableSMTP || !email} className="send">
|
||||
{t("action.send", { ns: "common" })}
|
||||
|
||||
@@ -30,11 +30,11 @@ const LeaveConfirmModal: FC<Props> = ({ id, closeModal, handleNextStep }) => {
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
className="compact"
|
||||
title={t("channel.leave") || ""}
|
||||
title={t("channel.leave")}
|
||||
description={
|
||||
isOwner
|
||||
? t("channel.transfer_desc") || ""
|
||||
: t("channel.leave_desc") || ""
|
||||
? t("channel.transfer_desc")
|
||||
: t("channel.leave_desc")
|
||||
}
|
||||
buttons={
|
||||
<>
|
||||
|
||||
@@ -60,7 +60,7 @@ const PinMessageModal: FC<Props> = ({ closeModal, mid = 0, gid = 0 }) => {
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
title={t("action.pin") || ""}
|
||||
title={t("action.pin")}
|
||||
description={`Do you want to pin this message to #${channel?.name}`}
|
||||
>
|
||||
<PreviewMessage mid={mid} />
|
||||
|
||||
@@ -70,7 +70,7 @@ const UsersModal: FC<Props> = ({ closeModal }) => {
|
||||
<Modal>
|
||||
<StyledWrapper ref={wrapperRef}>
|
||||
<div className="search">
|
||||
<input value={input} onChange={handleSearch} placeholder={t("search_user_placeholder") || ""} />
|
||||
<input value={input} onChange={handleSearch} placeholder={t("search_user_placeholder")} />
|
||||
</div>
|
||||
{users && (
|
||||
<ul className="users">
|
||||
|
||||
+39
-6
@@ -1,12 +1,39 @@
|
||||
import i18n from 'i18next';
|
||||
import dayjs from 'dayjs';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
import Backend from 'i18next-http-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import common from '../public/locales/en/common.json';
|
||||
|
||||
import auth from '../public/locales/en/auth.json';
|
||||
import member from '../public/locales/en/member.json';
|
||||
import chat from '../public/locales/en/chat.json';
|
||||
import fav from '../public/locales/en/fav.json';
|
||||
import welcome from '../public/locales/en/welcome.json';
|
||||
import setting from '../public/locales/en/setting.json';
|
||||
import file from '../public/locales/en/file.json';
|
||||
|
||||
// don't want to use this?
|
||||
// have a look at the Quick start guide
|
||||
// for passing in lng and translations on init
|
||||
|
||||
export const defaultNS = "common";
|
||||
export const resources = {
|
||||
en: {
|
||||
common,
|
||||
chat,
|
||||
auth,
|
||||
fav,
|
||||
member,
|
||||
welcome,
|
||||
setting,
|
||||
file,
|
||||
},
|
||||
} as const;
|
||||
i18n.on("languageChanged", (lng) => {
|
||||
console.log("changed", lng);
|
||||
dayjs.locale(lng === 'zh' ? "zh-cn" : lng);
|
||||
});
|
||||
i18n
|
||||
// load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
|
||||
// learn more: https://github.com/i18next/i18next-http-backend
|
||||
@@ -21,12 +48,18 @@ i18n
|
||||
// for all options read: https://www.i18next.com/overview/configuration-options
|
||||
.init({
|
||||
ns: ["common", "chat", "member", "setting", "fav", "file", "welcome", "auth"],
|
||||
defaultNS: "common",
|
||||
defaultNS,
|
||||
// lng: "en",
|
||||
fallbackLng: 'en',
|
||||
debug: true,
|
||||
// interpolation: {
|
||||
// escapeValue: false, // not needed for react as it escapes by default
|
||||
// }
|
||||
fallbackNS: "common",
|
||||
debug: false,
|
||||
detection: {
|
||||
order: ["localStorage", "navigator"]
|
||||
},
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
returnNull: false,
|
||||
});
|
||||
|
||||
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import { resources, defaultNS } from "./i18n";
|
||||
|
||||
declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
allowObjectInHTMLChildren: true,
|
||||
returnNull: false;
|
||||
defaultNS: typeof defaultNS;
|
||||
resources: typeof resources["en"];
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ export default function LoginPage() {
|
||||
name="email"
|
||||
value={email}
|
||||
required
|
||||
placeholder={t("placeholder_email") || ""}
|
||||
placeholder={t("placeholder_email")}
|
||||
data-type="email"
|
||||
onChange={handleInput}
|
||||
/>
|
||||
@@ -151,7 +151,7 @@ export default function LoginPage() {
|
||||
required
|
||||
data-type="password"
|
||||
onChange={handleInput}
|
||||
placeholder={t("placeholder_pwd") || ""}
|
||||
placeholder={t("placeholder_pwd")}
|
||||
/>
|
||||
<Button type="submit" disabled={isLoading}>
|
||||
{isLoading ? "Signing" : t("sign_in")}
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function Reg() {
|
||||
name="email"
|
||||
value={email}
|
||||
required
|
||||
placeholder={t("placeholder_email") || ""}
|
||||
placeholder={t("placeholder_email")}
|
||||
data-type="email"
|
||||
onChange={handleInput}
|
||||
/>
|
||||
@@ -131,7 +131,7 @@ export default function Reg() {
|
||||
required
|
||||
data-type="password"
|
||||
onChange={handleInput}
|
||||
placeholder={t("placeholder_pwd") || ""}
|
||||
placeholder={t("placeholder_pwd")}
|
||||
/>
|
||||
<Input
|
||||
required
|
||||
@@ -141,7 +141,7 @@ export default function Reg() {
|
||||
value={confirmPassword}
|
||||
data-type="confirmPassword"
|
||||
onChange={handleInput}
|
||||
placeholder={t("placeholder_confirm_pwd") || ""}
|
||||
placeholder={t("placeholder_confirm_pwd")}
|
||||
></Input>
|
||||
<Button type="submit" disabled={isLoading}>
|
||||
{isLoading ? "Signing Up" : t("sign_up")}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import { FC, MouseEvent } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props {
|
||||
email: string;
|
||||
@@ -7,14 +8,15 @@ interface Props {
|
||||
}
|
||||
|
||||
const SentTip: FC<Props> = ({ email, reset }) => {
|
||||
const { t } = useTranslation("auth");
|
||||
return (
|
||||
<div className="tips">
|
||||
<h2 className="title">Check your email</h2>
|
||||
<h2 className="title">{t("check_email")}</h2>
|
||||
<span className="desc">
|
||||
We’ve sent you a magic link to {email}. Click on the link to continue.
|
||||
{t("check_email_desc", { email })}
|
||||
</span>
|
||||
<Button onClick={reset} className="main flex">
|
||||
Use a different email
|
||||
{t("use_different")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,8 +7,10 @@ import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import { useSendLoginMagicLinkMutation } from "../../app/services/auth";
|
||||
import SentTip from "./SentTip";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function SendMagicLinkPage() {
|
||||
const { t } = useTranslation("auth");
|
||||
const [sent, setSent] = useState(false);
|
||||
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendLoginMagicLinkMutation();
|
||||
const navigateTo = useNavigate();
|
||||
@@ -69,8 +71,8 @@ export default function SendMagicLinkPage() {
|
||||
<>
|
||||
<div className="tips">
|
||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
|
||||
<h2 className="title">Login to VoceChat</h2>
|
||||
<span className="desc">Please enter your Email</span>
|
||||
<h2 className="title">{t("login.title")}</h2>
|
||||
<span className="desc">{t("placeholder_email")}</span>
|
||||
</div>
|
||||
<form onSubmit={handleLogin}>
|
||||
<Input
|
||||
@@ -81,15 +83,15 @@ export default function SendMagicLinkPage() {
|
||||
value={email}
|
||||
required
|
||||
// pattern={`^\S+@\S+\.\S+$`}
|
||||
placeholder="Enter your email"
|
||||
placeholder={t("placeholder_email")}
|
||||
onChange={handleInput}
|
||||
/>
|
||||
<Button type="submit" disabled={isLoading || !email}>
|
||||
{isLoading ? "Sending" : `Continue with Email`}
|
||||
{isLoading ? "Sending" : t("continue")}
|
||||
</Button>
|
||||
</form>
|
||||
<hr className="or" />
|
||||
<Button onClick={handlePwdPath}>Sign in with Password</Button>
|
||||
<Button onClick={handlePwdPath}>{t("login.password")}</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -62,7 +62,8 @@ const Styled = styled.div`
|
||||
`;
|
||||
|
||||
export default function APIConfig() {
|
||||
const { t } = useTranslation(["setting", "common"]);
|
||||
const { t } = useTranslation("setting");
|
||||
const { t: ct } = useTranslation();
|
||||
const { updateConfig, values } = useConfig("login");
|
||||
const { data } = useGetThirdPartySecretQuery();
|
||||
const [updateSecret, { data: updatedSecret, isSuccess, isLoading }] =
|
||||
@@ -99,10 +100,10 @@ export default function APIConfig() {
|
||||
</div>
|
||||
<div className="btns">
|
||||
<Button onClick={() => hideAll()} className="cancel small">
|
||||
{t("action.cancel", { ns: "common" })}
|
||||
{ct("action.cancel")}
|
||||
</Button>
|
||||
<Button disabled={isLoading} className="small danger" onClick={() => updateSecret()}>
|
||||
{t("action.yes", { ns: "common" })}
|
||||
{ct("action.yes")}
|
||||
</Button>
|
||||
</div>
|
||||
</StyledConfirm>
|
||||
|
||||
@@ -48,8 +48,8 @@ const LicensePriceListModal: FC<Props> = ({ closeModal }) => {
|
||||
return (
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
title={t("license.renew") || ""}
|
||||
description={t("license.renew_select") || ""}
|
||||
title={t("license.renew")}
|
||||
description={t("license.renew_select")}
|
||||
buttons={
|
||||
<>
|
||||
<Button onClick={closeModal} className="ghost">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// import React from 'react'
|
||||
import dayjs from 'dayjs';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import StyledRadio from "../../../common/component/styled/Radio";
|
||||
|
||||
@@ -9,7 +8,6 @@ const Index = () => {
|
||||
const { t, i18n } = useTranslation("setting");
|
||||
const handleGuestToggle = (v: "zh" | "en") => {
|
||||
i18n.changeLanguage(v);
|
||||
dayjs.locale(v === "zh" ? "zh-cn" : "en");
|
||||
};
|
||||
return (
|
||||
<div className="setting">
|
||||
|
||||
@@ -24,8 +24,8 @@ const RemoveConfirmModal: FC<Props> = ({ closeModal }) => {
|
||||
return (
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
title={t("remove_account") || ""}
|
||||
description={t("remove_account_desc") || ""}
|
||||
title={t("remove_account")}
|
||||
description={t("remove_account_desc")}
|
||||
buttons={
|
||||
<>
|
||||
<Button onClick={closeModal}>{t("action.cancel", { ns: "common" })}</Button>
|
||||
|
||||
@@ -77,8 +77,8 @@ const ProfileBasicEditModal: FC<Props> = ({ closeModal }) => {
|
||||
return (
|
||||
<Modal id="modal-modal">
|
||||
<StyledEdit
|
||||
title={t("change_pwd") || ""}
|
||||
description={t("change_pwd_desc") || ""}
|
||||
title={t("change_pwd")}
|
||||
description={t("change_pwd_desc")}
|
||||
buttons={
|
||||
<>
|
||||
<Button className="cancel" onClick={closeModal}>
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function ConfigFirebase() {
|
||||
onChange={handleChange}
|
||||
value={token_url}
|
||||
name="token_url"
|
||||
placeholder={t("firebase.token_url") || ""}
|
||||
placeholder={t("firebase.token_url")}
|
||||
/>
|
||||
</div>
|
||||
<div className="input">
|
||||
@@ -58,7 +58,7 @@ export default function ConfigFirebase() {
|
||||
onChange={handleChange}
|
||||
value={project_id}
|
||||
name="project_id"
|
||||
placeholder={t("firebase.project_id") || ""}
|
||||
placeholder={t("firebase.project_id")}
|
||||
/>
|
||||
</div>
|
||||
<div className="input">
|
||||
@@ -71,7 +71,7 @@ export default function ConfigFirebase() {
|
||||
onChange={handleChange}
|
||||
value={private_key}
|
||||
name="private_key"
|
||||
placeholder={t("firebase.private_key") || ""}
|
||||
placeholder={t("firebase.private_key")}
|
||||
/>
|
||||
</div>
|
||||
<div className="input">
|
||||
@@ -82,7 +82,7 @@ export default function ConfigFirebase() {
|
||||
onChange={handleChange}
|
||||
value={client_email}
|
||||
name="client_email"
|
||||
placeholder={t("firebase.client_email") || ""}
|
||||
placeholder={t("firebase.client_email")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function Setting() {
|
||||
<StyledSettingContainer
|
||||
nav={currNav}
|
||||
closeModal={close}
|
||||
title={t("setting") || ""}
|
||||
title={t("setting")}
|
||||
navs={navs}
|
||||
dangers={[{ title: t("action.logout"), handler: toggleLogoutConfirm }]}
|
||||
>
|
||||
|
||||
@@ -33,8 +33,8 @@ const DeleteConfirmModal: FC<Props> = ({ id, closeModal }) => {
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
className="compact"
|
||||
title={t("channel.delete") || ""}
|
||||
description={t("channel.delete_desc") || ""}
|
||||
title={t("channel.delete")}
|
||||
description={t("channel.delete_desc")}
|
||||
buttons={
|
||||
<>
|
||||
<Button onClick={closeModal.bind(null, undefined)} className="cancel">
|
||||
|
||||
@@ -133,7 +133,7 @@ export default function Overview({ id = 0 }) {
|
||||
value={name}
|
||||
name="name"
|
||||
id="name"
|
||||
placeholder={t("name") || ""}
|
||||
placeholder={t("name")}
|
||||
/>
|
||||
</div>
|
||||
<div className="input">
|
||||
@@ -146,7 +146,7 @@ export default function Overview({ id = 0 }) {
|
||||
rows={4}
|
||||
name="name"
|
||||
id="name"
|
||||
placeholder={t("topic_placeholder") || ""} />
|
||||
placeholder={t("topic_placeholder")} />
|
||||
</div>
|
||||
{!readOnly && <div className="input">
|
||||
<Label htmlFor="desc">{t("visibility")}</Label>
|
||||
|
||||
Reference in New Issue
Block a user