Skip to content

Commit

Permalink
chore: adding missing translations (#4273)
Browse files Browse the repository at this point in the history
* Added missing translations strings (filters, about page, ...)

* Forgot one translation string.

* Fixed PR issues and added Access Token related missing translation strings.

* Fixed eslint issues.

* Fixed eslint issues #2.

* Fixed access token dialog translations, added missing webhook dialog translations.
  • Loading branch information
dandelionmood authored Jan 8, 2025
1 parent 7b909fb commit cdadf13
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 74 deletions.
9 changes: 8 additions & 1 deletion web/src/components/ActivityCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,14 @@ const ActivityCalendar = (props: Props) => {
const date = dayjs(`${year}-${month + 1}-${item.day}`).format("YYYY-MM-DD");
const count = item.isCurrentMonth ? data[date] || 0 : 0;
const isToday = dayjs().format("YYYY-MM-DD") === date;
const tooltipText = count ? t("memo.count-memos-in-date", { count: count, date: date }) : date;
const tooltipText =
count === 0
? t("memo.no-memos")
: t("memo.count-memos-in-date", {
count: count,
memos: count === 1 ? t("common.memo") : t("common.memos"),
date: date,
}).toLowerCase();
const isSelected = dayjs(props.selectedDate).format("YYYY-MM-DD") === date;

return (
Expand Down
40 changes: 20 additions & 20 deletions web/src/components/CreateAccessTokenDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ interface Props extends DialogProps {
onConfirm: () => void;
}

const expirationOptions = [
{
label: "8 hours",
value: 3600 * 8,
},
{
label: "1 month",
value: 3600 * 24 * 30,
},
{
label: "Never",
value: 0,
},
];

interface State {
description: string;
expiration: number;
Expand All @@ -43,6 +28,21 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
});
const requestState = useLoading(false);

const expirationOptions = [
{
label: t("setting.access-token-section.create-dialog.duration-8h"),
value: 3600 * 8,
},
{
label: t("setting.access-token-section.create-dialog.duration-1m"),
value: 3600 * 24 * 30,
},
{
label: t("setting.access-token-section.create-dialog.duration-never"),
value: 0,
},
];

const setPartialState = (partialState: Partial<State>) => {
setState({
...state,
Expand All @@ -64,7 +64,7 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {

const handleSaveBtnClick = async () => {
if (!state.description) {
toast.error("Description is required");
toast.error(t("message.description-is-required"));
return;
}

Expand All @@ -86,29 +86,29 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
return (
<>
<div className="dialog-header-container">
<p className="title-text">Create access token</p>
<p className="title-text">{t("setting.access-token-section.create-dialog.create-access-token")}</p>
<Button size="sm" variant="plain" onClick={() => destroy()}>
<XIcon className="w-5 h-auto" />
</Button>
</div>
<div className="dialog-content-container !w-80">
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">
Description <span className="text-red-600">*</span>
{t("setting.access-token-section.create-dialog.description")} <span className="text-red-600">*</span>
</span>
<div className="relative w-full">
<Input
className="w-full"
type="text"
placeholder="Some description"
placeholder={t("setting.access-token-section.create-dialog.some-description")}
value={state.description}
onChange={handleDescriptionInputChange}
/>
</div>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">
Expiration <span className="text-red-600">*</span>
{t("setting.access-token-section.create-dialog.expiration")} <span className="text-red-600">*</span>
</span>
<div className="w-full flex flex-row justify-start items-center text-base">
<RadioGroup orientation="horizontal" value={state.expiration} onChange={handleRoleInputChange}>
Expand Down
14 changes: 8 additions & 6 deletions web/src/components/CreateWebhookDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {

const handleSaveBtnClick = async () => {
if (!state.name || !state.url) {
toast.error("Please fill all required fields");
toast.error(t("message.fill-all-required-fields"));
return;
}

Expand Down Expand Up @@ -95,35 +95,37 @@ const CreateWebhookDialog: React.FC<Props> = (props: Props) => {
return (
<>
<div className="dialog-header-container">
<p className="title-text">{isCreating ? "Create webhook" : "Edit webhook"}</p>
<p className="title-text">
{isCreating ? t("setting.webhook-section.create-dialog.create-webhook") : t("setting.webhook-section.create-dialog.edit-webhook")}
</p>
<Button size="sm" variant="plain" onClick={() => destroy()}>
<XIcon className="w-5 h-auto" />
</Button>
</div>
<div className="dialog-content-container !w-80">
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">
Title <span className="text-red-600">*</span>
{t("setting.webhook-section.create-dialog.title")} <span className="text-red-600">*</span>
</span>
<div className="relative w-full">
<Input
className="w-full"
type="text"
placeholder="An easy-to-remember name"
placeholder={t("setting.webhook-section.create-dialog.an-easy-to-remember-name")}
value={state.name}
onChange={handleTitleInputChange}
/>
</div>
</div>
<div className="w-full flex flex-col justify-start items-start mb-3">
<span className="mb-2">
Payload URL <span className="text-red-600">*</span>
{t("setting.webhook-section.create-dialog.payload-url")} <span className="text-red-600">*</span>
</span>
<div className="relative w-full">
<Input
className="w-full"
type="text"
placeholder="https://example.com/postreceive"
placeholder={t("setting.webhook-section.create-dialog.url-example-post-receive")}
value={state.url}
onChange={handleUrlInputChange}
/>
Expand Down
12 changes: 7 additions & 5 deletions web/src/components/MemoDisplaySettingMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Option, Select } from "@mui/joy";
import clsx from "clsx";
import { Settings2Icon } from "lucide-react";
import { useMemoFilterStore } from "@/store/v1";
import { useTranslate } from "@/utils/i18n";
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";

interface Props {
className?: string;
}

const MemoDisplaySettingMenu = ({ className }: Props) => {
const t = useTranslate();
const memoFilterStore = useMemoFilterStore();
const isApplying = Boolean(memoFilterStore.orderByTimeAsc) !== false;

Expand All @@ -22,16 +24,16 @@ const MemoDisplaySettingMenu = ({ className }: Props) => {
<PopoverContent align="end" alignOffset={-12} sideOffset={14}>
<div className="flex flex-col gap-2">
<div className="w-full flex flex-row justify-between items-center">
<span className="text-sm shrink-0 mr-3">Order by</span>
<span className="text-sm shrink-0 mr-3">{t("memo.order-by")}</span>
<Select value="displayTime">
<Option value={"displayTime"}>Display Time</Option>
<Option value={"displayTime"}>{t("memo.display-time")}</Option>
</Select>
</div>
<div className="w-full flex flex-row justify-between items-center">
<span className="text-sm shrink-0 mr-3">Direction</span>
<span className="text-sm shrink-0 mr-3">{t("memo.direction")}</span>
<Select value={memoFilterStore.orderByTimeAsc} onChange={(_, value) => memoFilterStore.setOrderByTimeAsc(Boolean(value))}>
<Option value={false}>DESC</Option>
<Option value={true}>ASC</Option>
<Option value={false}>{t("memo.direction-desc")}</Option>
<Option value={true}>{t("memo.direction-asc")}</Option>
</Select>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const AddMemoRelationPopover = (props: Props) => {
// If embedded mode is enabled, embed the memo instead of creating a relation.
if (embedded) {
if (!editorRef.current) {
toast.error("Failed to embed memo");
toast.error(t("message.failed-to-embed-memo"));
return;
}

Expand Down
4 changes: 3 additions & 1 deletion web/src/components/MemoFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, FilterIcon, LinkIcon,
import { useEffect, useRef } from "react";
import { useSearchParams } from "react-router-dom";
import { FilterFactor, getMemoFilterKey, MemoFilter, parseFilterQuery, stringifyFilters, useMemoFilterStore } from "@/store/v1";
import { useTranslate } from "@/utils/i18n";

const MemoFilters = () => {
const t = useTranslate();
const [searchParams, setSearchParams] = useSearchParams();
const memoFilterStore = useMemoFilterStore();
const filters = memoFilterStore.filters;
Expand Down Expand Up @@ -75,7 +77,7 @@ const MemoFilters = () => {
<div className="w-full mb-2 flex flex-row justify-start items-start gap-2">
<span className="flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-6 border border-transparent">
<FilterIcon className="w-4 h-auto opacity-60 inline" />
Filters
{t("memo.filters")}
</span>
<div className="flex flex-row justify-start items-center flex-wrap gap-2 leading-6 h-6">
{filters.map((filter) => (
Expand Down
13 changes: 6 additions & 7 deletions web/src/components/Settings/AccessTokenSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ const AccessTokenSection = () => {

const copyAccessToken = (accessToken: string) => {
copy(accessToken);
toast.success("Access token copied to clipboard");
toast.success(t("setting.access-token-section.access-token-copied-to-clipboard"));
};

const handleDeleteAccessToken = async (accessToken: string) => {
const confirmed = window.confirm(
`Are you sure to delete access token \`${getFormatedAccessToken(accessToken)}\`? You cannot undo this action.`,
);
const formatedAccessToken = getFormatedAccessToken(accessToken);
const confirmed = window.confirm(t("setting.access-token-section.access-token-deletion", { accessToken: formatedAccessToken }));
if (confirmed) {
await userServiceClient.deleteUserAccessToken({ name: currentUser.name, accessToken: accessToken });
setUserAccessTokens(userAccessTokens.filter((token) => token.accessToken !== accessToken));
Expand Down Expand Up @@ -85,10 +84,10 @@ const AccessTokenSection = () => {
{t("common.description")}
</th>
<th scope="col" className="px-3 py-2 text-left text-sm font-semibold text-gray-900 dark:text-gray-400">
{t("setting.access-token-section.created-at")}
{t("setting.access-token-section.create-dialog.created-at")}
</th>
<th scope="col" className="px-3 py-2 text-left text-sm font-semibold text-gray-900 dark:text-gray-400">
{t("setting.access-token-section.expires-at")}
{t("setting.access-token-section.create-dialog.expires-at")}
</th>
<th scope="col" className="relative py-3.5 pl-3 pr-4">
<span className="sr-only">{t("common.delete")}</span>
Expand All @@ -111,7 +110,7 @@ const AccessTokenSection = () => {
{userAccessToken.issuedAt?.toLocaleString()}
</td>
<td className="whitespace-nowrap px-3 py-2 text-sm text-gray-500 dark:text-gray-400">
{userAccessToken.expiresAt?.toLocaleString() ?? "Never"}
{userAccessToken.expiresAt?.toLocaleString() ?? t("setting.access-token-section.create-dialog.duration-never")}
</td>
<td className="relative whitespace-nowrap py-2 pl-3 pr-4 text-right text-sm">
<Button
Expand Down
11 changes: 5 additions & 6 deletions web/src/components/UserStatisticsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const UserStatisticsView = () => {
const [visibleMonthString, setVisibleMonthString] = useState(dayjs(selectedDate.toDateString()).format("YYYY-MM"));
const days = Math.ceil((Date.now() - currentUser.createTime!.getTime()) / 86400000);

const singularOrPluralMemo = (memoAmount > 0 ? t("common.memos") : t("common.memo")).toLowerCase();
const singularOrPluralDay = (days > 0 ? t("common.days") : t("common.day")).toLowerCase();

useAsyncEffect(async () => {
const memoStats: UserMemoStats = { link: 0, taskList: 0, code: 0, incompleteTasks: 0 };
metadataList.forEach((memo) => {
Expand Down Expand Up @@ -90,14 +93,10 @@ const UserStatisticsView = () => {
onClick={onCalendarClick}
/>
{memoAmount === 0 ? (
<p className="mt-1 w-full text-xs italic opacity-80">No memos</p>
) : memoAmount === 1 ? (
<p className="mt-1 w-full text-xs italic opacity-80">
<span>{memoAmount}</span> memo in <span>{days}</span> {days > 1 ? "days" : "day"}
</p>
<p className="mt-1 w-full text-xs italic opacity-80">{t("memo.no-memos")}</p>
) : (
<p className="mt-1 w-full text-xs italic opacity-80">
<span>{memoAmount}</span> memos in <span>{days}</span> {days > 1 ? "days" : "day"}
<span>{memoAmount}</span> {singularOrPluralMemo} {t("common.in").toLowerCase()} <span>{days}</span> {singularOrPluralDay}
</p>
)}
</div>
Expand Down
Loading

0 comments on commit cdadf13

Please sign in to comment.