mirror of
https://github.com/usememos/memos.git
synced 2024-12-19 00:51:30 +03:00
feat: add typeScript support to enforce valid translation keys (#1954)
* #1952 Fix incorrect localization key for sign-up failure message * feat: add typeScript support to enforce valid translation keys * feat: add typeScript support to enforce valid translation keys * fix lint errors * fix lint error
This commit is contained in:
parent
5e20094386
commit
1780225da5
@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -7,7 +7,7 @@ import GitHubBadge from "./GitHubBadge";
|
||||
type Props = DialogProps;
|
||||
|
||||
const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const profile = globalStore.state.systemStatus.profile;
|
||||
const customizedProfile = globalStore.state.systemStatus.customizedProfile;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Option, Select } from "@mui/joy";
|
||||
import { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import Icon from "./Icon";
|
||||
|
||||
interface Props {
|
||||
@ -9,11 +9,11 @@ interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const appearanceList = ["system", "light", "dark"];
|
||||
const appearanceList = ["system", "light", "dark"] as const;
|
||||
|
||||
const AppearanceSelect: FC<Props> = (props: Props) => {
|
||||
const { onChange, value, className } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
|
||||
const getPrefixIcon = (appearance: Appearance) => {
|
||||
const className = "w-4 h-auto";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMemoStore } from "@/store/module";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { getDateTimeString } from "@/helpers/datetime";
|
||||
import Icon from "./Icon";
|
||||
import MemoContent from "./MemoContent";
|
||||
@ -15,7 +15,7 @@ interface Props {
|
||||
|
||||
const ArchivedMemo: React.FC<Props> = (props: Props) => {
|
||||
const { memo } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const memoStore = useMemoStore();
|
||||
|
||||
const handleDeleteMemoClick = async () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useMemoStore } from "@/store/module";
|
||||
import useLoading from "@/hooks/useLoading";
|
||||
import Icon from "./Icon";
|
||||
@ -11,7 +11,7 @@ import "@/less/archived-memo-dialog.less";
|
||||
type Props = DialogProps;
|
||||
|
||||
const ArchivedMemoDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { destroy } = props;
|
||||
const memoStore = useMemoStore();
|
||||
const memos = memoStore.state.memos;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@ -6,7 +6,7 @@ interface Props {
|
||||
|
||||
const BetaBadge: React.FC<Props> = (props: Props) => {
|
||||
const { className } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
|
||||
return (
|
||||
<span
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -11,7 +11,7 @@ interface Props extends DialogProps {
|
||||
|
||||
const ChangeMemberPasswordDialog: React.FC<Props> = (props: Props) => {
|
||||
const { user: propsUser, destroy } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [newPasswordAgain, setNewPasswordAgain] = useState("");
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { getNormalizedTimeString, getUnixTime } from "@/helpers/datetime";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useMemoStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -11,7 +11,7 @@ interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const ChangeMemoCreatedTsDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { destroy, memoId } = props;
|
||||
const memoStore = useMemoStore();
|
||||
const [createdAt, setCreatedAt] = useState("");
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore, useUserStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -8,7 +8,7 @@ import { generateDialog } from "./Dialog";
|
||||
type Props = DialogProps;
|
||||
|
||||
const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const globalStore = useGlobalStore();
|
||||
const profile = globalStore.state.systemStatus.profile;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useResourceStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -25,7 +25,7 @@ const validateFilename = (filename: string): boolean => {
|
||||
|
||||
const ChangeResourceFilenameDialog: React.FC<Props> = (props: Props) => {
|
||||
const { destroy, resourceId, resourceFilename } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const resourceStore = useResourceStore();
|
||||
const [filename, setFilename] = useState<string>(resourceFilename);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Button, Divider, Input, Option, Select, Typography } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { toast } from "react-hot-toast";
|
||||
import * as api from "@/helpers/api";
|
||||
import { UNKNOWN_ID } from "@/helpers/consts";
|
||||
@ -101,7 +101,7 @@ interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const identityProviderTypes = [...new Set(templateList.map((t) => t.type))];
|
||||
const { confirmCallback, destroy, identityProvider } = props;
|
||||
const [basicInfo, setBasicInfo] = useState({
|
||||
@ -236,7 +236,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
|
||||
return (
|
||||
<>
|
||||
<div className="dialog-header-container">
|
||||
<p className="title-text ml-auto">{t("setting.sso-section." + (isCreating ? "create" : "update") + "-sso")}</p>
|
||||
<p className="title-text ml-auto">{t(isCreating ? "setting.sso-section.create-sso" : "setting.sso-section.update-sso")}</p>
|
||||
<button className="btn close-btn ml-auto" onClick={handleCloseBtnClick}>
|
||||
<Icon.X />
|
||||
</button>
|
||||
@ -411,7 +411,7 @@ const CreateIdentityProviderDialog: React.FC<Props> = (props: Props) => {
|
||||
{t("common.cancel")}
|
||||
</Button>
|
||||
<Button onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
|
||||
{t("common." + (isCreating ? "create" : "update"))}
|
||||
{t(isCreating ? "common.create" : "common.update")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button, Input, Select, Option, Typography, List, ListItem, Autocomplete } from "@mui/joy";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useResourceStore } from "../store/module";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
@ -21,7 +21,7 @@ interface State {
|
||||
}
|
||||
|
||||
const CreateResourceDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { destroy, onCancel, onConfirm } = props;
|
||||
const resourceStore = useResourceStore();
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useShortcutStore, useTagStore } from "@/store/module";
|
||||
import { filterConsts, getDefaultFilter, relationConsts } from "@/helpers/filter";
|
||||
import { getNormalizedTimeString } from "@/helpers/datetime";
|
||||
@ -20,7 +20,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
|
||||
const [title, setTitle] = useState<string>("");
|
||||
const [filters, setFilters] = useState<Filter[]>([]);
|
||||
const requestState = useLoading(false);
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
|
||||
useEffect(() => {
|
||||
if (shortcutId) {
|
||||
@ -158,7 +158,7 @@ interface MemoFilterInputerProps {
|
||||
|
||||
const MemoFilterInputer: React.FC<MemoFilterInputerProps> = (props: MemoFilterInputerProps) => {
|
||||
const { index, filter, handleFilterChange, handleFilterRemove } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const tagStore = useTagStore();
|
||||
const [value, setValue] = useState<string>(filter.value.value);
|
||||
const tags = Array.from(tagStore.getState().tags);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button, Input, Typography } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import * as api from "@/helpers/api";
|
||||
import { generateDialog } from "./Dialog";
|
||||
import Icon from "./Icon";
|
||||
@ -14,7 +14,7 @@ interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { destroy, storage, confirmCallback } = props;
|
||||
const [basicInfo, setBasicInfo] = useState({
|
||||
name: "",
|
||||
@ -106,7 +106,9 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
|
||||
return (
|
||||
<>
|
||||
<div className="dialog-header-container">
|
||||
<span className="title-text ml-auto">{t("setting.storage-section." + (isCreating ? "create" : "update") + "-storage")}</span>
|
||||
<span className="title-text ml-auto">
|
||||
{t(isCreating ? "setting.storage-section.create-storage" : "setting.storage-section.update-storage")}
|
||||
</span>
|
||||
<button className="btn close-btn ml-auto" onClick={handleCloseBtnClick}>
|
||||
<Icon.X />
|
||||
</button>
|
||||
@ -219,7 +221,7 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
|
||||
{t("common.cancel")}
|
||||
</Button>
|
||||
<Button onClick={handleConfirmBtnClick} disabled={!allowConfirmAction()}>
|
||||
{t("common." + (isCreating ? "create" : "update"))}
|
||||
{t(isCreating ? "common.create" : "common.update")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Input } from "@mui/joy";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useTagStore } from "@/store/module";
|
||||
import { getTagSuggestionList } from "@/helpers/api";
|
||||
import { matcher } from "@/labs/marked/matcher";
|
||||
@ -22,7 +22,7 @@ const validateTagName = (tagName: string): boolean => {
|
||||
const CreateTagDialog: React.FC<Props> = (props: Props) => {
|
||||
const { destroy } = props;
|
||||
const tagStore = useTagStore();
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const [tagName, setTagName] = useState<string>("");
|
||||
const [suggestTagNameList, setSuggestTagNameList] = useState<string[]>([]);
|
||||
const [showTagSuggestions, setShowTagSuggestions] = useState<boolean>(false);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import Icon from "../Icon";
|
||||
import { generateDialog } from "./BaseDialog";
|
||||
import "@/less/common-dialog.less";
|
||||
@ -23,10 +23,10 @@ const defaultProps = {
|
||||
confirmBtnText: "common.confirm",
|
||||
onClose: () => null,
|
||||
onConfirm: () => null,
|
||||
};
|
||||
} as const;
|
||||
|
||||
const CommonDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { title, content, destroy, closeBtnText, confirmBtnText, onClose, onConfirm, style } = {
|
||||
...defaultProps,
|
||||
closeBtnText: t(defaultProps.closeBtnText),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import copy from "copy-to-clipboard";
|
||||
import React from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
|
||||
@ -10,7 +10,7 @@ interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const EmbedMemoDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { memoId, destroy } = props;
|
||||
|
||||
const memoEmbeddedCode = () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import { NavLink, useLocation } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useLayoutStore, useUserStore } from "@/store/module";
|
||||
import { resolution } from "@/utils/layout";
|
||||
import Icon from "./Icon";
|
||||
@ -9,7 +9,7 @@ import showAboutSiteDialog from "./AboutSiteDialog";
|
||||
import UpgradeVersionView from "./UpgradeVersionBanner";
|
||||
|
||||
const Header = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const location = useLocation();
|
||||
const userStore = useUserStore();
|
||||
const layoutStore = useLayoutStore();
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import Icon from "./Icon";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
interface Props {
|
||||
className?: string;
|
||||
url: string;
|
||||
@ -10,7 +9,7 @@ interface Props {
|
||||
|
||||
const LearnMore: React.FC<Props> = (props: Props) => {
|
||||
const { className, url, title } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -2,6 +2,7 @@ import { Divider, Tooltip } from "@mui/joy";
|
||||
import { isEqual, uniqWith } from "lodash-es";
|
||||
import { memo, useEffect, useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useFilterStore, useMemoStore, useUserStore } from "@/store/module";
|
||||
@ -28,7 +29,8 @@ interface Props {
|
||||
|
||||
const Memo: React.FC<Props> = (props: Props) => {
|
||||
const { memo, showCreator, showVisibility, showRelatedMemos } = props;
|
||||
const { t, i18n } = useTranslation();
|
||||
const { i18n } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const userStore = useUserStore();
|
||||
const memoStore = useMemoStore();
|
||||
@ -225,7 +227,7 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||
</div>
|
||||
<div className="btns-container space-x-2">
|
||||
{showVisibility && memo.visibility !== "PRIVATE" && (
|
||||
<Tooltip title={t(`memo.visibility.${memo.visibility.toLowerCase()}`)} placement="top">
|
||||
<Tooltip title={t(`memo.visibility.${memo.visibility.toLowerCase() as Lowercase<typeof memo.visibility>}`)} placement="top">
|
||||
<div onClick={() => handleMemoVisibilityClick(memo.visibility)}>
|
||||
{memo.visibility === "PUBLIC" ? (
|
||||
<Icon.Globe2 className="w-4 h-auto cursor-pointer rounded text-green-600" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { marked } from "@/labs/marked";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
@ -23,7 +23,7 @@ interface State {
|
||||
|
||||
const MemoContent: React.FC<Props> = (props: Props) => {
|
||||
const { className, content, showFull, onMemoContentClick, onMemoContentDoubleClick } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const [state, setState] = useState<State>({
|
||||
expandButtonStatus: -1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { toLower } from "lodash-es";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import Selector from "@/components/kit/Selector";
|
||||
@ -11,14 +11,14 @@ interface Props {
|
||||
|
||||
const MemoVisibilitySelector = (props: Props) => {
|
||||
const { value, onChange } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const {
|
||||
state: { systemStatus },
|
||||
} = useGlobalStore();
|
||||
const memoVisibilityOptionSelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: t(`memo.visibility.${toLower(item.value)}`),
|
||||
text: t(`memo.visibility.${toLower(item.value) as Lowercase<typeof item.value>}`),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { isNumber, last, uniq } from "lodash-es";
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getMatchedNodes } from "@/labs/marked";
|
||||
import { upsertMemoResource } from "@/helpers/api";
|
||||
@ -42,7 +43,8 @@ interface State {
|
||||
|
||||
const MemoEditor = (props: Props) => {
|
||||
const { className, memoId, onConfirm } = props;
|
||||
const { t, i18n } = useTranslation();
|
||||
const { i18n } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const {
|
||||
state: { systemStatus },
|
||||
} = useGlobalStore();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useFilterStore, useShortcutStore } from "@/store/module";
|
||||
import { getDateString } from "@/helpers/datetime";
|
||||
@ -8,7 +8,7 @@ import Icon from "./Icon";
|
||||
import "@/less/memo-filter.less";
|
||||
|
||||
const MemoFilter = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const location = useLocation();
|
||||
const filterStore = useFilterStore();
|
||||
const shortcutStore = useShortcutStore();
|
||||
@ -46,7 +46,8 @@ const MemoFilter = () => {
|
||||
filterStore.setMemoTypeFilter(undefined);
|
||||
}}
|
||||
>
|
||||
<Icon.Box className="icon-text" /> {t(getTextWithMemoType(memoType as MemoSpecType))}
|
||||
<Icon.Box className="icon-text" />{" "}
|
||||
{t(getTextWithMemoType(memoType as MemoSpecType) as Exclude<ReturnType<typeof getTextWithMemoType>, "">)}
|
||||
</div>
|
||||
<div
|
||||
className={"filter-item-container " + (visibility ? "" : "!hidden")}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useFilterStore, useMemoStore, useShortcutStore, useUserStore } from "@/store/module";
|
||||
import { TAG_REG, LINK_REG, PLAIN_LINK_REG } from "@/labs/marked/parser";
|
||||
import { getTimeStampByDate } from "@/helpers/datetime";
|
||||
@ -11,7 +11,7 @@ import Memo from "./Memo";
|
||||
import "@/less/memo-list.less";
|
||||
|
||||
const MemoList = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const memoStore = useMemoStore();
|
||||
const userStore = useUserStore();
|
||||
const shortcutStore = useShortcutStore();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import copy from "copy-to-clipboard";
|
||||
import React from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useResourceStore } from "@/store/module";
|
||||
import { getResourceUrl } from "@/utils/resource";
|
||||
import Dropdown from "./kit/Dropdown";
|
||||
@ -15,7 +15,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const ResourceItemDropdown = ({ resource }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const resourceStore = useResourceStore();
|
||||
const resources = resourceStore.state.resources;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import Icon from "./Icon";
|
||||
import useDebounce from "@/hooks/useDebounce";
|
||||
|
||||
@ -7,7 +7,7 @@ interface ResourceSearchBarProps {
|
||||
setQuery: (queryText: string) => void;
|
||||
}
|
||||
const ResourceSearchBar = ({ setQuery }: ResourceSearchBarProps) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const [queryText, setQueryText] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { useEffect, useState, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import useDebounce from "@/hooks/useDebounce";
|
||||
import { useFilterStore } from "@/store/module";
|
||||
import Icon from "./Icon";
|
||||
|
||||
const SearchBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const [queryText, setQueryText] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Table } from "@mui/joy";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
import Dropdown from "../kit/Dropdown";
|
||||
@ -15,7 +15,7 @@ interface State {
|
||||
}
|
||||
|
||||
const PreferencesSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const currentUser = userStore.state.user;
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button, Input, Textarea } from "@mui/joy";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import { showCommonDialog } from "../Dialog/CommonDialog";
|
||||
import showChangePasswordDialog from "../ChangePasswordDialog";
|
||||
@ -8,7 +8,7 @@ import showUpdateAccountDialog from "../UpdateAccountDialog";
|
||||
import UserAvatar from "../UserAvatar";
|
||||
|
||||
const MyAccountSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const user = userStore.state.user as User;
|
||||
const openAPIRoute = `${window.location.origin}/api/v1/memo?openId=${user.openId}`;
|
||||
|
@ -2,7 +2,7 @@ import { Input, Button, Divider, Switch, Option, Select } from "@mui/joy";
|
||||
import { useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore, useUserStore } from "@/store/module";
|
||||
import { VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts";
|
||||
import AppearanceSelect from "../AppearanceSelect";
|
||||
@ -11,7 +11,7 @@ import LearnMore from "../LearnMore";
|
||||
import "@/less/settings/preferences-section.less";
|
||||
|
||||
const PreferencesSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const userStore = useUserStore();
|
||||
const { appearance, locale } = globalStore.state;
|
||||
@ -20,7 +20,7 @@ const PreferencesSection = () => {
|
||||
const visibilitySelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: t(`memo.visibility.${item.text.toLowerCase()}`),
|
||||
text: t(`memo.visibility.${item.text.toLowerCase() as Lowercase<typeof item.text>}`),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Divider } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import * as api from "@/helpers/api";
|
||||
import showCreateIdentityProviderDialog from "../CreateIdentityProviderDialog";
|
||||
import Dropdown from "../kit/Dropdown";
|
||||
@ -9,7 +9,7 @@ import { showCommonDialog } from "../Dialog/CommonDialog";
|
||||
import LearnMore from "../LearnMore";
|
||||
|
||||
const SSOSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const [identityProviderList, setIdentityProviderList] = useState<IdentityProvider[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Divider, Select, Option } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
import showCreateStorageServiceDialog from "../CreateStorageServiceDialog";
|
||||
@ -11,7 +11,7 @@ import { showCommonDialog } from "../Dialog/CommonDialog";
|
||||
import LearnMore from "../LearnMore";
|
||||
|
||||
const StorageSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const systemStatus = globalStore.state.systemStatus;
|
||||
const [storageServiceId, setStorageServiceId] = useState(systemStatus.storageServiceId);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Button, Divider, Input, Switch, Textarea, Tooltip } from "@mui/joy";
|
||||
import { formatBytes } from "@/helpers/utils";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
@ -21,7 +21,7 @@ interface State {
|
||||
}
|
||||
|
||||
const SystemSection = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const systemStatus = globalStore.state.systemStatus;
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -2,7 +2,7 @@ import { Select, Option } from "@mui/joy";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { toLower } from "lodash-es";
|
||||
import toImage from "@/labs/html2image";
|
||||
@ -30,7 +30,7 @@ interface State {
|
||||
|
||||
const ShareMemoDialog: React.FC<Props> = (props: Props) => {
|
||||
const { memo: propsMemo, destroy } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const memoStore = useMemoStore();
|
||||
const globalStore = useGlobalStore();
|
||||
@ -109,7 +109,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
|
||||
const memoVisibilityOptionSelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: t(`memo.visibility.${toLower(item.value)}`),
|
||||
text: t(`memo.visibility.${toLower(item.value) as Lowercase<typeof item.value>}`),
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useFilterStore, useShortcutStore } from "@/store/module";
|
||||
import { getTimeStampByDate } from "@/helpers/datetime";
|
||||
import useToggle from "@/hooks/useToggle";
|
||||
@ -9,7 +9,7 @@ import Icon from "./Icon";
|
||||
import showCreateShortcutDialog from "./CreateShortcutDialog";
|
||||
|
||||
const ShortcutList = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const shortcutStore = useShortcutStore();
|
||||
const filter = filterStore.state;
|
||||
@ -62,7 +62,7 @@ interface ShortcutContainerProps {
|
||||
|
||||
const ShortcutContainer: React.FC<ShortcutContainerProps> = (props: ShortcutContainerProps) => {
|
||||
const { shortcut, isActive } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const shortcutStore = useShortcutStore();
|
||||
const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useFilterStore, useTagStore } from "@/store/module";
|
||||
import useToggle from "@/hooks/useToggle";
|
||||
import Icon from "./Icon";
|
||||
@ -12,7 +12,7 @@ interface Tag {
|
||||
}
|
||||
|
||||
const TagList = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const tagStore = useTagStore();
|
||||
const tagsText = tagStore.state.tags;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { isEqual } from "lodash-es";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import { convertFileToBase64 } from "@/helpers/utils";
|
||||
import Icon from "./Icon";
|
||||
@ -18,7 +18,7 @@ interface State {
|
||||
}
|
||||
|
||||
const UpdateAccountDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const user = userStore.state.user as User;
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
@ -12,7 +12,7 @@ import AppearanceSelect from "./AppearanceSelect";
|
||||
type Props = DialogProps;
|
||||
|
||||
const UpdateCustomizedProfileDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const [state, setState] = useState<CustomizedProfile>(globalStore.state.systemStatus.customizedProfile);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Button, Input } from "@mui/joy";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
@ -14,7 +14,7 @@ interface Props extends DialogProps {
|
||||
}
|
||||
|
||||
const UpdateLocalStorageDialog: React.FC<Props> = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { destroy, localStoragePath, confirmCallback } = props;
|
||||
const globalStore = useGlobalStore();
|
||||
const [path, setPath] = useState(localStoragePath || "");
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useFilterStore, useMemoStore, useUserStore } from "../store/module";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { getMemoStats } from "@/helpers/api";
|
||||
import { DAILY_TIMESTAMP } from "@/helpers/consts";
|
||||
import { getDateStampByDate, getDateString, getTimeStampByDate } from "@/helpers/datetime";
|
||||
@ -29,7 +29,7 @@ interface DailyUsageStat {
|
||||
}
|
||||
|
||||
const UsageHeatMap = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const userStore = useUserStore();
|
||||
const memoStore = useMemoStore();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useGlobalStore, useUserStore } from "@/store/module";
|
||||
import Dropdown from "./kit/Dropdown";
|
||||
@ -8,7 +8,7 @@ import UserAvatar from "./UserAvatar";
|
||||
import showAboutSiteDialog from "./AboutSiteDialog";
|
||||
|
||||
const UserBanner = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const navigate = useNavigate();
|
||||
const globalStore = useGlobalStore();
|
||||
const userStore = useUserStore();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Badge, Button } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { DAILY_TIMESTAMP } from "@/helpers/consts";
|
||||
import { getMemoStats } from "@/helpers/api";
|
||||
import { getDateStampByDate } from "@/helpers/datetime";
|
||||
@ -15,7 +15,7 @@ interface DatePickerProps {
|
||||
}
|
||||
|
||||
const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const { className, datestamp, handleDateStampChange } = props;
|
||||
const [currentDateStamp, setCurrentDateStamp] = useState<DateStamp>(getMonthFirstDayDateStamp(datestamp));
|
||||
const [countByDate, setCountByDate] = useState(new Map());
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import { memo, useEffect, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import useToggle from "@/hooks/useToggle";
|
||||
import Icon from "../Icon";
|
||||
import "@/less/common/selector.less";
|
||||
@ -20,13 +20,13 @@ interface Props {
|
||||
}
|
||||
|
||||
const nullItem = {
|
||||
text: "common.select",
|
||||
text: "common.select" as const,
|
||||
value: "",
|
||||
};
|
||||
|
||||
const Selector: React.FC<Props> = (props: Props) => {
|
||||
const { className, dataSource, handleValueChanged, value, disabled, tooltipTitle } = props;
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const [showSelector, toggleSelectorStatus] = useToggle(false);
|
||||
|
||||
const selectorElRef = useRef<HTMLDivElement>(null);
|
||||
|
@ -11,7 +11,7 @@ export const VISIBILITY_SELECTOR_ITEMS = [
|
||||
{ text: "PRIVATE", value: "PRIVATE" },
|
||||
{ text: "PROTECTED", value: "PROTECTED" },
|
||||
{ text: "PUBLIC", value: "PUBLIC" },
|
||||
];
|
||||
] as const;
|
||||
|
||||
// space width for tab action in editor
|
||||
export const TAB_SPACE_WIDTH = 2;
|
||||
|
@ -4,7 +4,7 @@ import { TAG_REG, LINK_REG, PLAIN_LINK_REG } from "@/labs/marked/parser";
|
||||
export const relationConsts = [
|
||||
{ text: "filter.and", value: "AND" },
|
||||
{ text: "filter.or", value: "OR" },
|
||||
];
|
||||
] as const;
|
||||
|
||||
export const filterConsts = {
|
||||
TAG: {
|
||||
@ -105,11 +105,11 @@ export const filterConsts = {
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
} as const;
|
||||
|
||||
export const memoSpecialTypes = filterConsts["TYPE"].values;
|
||||
|
||||
export const getTextWithMemoType = (type: string): string => {
|
||||
export const getTextWithMemoType = (type: string) => {
|
||||
for (const t of memoSpecialTypes) {
|
||||
if (t.value === type) {
|
||||
return t.text;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import toast from "react-hot-toast";
|
||||
import { useMemoStore } from "@/store/module";
|
||||
import useLoading from "@/hooks/useLoading";
|
||||
@ -9,7 +9,7 @@ import Empty from "@/components/Empty";
|
||||
import "@/less/archived.less";
|
||||
|
||||
const Archived = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const memoStore = useMemoStore();
|
||||
const loadingState = useLoading();
|
||||
const [archivedMemos, setArchivedMemos] = useState<Memo[]>([]);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button, Divider } from "@mui/joy";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore, useUserStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
import { absolutifyLink } from "@/helpers/utils";
|
||||
@ -11,7 +11,7 @@ import AppearanceSelect from "@/components/AppearanceSelect";
|
||||
import LocaleSelect from "@/components/LocaleSelect";
|
||||
|
||||
const Auth = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const userStore = useUserStore();
|
||||
const actionBtnLoadingState = useLoading(false);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { last } from "lodash-es";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import * as api from "@/helpers/api";
|
||||
import { absolutifyLink } from "@/helpers/utils";
|
||||
@ -14,7 +14,7 @@ interface State {
|
||||
}
|
||||
|
||||
const AuthCallback = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const userStore = useUserStore();
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { last } from "lodash-es";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useMemoStore, useUserStore } from "@/store/module";
|
||||
import { DAILY_TIMESTAMP, DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
|
||||
import MobileHeader from "@/components/MobileHeader";
|
||||
@ -17,7 +17,7 @@ import { convertToMillis, getDateStampByDate, getNormalizedDateString, getTimeSt
|
||||
import Empty from "@/components/Empty";
|
||||
|
||||
const DailyReview = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const memoStore = useMemoStore();
|
||||
const memos = memoStore.state.memos;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useFilterStore, useMemoStore } from "@/store/module";
|
||||
import { TAG_REG } from "@/labs/marked/parser";
|
||||
@ -16,7 +16,7 @@ interface State {
|
||||
}
|
||||
|
||||
const Explore = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const location = useLocation();
|
||||
const filterStore = useFilterStore();
|
||||
const memoStore = useMemoStore();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useGlobalStore, useUserStore } from "@/store/module";
|
||||
import MemoEditor from "@/components/MemoEditor";
|
||||
import MemoFilter from "@/components/MemoFilter";
|
||||
@ -9,7 +9,7 @@ import MobileHeader from "@/components/MobileHeader";
|
||||
import HomeSidebar from "@/components/HomeSidebar";
|
||||
|
||||
function Home() {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const userStore = useUserStore();
|
||||
const user = userStore.state.user;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Link, useLocation, useParams } from "react-router-dom";
|
||||
import { UNKNOWN_ID } from "@/helpers/consts";
|
||||
import { useGlobalStore, useMemoStore } from "@/store/module";
|
||||
@ -13,7 +13,7 @@ interface State {
|
||||
}
|
||||
|
||||
const MemoDetail = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const globalStore = useGlobalStore();
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { Link } from "react-router-dom";
|
||||
import "@/less/not-found.less";
|
||||
|
||||
const NotFound = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
|
||||
return (
|
||||
<div className="page-wrapper not-found">
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Button } from "@mui/joy";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
|
||||
import useLoading from "@/hooks/useLoading";
|
||||
import useEvent from "@/hooks/useEvent";
|
||||
@ -17,7 +17,7 @@ import showCreateResourceDialog from "@/components/CreateResourceDialog";
|
||||
import Empty from "@/components/Empty";
|
||||
|
||||
const ResourcesDashboard = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const loadingState = useLoading();
|
||||
const resourceStore = useResourceStore();
|
||||
const resources = resourceStore.state.resources;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Option, Select } from "@mui/joy";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import { useUserStore } from "@/store/module";
|
||||
import Icon from "@/components/Icon";
|
||||
import BetaBadge from "@/components/BetaBadge";
|
||||
@ -20,7 +20,7 @@ interface State {
|
||||
}
|
||||
|
||||
const Setting = () => {
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const userStore = useUserStore();
|
||||
const user = userStore.state.user;
|
||||
const [state, setState] = useState<State>({
|
||||
|
@ -3,7 +3,7 @@ import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
|
||||
import store, { useAppSelector } from "../";
|
||||
import { patchResource, setResources, deleteResource, upsertResources } from "../reducer/resource";
|
||||
import { useGlobalStore } from "./global";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
const convertResponseModelResource = (resource: Resource): Resource => {
|
||||
return {
|
||||
@ -15,7 +15,7 @@ const convertResponseModelResource = (resource: Resource): Resource => {
|
||||
|
||||
export const useResourceStore = () => {
|
||||
const state = useAppSelector((state) => state.resource);
|
||||
const { t } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const globalStore = useGlobalStore();
|
||||
const maxUploadSizeMiB = globalStore.state.systemStatus.maxUploadSizeMiB;
|
||||
|
||||
|
3
web/src/types/utils/nestedKeyOf.types.ts
Normal file
3
web/src/types/utils/nestedKeyOf.types.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type NestedKeyOf<T, K = keyof T> = K extends keyof T & (string | number)
|
||||
? `${K}` | (T[K] extends object ? `${K}.${NestedKeyOf<T[K]>}` : never)
|
||||
: never;
|
@ -1,5 +1,8 @@
|
||||
import i18n, { TLocale, availableLocales } from "@/i18n";
|
||||
import { FallbackLngObjList } from "i18next";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import locales from "@/locales/en.json";
|
||||
import type { NestedKeyOf } from "@/types/utils/nestedKeyOf.types";
|
||||
|
||||
export const findNearestLanguageMatch = (codename: string): Locale => {
|
||||
// Find existing translations for full codes (e.g. "en-US", "zh-Hant")
|
||||
@ -33,3 +36,14 @@ export const findNearestLanguageMatch = (codename: string): Locale => {
|
||||
// should be "en", so the selector is not empty if there isn't a translation for current user's language
|
||||
return (i18n.store.options.fallbackLng as FallbackLngObjList).default[0] as Locale;
|
||||
};
|
||||
|
||||
// Represents the keys of nested translation objects.
|
||||
type Translations = NestedKeyOf<typeof locales>;
|
||||
|
||||
// Represents a typed translation function.
|
||||
type TypedT = (key: Translations, params?: Record<string, any>) => string;
|
||||
|
||||
export const useTranslate = (): TypedT => {
|
||||
const { t } = useTranslation<Translations>();
|
||||
return t;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user