mirror of
https://github.com/massbug/judge4c.git
synced 2025-05-18 07:16:34 +00:00
feat: add missing i18n in sign up and login in page,add i18n in table.tsx
This commit is contained in:
parent
983c66bdbb
commit
55a9d79965
@ -4,7 +4,8 @@
|
||||
"Enter your email below to sign in to your account": "Enter your email below to sign in to your account",
|
||||
"Or": "Or",
|
||||
"Don't have an account?": "Don't have an account?",
|
||||
"Sign up": "Sign up"
|
||||
"sign-up": "Sign up",
|
||||
"signing-in": "Signing In..."
|
||||
},
|
||||
"sign-up-form": {
|
||||
"title": "Hello world!",
|
||||
@ -12,7 +13,8 @@
|
||||
"sign-up-to-your-account": "Sign up to your account",
|
||||
"or": "Or",
|
||||
"already-have-an-account": "Already have an account?",
|
||||
"sign-in": "Sign in"
|
||||
"sign-in": "Sign in",
|
||||
"creating-account": "Creating Account..."
|
||||
},
|
||||
"appearance-settings": {
|
||||
"choose-a-theme": "Choose a theme",
|
||||
@ -71,5 +73,33 @@
|
||||
"test": {
|
||||
"case": "Case",
|
||||
"failed-to-submit-the-form-please-try-again": "Failed to submit the form. Please try again."
|
||||
},
|
||||
"problemset": {
|
||||
"select-all": "Select all",
|
||||
"select-row": "Select row",
|
||||
"title": "Title",
|
||||
"difficulty": "Difficulty",
|
||||
"actions": "Actions",
|
||||
"displayid-or-title": "DisplayId or Title...",
|
||||
"filter-by-displayid-or-title": "Filter by displayId or title",
|
||||
"clear-filter": "Clear filter",
|
||||
"filters": "Filters",
|
||||
"view": "View",
|
||||
"toggle-columns": "Toggle columns",
|
||||
"delete": "Delete",
|
||||
"are-you-absolutely-sure": "Are you absolutely sure?",
|
||||
"this-action-cannot-be-undone-this-will-permanently-delete": "This action cannot be undone. This will permanently delete",
|
||||
"cancel": "Cancel",
|
||||
"add-problem": "Add Problem",
|
||||
"enter": "Enter",
|
||||
"no-results": "No results.",
|
||||
"rows-per-page": "Rows per page",
|
||||
"select-number-of-results": "Select number of results",
|
||||
"go-to-first-page": "Go to first page",
|
||||
"go-to-previous-page": "Go to previous page",
|
||||
"go-to-next-page": "Go to next page",
|
||||
"go-to-last-page": "Go to last page",
|
||||
"edit-item": "Edit item",
|
||||
"edit": "Edit"
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,8 @@
|
||||
"Enter your email below to sign in to your account": "在下方输入你的邮箱以登录",
|
||||
"Or": "或",
|
||||
"Don't have an account?": "没有帐户?",
|
||||
"Sign up": "注册"
|
||||
"sign-up": "注册",
|
||||
"signing-in": "正在登录。。。"
|
||||
},
|
||||
"sign-up-form": {
|
||||
"title": "Hello world!",
|
||||
@ -12,7 +13,8 @@
|
||||
"enter-your-email-below-to-sign-up-to-your-account": "在下面输入您的电子邮件以注册您的帐户",
|
||||
"or": "或",
|
||||
"sign-in": "登录",
|
||||
"sign-up-to-your-account": "注册您的帐户"
|
||||
"sign-up-to-your-account": "注册您的帐户",
|
||||
"creating-account": "正在创建帐户。。。"
|
||||
},
|
||||
"appearance-settings": {
|
||||
"dark": "暗",
|
||||
@ -71,5 +73,33 @@
|
||||
"test": {
|
||||
"case": "样例",
|
||||
"failed-to-submit-the-form-please-try-again": "提交失败。请重试。"
|
||||
},
|
||||
"problemset": {
|
||||
"actions": "行动",
|
||||
"add-problem": "添加问题",
|
||||
"are-you-absolutely-sure": "你真的确定吗?",
|
||||
"cancel": "取消",
|
||||
"clear-filter": "清除过滤器",
|
||||
"enter": "进入",
|
||||
"filter-by-displayid-or-title": "按显示ID或标题筛选",
|
||||
"filters": "过滤器",
|
||||
"go-to-first-page": "转到第一页",
|
||||
"go-to-last-page": "转到最后一页",
|
||||
"select-number-of-results": "选择结果数量",
|
||||
"select-row": "选定行",
|
||||
"this-action-cannot-be-undone-this-will-permanently-delete": "此操作无法撤消。这将永久删除",
|
||||
"title": "名称",
|
||||
"toggle-columns": "切换列",
|
||||
"delete": "删除",
|
||||
"difficulty": "难度",
|
||||
"displayid-or-title": "显示ID或标题。。。",
|
||||
"edit": "编辑",
|
||||
"edit-item": "编辑项目",
|
||||
"view": "视图",
|
||||
"go-to-next-page": "转到下一页",
|
||||
"go-to-previous-page": "转到上一页",
|
||||
"no-results": "没有结果。",
|
||||
"rows-per-page": "每页行数",
|
||||
"select-all": "选择全部"
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ export function CredentialsSignInForm() {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={isPending} className="w-full">
|
||||
{isPending ? "Signing In..." : "Sign In"}
|
||||
{isPending ? t('sign-in-form.signing-in'): t('sign-up-form.sign-in')}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
@ -117,7 +117,7 @@ export function CredentialsSignUpForm() {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={isPending} className="w-full">
|
||||
{isPending ? "Creating Account..." : "Sign Up"}
|
||||
{isPending ? t('sign-up-form.creating-account'): t('sign-in-form.sign-up')}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
@ -83,9 +83,12 @@ import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Difficulty, Problem } from "@/generated/client";
|
||||
import { cn, getDifficultyColorClass } from "@/lib/utils";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type ProblemTableItem = Pick<Problem, "id" | "displayId" | "title" | "difficulty">;
|
||||
|
||||
const t = useTranslations('problemset');
|
||||
|
||||
interface ProblemTableProps {
|
||||
data: ProblemTableItem[];
|
||||
}
|
||||
@ -117,14 +120,14 @@ const columns: ColumnDef<ProblemTableItem>[] = [
|
||||
(table.getIsSomePageRowsSelected() && "indeterminate")
|
||||
}
|
||||
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
||||
aria-label="Select all"
|
||||
aria-label= {t('select-all')}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
aria-label="Select row"
|
||||
aria-label= {t('select-row')}
|
||||
/>
|
||||
),
|
||||
size: 28,
|
||||
@ -140,12 +143,12 @@ const columns: ColumnDef<ProblemTableItem>[] = [
|
||||
enableHiding: false,
|
||||
},
|
||||
{
|
||||
header: "Title",
|
||||
header: t('title'),
|
||||
accessorKey: "title",
|
||||
cell: ({ row }) => <div className="font-medium">{row.getValue("title")}</div>,
|
||||
},
|
||||
{
|
||||
header: "Difficulty",
|
||||
header: t('difficulty'),
|
||||
accessorKey: "difficulty",
|
||||
cell: ({ row }) => {
|
||||
const difficulty = row.getValue("difficulty") as Difficulty;
|
||||
@ -160,7 +163,7 @@ const columns: ColumnDef<ProblemTableItem>[] = [
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: () => <span className="sr-only">Actions</span>,
|
||||
header: () => <span className="sr-only">t('actions')</span>,
|
||||
cell: () => <RowActions />,
|
||||
enableHiding: false,
|
||||
},
|
||||
@ -262,9 +265,9 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
onChange={(e) =>
|
||||
table.getColumn("displayId")?.setFilterValue(e.target.value)
|
||||
}
|
||||
placeholder="DisplayId or Title..."
|
||||
placeholder={t('displayid-or-title')}
|
||||
type="text"
|
||||
aria-label="Filter by displayId or title"
|
||||
aria-label={t('filter-by-displayid-or-title')}
|
||||
/>
|
||||
<div className="text-muted-foreground/80 pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 peer-disabled:opacity-50">
|
||||
<ListFilterIcon size={16} aria-hidden="true" />
|
||||
@ -272,7 +275,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
{Boolean(table.getColumn("displayId")?.getFilterValue()) && (
|
||||
<button
|
||||
className="text-muted-foreground/80 hover:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md transition-[color,box-shadow] outline-none focus:z-10 focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
aria-label="Clear filter"
|
||||
aria-label={t('clear-filter')}
|
||||
onClick={() => {
|
||||
table.getColumn("displayId")?.setFilterValue("");
|
||||
if (inputRef.current) {
|
||||
@ -292,7 +295,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
size={16}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
Difficulty
|
||||
{t('difficulty')}
|
||||
{selectedDifficulties.length > 0 && (
|
||||
<span className="bg-background text-muted-foreground/70 -me-1 inline-flex h-5 max-h-full items-center rounded border px-1 font-[inherit] text-[0.625rem] font-medium">
|
||||
{selectedDifficulties.length}
|
||||
@ -303,7 +306,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
<PopoverContent className="w-auto min-w-36 p-3" align="start">
|
||||
<div className="space-y-3">
|
||||
<div className="text-muted-foreground text-xs font-medium">
|
||||
Filters
|
||||
{t('filters')}
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
{uniqueDifficultyValues.map((value) => (
|
||||
@ -334,11 +337,11 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
size={16}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
View
|
||||
{t('view')}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>{t('toggle-columns')}</DropdownMenuLabel>
|
||||
{table
|
||||
.getAllColumns()
|
||||
.filter((column) => column.getCanHide())
|
||||
@ -370,7 +373,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
size={16}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
Delete
|
||||
{t('delete')}
|
||||
<span className="bg-background text-muted-foreground/70 -me-1 inline-flex h-5 max-h-full items-center rounded border px-1 font-[inherit] text-[0.625rem] font-medium">
|
||||
{table.getSelectedRowModel().rows.length}
|
||||
</span>
|
||||
@ -386,10 +389,10 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
</div>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure?
|
||||
{t('are-you-absolutely-sure')}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently delete{" "}
|
||||
{t('this-action-cannot-be-undone-this-will-permanently-delete')}{" "}
|
||||
{table.getSelectedRowModel().rows.length} selected{" "}
|
||||
{table.getSelectedRowModel().rows.length === 1
|
||||
? "row"
|
||||
@ -399,9 +402,9 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
</AlertDialogHeader>
|
||||
</div>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogCancel>{t('cancel')}</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={handleDeleteRows}>
|
||||
Delete
|
||||
{t('delete')}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
@ -414,7 +417,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
size={16}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
Add Problem
|
||||
{t('add-problem')}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
@ -439,7 +442,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
onKeyDown={(e) => {
|
||||
if (
|
||||
header.column.getCanSort() &&
|
||||
(e.key === "Enter" || e.key === " ")
|
||||
(e.key === t('enter') || e.key === " ")
|
||||
) {
|
||||
e.preventDefault();
|
||||
header.column.getToggleSortingHandler()?.(e);
|
||||
@ -499,7 +502,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
{t('problemset.no-results')}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
@ -508,7 +511,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-8">
|
||||
<div className="flex items-center gap-3">
|
||||
<Label className="max-sm:sr-only">Rows per page</Label>
|
||||
<Label className="max-sm:sr-only">{t('rows-per-page')}</Label>
|
||||
<Select
|
||||
value={table.getState().pagination.pageSize.toString()}
|
||||
onValueChange={(value) => {
|
||||
@ -516,7 +519,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-fit whitespace-nowrap">
|
||||
<SelectValue placeholder="Select number of results" />
|
||||
<SelectValue placeholder={t('problemset.select-number-of-results')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="[&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8 [&_*[role=option]>span]:start-auto [&_*[role=option]>span]:end-2">
|
||||
{[5, 10, 25, 50].map((pageSize) => (
|
||||
@ -563,7 +566,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
className="disabled:pointer-events-none disabled:opacity-50"
|
||||
onClick={() => table.firstPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
aria-label="Go to first page"
|
||||
aria-label={t('go-to-first-page')}
|
||||
>
|
||||
<ChevronFirstIcon size={16} aria-hidden="true" />
|
||||
</Button>
|
||||
@ -575,7 +578,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
className="disabled:pointer-events-none disabled:opacity-50"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
aria-label="Go to previous page"
|
||||
aria-label={t('go-to-previous-page')}
|
||||
>
|
||||
<ChevronLeftIcon size={16} aria-hidden="true" />
|
||||
</Button>
|
||||
@ -587,7 +590,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
className="disabled:pointer-events-none disabled:opacity-50"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
aria-label="Go to next page"
|
||||
aria-label={t('go-to-next-page')}
|
||||
>
|
||||
<ChevronRightIcon size={16} aria-hidden="true" />
|
||||
</Button>
|
||||
@ -599,7 +602,7 @@ export function ProblemsetTable({ data }: ProblemTableProps) {
|
||||
className="disabled:pointer-events-none disabled:opacity-50"
|
||||
onClick={() => table.lastPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
aria-label="Go to last page"
|
||||
aria-label={t('go-to-last-page')}
|
||||
>
|
||||
<ChevronLastIcon size={16} aria-hidden="true" />
|
||||
</Button>
|
||||
@ -621,7 +624,7 @@ function RowActions() {
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
className="shadow-none"
|
||||
aria-label="Edit item"
|
||||
aria-label={t('edit-item')}
|
||||
>
|
||||
<EllipsisIcon size={16} aria-hidden="true" />
|
||||
</Button>
|
||||
@ -630,12 +633,12 @@ function RowActions() {
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
<span>Edit</span>
|
||||
<span>{t('edit')}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem className="text-destructive focus:text-destructive">
|
||||
<span>Delete</span>
|
||||
<span>{t('delete')}</span>
|
||||
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
Loading…
Reference in New Issue
Block a user