From 48a529e5d66981834503a934380e89c813c2669b Mon Sep 17 00:00:00 2001 From: Tristan Yang Date: Fri, 25 Nov 2022 11:28:00 +0800 Subject: [PATCH] feat: add typescript support to i18next --- config/webpack.config.js | 2 + public/locales/en/auth.json | 13 ++++-- public/locales/zh/auth.json | 5 +++ public/locales/zh/welcome.json | 25 ++++++++++- src/common/DayjsSetting.ts | 7 +-- src/common/component/ChannelModal/index.tsx | 2 +- .../component/InviteModal/InviteByEmail.tsx | 2 +- .../LeaveChannel/LeaveConfirmModal.tsx | 6 +-- .../component/Message/PinMessageModal.tsx | 2 +- src/common/component/UsersModal.tsx | 2 +- src/i18n.ts | 45 ++++++++++++++++--- src/i18next.d.ts | 10 +++++ src/routes/login/index.tsx | 4 +- src/routes/reg/Register.tsx | 6 +-- src/routes/sendMagicLink/SentTip.tsx | 8 ++-- src/routes/sendMagicLink/index.tsx | 12 ++--- src/routes/setting/APIConfig.tsx | 7 +-- .../setting/License/LicensePriceListModal.tsx | 4 +- src/routes/setting/Overview/language.tsx | 2 - .../setting/RemoveAccountConfirmModal.tsx | 4 +- src/routes/setting/UpdatePasswordModal.tsx | 4 +- src/routes/setting/config/Firebase.tsx | 8 ++-- src/routes/setting/index.tsx | 2 +- .../settingChannel/DeleteConfirmModal.tsx | 4 +- src/routes/settingChannel/Overview.tsx | 4 +- 25 files changed, 136 insertions(+), 54 deletions(-) create mode 100644 src/i18next.d.ts diff --git a/config/webpack.config.js b/config/webpack.config.js index da871227..c671e49c 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -251,6 +251,8 @@ module.exports = function (webpackEnv) { // please link the files into your node_modules/ and let module-resolution kick in. // Make sure your source files are compiled, as they will not be processed in any way. new ModuleScopePlugin(paths.appSrc, [ + // 服务于多语言 + `${paths.appPublic}/locales`, paths.appPackageJson, reactRefreshRuntimeEntry, reactRefreshWebpackPluginRuntimeEntry, diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json index 72769c4d..296da14d 100644 --- a/public/locales/en/auth.json +++ b/public/locales/en/auth.json @@ -5,6 +5,7 @@ "google": "Sign in with Google", "github": "Sign in with Github", "metamask": "Sign in with MetaMask", + "password": "Sign in with Password", "oidc": "Sign in with OIDC", "no_account": "Don't have an account?" }, @@ -15,11 +16,15 @@ "github": "Sign Up with Github", "metamask": "Sign Up with MetaMask", "oidc": "Sign Up with OIDC", - "have_account": "Have an account?", - "placeholder_email": "Enter Email", - "placeholder_pwd": "Enter Password", - "placeholder_confirm_pwd": "Confirm Password" + "have_account": "Have an account?" }, + "continue": "Continue with Email", + "placeholder_email": "Enter your Email", + "placeholder_pwd": "Enter Password", + "placeholder_confirm_pwd": "Confirm Password", + "check_email": "Check your email", + "check_email_desc": " We’ve sent you a magic link to {{email}}. Click on the link to continue.", + "use_different": "Use a different email", "welcome": "Welcome to {{name}} server", "guest_login_tip": "Please sign in to send a message", "sign_in": "Sign In", diff --git a/public/locales/zh/auth.json b/public/locales/zh/auth.json index 3848e1a6..064f8eaa 100644 --- a/public/locales/zh/auth.json +++ b/public/locales/zh/auth.json @@ -5,6 +5,7 @@ "google": "谷歌登录", "github": "Github登录", "metamask": "MetaMask登录", + "password": "账号密码登录", "oidc": "OIDC登录", "no_account": "没有账号?" }, @@ -17,6 +18,10 @@ "oidc": "OIDC注册", "have_account": "已有账号?" }, + "continue": "继续", + "check_email": "检查你的邮箱", + "check_email_desc": "我们将链接已发送到你的邮箱:{{email}},请前往查收", + "use_different": "使用其它邮箱", "placeholder_email": "输入邮箱地址", "placeholder_pwd": "输入密码", "placeholder_confirm_pwd": "确认密码", diff --git a/public/locales/zh/welcome.json b/public/locales/zh/welcome.json index d5ba6ad0..1a7bf0a7 100644 --- a/public/locales/zh/welcome.json +++ b/public/locales/zh/welcome.json @@ -5,5 +5,28 @@ "start_by_channel": "创建频道,开启会话", "start_by_dm": "找人聊天", "download": "下载移动端APP", - "help": "还有问题?访问我们的帮助中心" + "help": "还有问题?访问我们的帮助中心", + "onboarding": { + "title": "VoceChat初始化", + "welcome": "欢迎来到你的VoceChat!", + "welcome_desc": "在这里,你能掌控一切,开始构建你的空间吧!", + "start": "开始", + "new_server": "创建一个新的服务器", + "server_desc": "服务器是你和你的朋友能够沟通的载体", + "placeholder_server": "输入服务器名称", + "create_server": "创建服务器", + "admin_title": "现在,初始化一个管理员账号", + "admin_desc": "这是你的服务器上第一个管理员账号,也是超级管理员", + "sign": "注册", + "invite_title": "最后一步:邀请TA人!", + "invite_desc": "首先,决定下注册方式", + "confirm": "确认", + "done_welcome": "欢迎来到 {{serverName}} 👏🏻", + "done_title": "VoceChat倾情打造", + "done_desc": "更多设置,像权限,安全,邀请,请前往 <0>设置页", + "enter": "进入", + "last_tip": "现在,你可以邀请别人啦!", + "last_desc": "将邀请链接发送给将来要入驻的社区成员吧:", + "done": "完成" + } } diff --git a/src/common/DayjsSetting.ts b/src/common/DayjsSetting.ts index 110dbc9d..4e98b7db 100644 --- a/src/common/DayjsSetting.ts +++ b/src/common/DayjsSetting.ts @@ -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"); diff --git a/src/common/component/ChannelModal/index.tsx b/src/common/component/ChannelModal/index.tsx index 19a50749..2f6fd35a 100644 --- a/src/common/component/ChannelModal/index.tsx +++ b/src/common/component/ChannelModal/index.tsx @@ -100,7 +100,7 @@ const ChannelModal: FC = ({ personal = false, closeModal }) => { {users && ( diff --git a/src/common/component/InviteModal/InviteByEmail.tsx b/src/common/component/InviteModal/InviteByEmail.tsx index 69d6a608..a89dcbc0 100644 --- a/src/common/component/InviteModal/InviteByEmail.tsx +++ b/src/common/component/InviteModal/InviteByEmail.tsx @@ -97,7 +97,7 @@ const InviteByEmail: FC = ({ cid }) => { onChange={handleEmail} disabled={!enableSMTP} type="email" - placeholder={enableSMTP ? "Enter Email" : t("enable_smtp") || ""} + placeholder={enableSMTP ? "Enter Email" : t("enable_smtp")} /> } - title={t("action.pin") || ""} + title={t("action.pin")} description={`Do you want to pin this message to #${channel?.name}`} > diff --git a/src/common/component/UsersModal.tsx b/src/common/component/UsersModal.tsx index 0104fdb4..f423fb2d 100644 --- a/src/common/component/UsersModal.tsx +++ b/src/common/component/UsersModal.tsx @@ -70,7 +70,7 @@ const UsersModal: FC = ({ closeModal }) => {
- +
{users && (
    diff --git a/src/i18n.ts b/src/i18n.ts index d6551485..c61e5dbf 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -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, }); diff --git a/src/i18next.d.ts b/src/i18next.d.ts new file mode 100644 index 00000000..26ce92da --- /dev/null +++ b/src/i18next.d.ts @@ -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"]; + } +} \ No newline at end of file diff --git a/src/routes/login/index.tsx b/src/routes/login/index.tsx index a15f677a..bf7472f9 100644 --- a/src/routes/login/index.tsx +++ b/src/routes/login/index.tsx @@ -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")} /> ); diff --git a/src/routes/sendMagicLink/index.tsx b/src/routes/sendMagicLink/index.tsx index f20cbbe7..4f3f4eb7 100644 --- a/src/routes/sendMagicLink/index.tsx +++ b/src/routes/sendMagicLink/index.tsx @@ -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() { <>
    logo -

    Login to VoceChat

    - Please enter your Email +

    {t("login.title")}

    + {t("placeholder_email")}

    - + )} diff --git a/src/routes/setting/APIConfig.tsx b/src/routes/setting/APIConfig.tsx index c74bff19..f9dbfea7 100644 --- a/src/routes/setting/APIConfig.tsx +++ b/src/routes/setting/APIConfig.tsx @@ -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() {
    diff --git a/src/routes/setting/License/LicensePriceListModal.tsx b/src/routes/setting/License/LicensePriceListModal.tsx index 7daf2889..e717d8d0 100644 --- a/src/routes/setting/License/LicensePriceListModal.tsx +++ b/src/routes/setting/License/LicensePriceListModal.tsx @@ -48,8 +48,8 @@ const LicensePriceListModal: FC = ({ closeModal }) => { return ( diff --git a/src/routes/setting/UpdatePasswordModal.tsx b/src/routes/setting/UpdatePasswordModal.tsx index e9e7cf07..89a4d10e 100644 --- a/src/routes/setting/UpdatePasswordModal.tsx +++ b/src/routes/setting/UpdatePasswordModal.tsx @@ -77,8 +77,8 @@ const ProfileBasicEditModal: FC = ({ closeModal }) => { return (