feat(ui): i18n for deleted keys page

This commit is contained in:
吹雪 2026-06-11 06:31:01 +09:00
parent 2d3fcca245
commit 81ed127926
4 changed files with 75 additions and 22 deletions

View file

@ -1,11 +1,13 @@
"use client";
import { useState } from "react";
import { Alert } from "antd";
import { useTranslation } from "react-i18next";
import { useDeletedKeys } from "@/app/(dashboard)/hooks/keys/useKeys";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { DeletedKeysTable } from "./DeletedKeysTable/DeletedKeysTable";
export default function DeletedKeysPage() {
const { t } = useTranslation();
const { premiumUser } = useAuthorized();
const [pageIndex, setPageIndex] = useState(0);
const [pageSize] = useState(50);
@ -19,8 +21,8 @@ export default function DeletedKeysPage() {
type="info"
banner
showIcon
message="Coming soon to Enterprise"
description="Deleted key auditing is graduating from beta into our Enterprise audit & compliance suite."
message={t("deletedKeys.deletedKeysPage.comingSoonToEnterprise")}
description={t("deletedKeys.deletedKeysPage.auditingDescription")}
/>
)}
<DeletedKeysTable

View file

@ -14,6 +14,7 @@ import {
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "@tremor/react";
import { Tooltip } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { KeyResponse } from "../../key_team_helpers/key_list";
interface DeletedKeysTableProps {
@ -35,6 +36,7 @@ export function DeletedKeysTable({
pageSize,
onPageChange,
}: DeletedKeysTableProps) {
const { t } = useTranslation();
const [sorting, setSorting] = useState<SortingState>([
{
id: "deleted_at",
@ -56,7 +58,7 @@ export function DeletedKeysTable({
{
id: "token",
accessorKey: "token",
header: "Key ID",
header: t("deletedKeys.deletedKeysTable.colKeyId"),
size: 150,
maxSize: 250,
cell: (info) => {
@ -71,7 +73,7 @@ export function DeletedKeysTable({
{
id: "key_alias",
accessorKey: "key_alias",
header: "Key Alias",
header: t("deletedKeys.deletedKeysTable.colKeyAlias"),
size: 150,
maxSize: 200,
cell: (info) => {
@ -86,7 +88,7 @@ export function DeletedKeysTable({
{
id: "team_alias",
accessorKey: "team_alias",
header: "Team Alias",
header: t("deletedKeys.deletedKeysTable.colTeamAlias"),
size: 120,
maxSize: 180,
cell: (info) => {
@ -97,7 +99,7 @@ export function DeletedKeysTable({
{
id: "spend",
accessorKey: "spend",
header: "Spend (USD)",
header: t("deletedKeys.deletedKeysTable.colSpend"),
size: 100,
maxSize: 140,
cell: (info) => (
@ -107,14 +109,14 @@ export function DeletedKeysTable({
{
id: "max_budget",
accessorKey: "max_budget",
header: "Budget (USD)",
header: t("deletedKeys.deletedKeysTable.colBudget"),
size: 110,
maxSize: 150,
cell: (info) => {
const maxBudget = info.getValue() as number | null;
return (
<span className="block max-w-[150px]">
{maxBudget === null ? "Unlimited" : `$${formatNumberWithCommas(maxBudget)}`}
{maxBudget === null ? t("deletedKeys.deletedKeysTable.unlimited") : `$${formatNumberWithCommas(maxBudget)}`}
</span>
);
},
@ -122,7 +124,7 @@ export function DeletedKeysTable({
{
id: "user_email",
accessorKey: "user_email",
header: "User Email",
header: t("deletedKeys.deletedKeysTable.colUserEmail"),
size: 160,
maxSize: 250,
cell: (info) => {
@ -137,7 +139,7 @@ export function DeletedKeysTable({
{
id: "user_id",
accessorKey: "user_id",
header: "User ID",
header: t("deletedKeys.deletedKeysTable.colUserId"),
size: 120,
maxSize: 200,
cell: (info) => {
@ -152,7 +154,7 @@ export function DeletedKeysTable({
{
id: "created_at",
accessorKey: "created_at",
header: "Created At",
header: t("common.createdAt"),
size: 120,
maxSize: 140,
cell: (info) => {
@ -165,7 +167,7 @@ export function DeletedKeysTable({
{
id: "created_by",
accessorKey: "created_by",
header: "Created By",
header: t("deletedKeys.deletedKeysTable.colCreatedBy"),
size: 120,
maxSize: 180,
cell: (info) => {
@ -180,7 +182,7 @@ export function DeletedKeysTable({
{
id: "deleted_at",
accessorKey: "deleted_at",
header: "Deleted At",
header: t("deletedKeys.deletedKeysTable.colDeletedAt"),
size: 120,
maxSize: 140,
cell: (info) => {
@ -191,7 +193,7 @@ export function DeletedKeysTable({
{
id: "deleted_by",
accessorKey: "deleted_by",
header: "Deleted By",
header: t("deletedKeys.deletedKeysTable.colDeletedBy"),
size: 120,
maxSize: 180,
cell: (info) => {
@ -239,19 +241,22 @@ export function DeletedKeysTable({
<div className="border-b py-4 flex-1 overflow-hidden">
<div className="flex items-center justify-between w-full mb-4">
{isLoading || isFetching ? (
<span className="inline-flex text-sm text-gray-700">Loading...</span>
<span className="inline-flex text-sm text-gray-700">{t("common.loading")}</span>
) : (
<span className="inline-flex text-sm text-gray-700">
Showing {rangeLabel} of {totalCount} results
{t("deletedKeys.deletedKeysTable.showingRange", { range: rangeLabel, total: totalCount })}
</span>
)}
<div className="inline-flex items-center gap-2">
{isLoading || isFetching ? (
<span className="text-sm text-gray-700">Loading...</span>
<span className="text-sm text-gray-700">{t("common.loading")}</span>
) : (
<span className="text-sm text-gray-700">
Page {currentPageIndex + 1} of {table.getPageCount()}
{t("deletedKeys.deletedKeysTable.pageOf", {
current: currentPageIndex + 1,
total: table.getPageCount(),
})}
</span>
)}
@ -260,7 +265,7 @@ export function DeletedKeysTable({
disabled={isLoading || isFetching || !table.getCanPreviousPage()}
className="px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
>
Previous
{t("common.previous")}
</button>
<button
@ -268,7 +273,7 @@ export function DeletedKeysTable({
disabled={isLoading || isFetching || !table.getCanNextPage()}
className="px-3 py-1 text-sm border rounded-md hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
>
Next
{t("common.next")}
</button>
</div>
</div>
@ -348,7 +353,7 @@ export function DeletedKeysTable({
<TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>🚅 Loading keys...</p>
<p>{t("deletedKeys.deletedKeysTable.loadingKeys")}</p>
</div>
</TableCell>
</TableRow>
@ -375,7 +380,7 @@ export function DeletedKeysTable({
<TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>No deleted keys found</p>
<p>{t("deletedKeys.deletedKeysTable.noDeletedKeys")}</p>
</div>
</TableCell>
</TableRow>

View file

@ -8025,5 +8025,28 @@
"modelRpmLimits": "Model RPM Limits: {{value}}",
"fieldMetadata": "Metadata"
}
},
"deletedKeys": {
"deletedKeysPage": {
"comingSoonToEnterprise": "Coming soon to Enterprise",
"auditingDescription": "Deleted key auditing is graduating from beta into our Enterprise audit & compliance suite."
},
"deletedKeysTable": {
"colKeyId": "Key ID",
"colKeyAlias": "Key Alias",
"colTeamAlias": "Team Alias",
"colSpend": "Spend (USD)",
"colBudget": "Budget (USD)",
"colUserEmail": "User Email",
"colUserId": "User ID",
"colCreatedBy": "Created By",
"colDeletedAt": "Deleted At",
"colDeletedBy": "Deleted By",
"unlimited": "Unlimited",
"showingRange": "Showing {{range}} of {{total}} results",
"pageOf": "Page {{current}} of {{total}}",
"loadingKeys": "🚅 Loading keys...",
"noDeletedKeys": "No deleted keys found"
}
}
}

View file

@ -8025,5 +8025,28 @@
"modelRpmLimits": "模型 RPM 限制:{{value}}",
"fieldMetadata": "元数据"
}
},
"deletedKeys": {
"deletedKeysPage": {
"comingSoonToEnterprise": "即将在企业版上线",
"auditingDescription": "已删除密钥审计正从测试版毕业,纳入我们的企业级审计与合规套件。"
},
"deletedKeysTable": {
"colKeyId": "密钥 ID",
"colKeyAlias": "密钥别名",
"colTeamAlias": "团队别名",
"colSpend": "花费(USD)",
"colBudget": "预算(USD)",
"colUserEmail": "用户邮箱",
"colUserId": "用户 ID",
"colCreatedBy": "创建人",
"colDeletedAt": "删除时间",
"colDeletedBy": "删除人",
"unlimited": "无限制",
"showingRange": "显示第 {{range}} 条,共 {{total}} 条",
"pageOf": "第 {{current}} 页,共 {{total}} 页",
"loadingKeys": "🚅 正在加载密钥...",
"noDeletedKeys": "未找到已删除密钥"
}
}
}