feat(ui): i18n for usage view select

This commit is contained in:
吹雪 2026-06-11 01:27:32 +09:00
parent 84c5d6af01
commit cc3eb38d8b
3 changed files with 116 additions and 56 deletions

View file

@ -10,7 +10,9 @@ import {
UserOutlined,
} from "@ant-design/icons";
import { Badge, Select } from "antd";
import React from "react";
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import type { TFunction } from "i18next";
export type UsageOption =
| "global"
| "my-usage"
@ -42,72 +44,72 @@ interface OptionConfig {
descriptionForNonAdmin?: string;
badgeText?: string;
}
const OPTIONS: OptionConfig[] = [
const getOptions = (t: TFunction): OptionConfig[] => [
{
value: "global",
label: "Global Usage",
showForAdmin: "Global Usage",
showForNonAdmin: "Your Usage",
description: "View usage across all resources",
descriptionForAdmin: "View usage across all resources",
descriptionForNonAdmin: "View your usage",
label: t("usagePage.usageViewSelect.globalUsageLabel"),
showForAdmin: t("usagePage.usageViewSelect.globalUsageLabel"),
showForNonAdmin: t("usagePage.usageViewSelect.yourUsageLabel"),
description: t("usagePage.usageViewSelect.globalUsageDesc"),
descriptionForAdmin: t("usagePage.usageViewSelect.globalUsageDesc"),
descriptionForNonAdmin: t("usagePage.usageViewSelect.yourUsageDesc"),
icon: <GlobalOutlined style={{ fontSize: "16px" }} />,
},
{
value: "my-usage",
label: "Your Usage",
description: "View your own usage",
label: t("usagePage.usageViewSelect.yourUsageLabel"),
description: t("usagePage.usageViewSelect.myUsageDesc"),
icon: <UserOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
{
value: "organization",
label: "Organization Usage",
showForAdmin: "Organization Usage",
showForNonAdmin: "Your Organization Usage",
description: "View organization-level usage",
descriptionForAdmin: "View usage across all organizations",
descriptionForNonAdmin: "View your organization's usage",
label: t("usagePage.usageViewSelect.organizationUsageLabel"),
showForAdmin: t("usagePage.usageViewSelect.organizationUsageLabel"),
showForNonAdmin: t("usagePage.usageViewSelect.yourOrganizationUsageLabel"),
description: t("usagePage.usageViewSelect.organizationUsageDesc"),
descriptionForAdmin: t("usagePage.usageViewSelect.organizationUsageAdminDesc"),
descriptionForNonAdmin: t("usagePage.usageViewSelect.organizationUsageNonAdminDesc"),
icon: <BankOutlined style={{ fontSize: "16px" }} />,
},
{
value: "team",
label: "Team Usage",
description: "View usage by team",
label: t("usagePage.usageViewSelect.teamUsageLabel"),
description: t("usagePage.usageViewSelect.teamUsageDesc"),
icon: <TeamOutlined style={{ fontSize: "16px" }} />,
},
{
value: "customer",
label: "Customer Usage",
description: "View usage by customer accounts",
label: t("usagePage.usageViewSelect.customerUsageLabel"),
description: t("usagePage.usageViewSelect.customerUsageDesc"),
icon: <ShoppingCartOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
{
value: "tag",
label: "Tag Usage",
description: "View usage grouped by tags",
label: t("usagePage.usageViewSelect.tagUsageLabel"),
description: t("usagePage.usageViewSelect.tagUsageDesc"),
icon: <TagsOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
{
value: "agent",
label: "Agent Usage (A2A)",
description: "View usage by AI agents",
label: t("usagePage.usageViewSelect.agentUsageLabel"),
description: t("usagePage.usageViewSelect.agentUsageDesc"),
icon: <RobotOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
{
value: "user",
label: "User Usage",
description: "View usage by individual users",
label: t("usagePage.usageViewSelect.userUsageLabel"),
description: t("usagePage.usageViewSelect.userUsageDesc"),
icon: <UserOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
{
value: "user-agent-activity",
label: "User Agent Activity",
description: "View detailed user agent activity logs",
label: t("usagePage.usageViewSelect.userAgentActivityLabel"),
description: t("usagePage.usageViewSelect.userAgentActivityDesc"),
icon: <LineChartOutlined style={{ fontSize: "16px" }} />,
adminOnly: true,
},
@ -117,36 +119,42 @@ export const UsageViewSelect: React.FC<UsageViewSelectProps> = ({
onChange,
isAdmin,
canViewTagUsage = false,
title = "Usage View",
description = "Select the usage data you want to view",
title,
description,
"data-id": dataId,
}) => {
const { t } = useTranslation();
const options = useMemo(() => getOptions(t), [t]);
const resolvedTitle = title ?? t("usagePage.usageViewSelect.title");
const resolvedDescription = description ?? t("usagePage.usageViewSelect.description");
const getFilteredOptions = () => {
return OPTIONS.filter((option) => {
if (option.value === "tag" && canViewTagUsage) {
return options
.filter((option) => {
if (option.value === "tag" && canViewTagUsage) {
return true;
}
if (option.adminOnly && !isAdmin) {
return false;
}
return true;
}
if (option.adminOnly && !isAdmin) {
return false;
}
return true;
}).map((option) => {
let label = option.label;
let desc = option.description;
if (option.showForAdmin && option.showForNonAdmin) {
label = isAdmin ? option.showForAdmin : option.showForNonAdmin;
}
if (option.descriptionForAdmin && option.descriptionForNonAdmin) {
desc = isAdmin ? option.descriptionForAdmin : option.descriptionForNonAdmin;
}
return {
value: option.value,
label,
description: desc,
icon: option.icon,
badgeText: option.badgeText,
};
});
})
.map((option) => {
let label = option.label;
let desc = option.description;
if (option.showForAdmin && option.showForNonAdmin) {
label = isAdmin ? option.showForAdmin : option.showForNonAdmin;
}
if (option.descriptionForAdmin && option.descriptionForNonAdmin) {
desc = isAdmin ? option.descriptionForAdmin : option.descriptionForNonAdmin;
}
return {
value: option.value,
label,
description: desc,
icon: option.icon,
badgeText: option.badgeText,
};
});
};
const filteredOptions = getFilteredOptions();
return (
@ -157,8 +165,8 @@ export const UsageViewSelect: React.FC<UsageViewSelectProps> = ({
<BarChartOutlined style={{ fontSize: "32px" }} />
</div>
<div className="flex-1 min-w-0">
<h3 className="text-sm font-semibold text-gray-900 mb-0.5 leading-tight">{title}</h3>
<p className="text-xs text-gray-600 leading-tight">{description}</p>
<h3 className="text-sm font-semibold text-gray-900 mb-0.5 leading-tight">{resolvedTitle}</h3>
<p className="text-xs text-gray-600 leading-tight">{resolvedDescription}</p>
</div>
</div>
<div className="flex-shrink-0">

View file

@ -4870,6 +4870,32 @@
}
},
"usagePage": {
"usageViewSelect": {
"title": "Usage View",
"description": "Select the usage data you want to view",
"globalUsageLabel": "Global Usage",
"globalUsageDesc": "View usage across all resources",
"yourUsageLabel": "Your Usage",
"yourUsageDesc": "View your usage",
"myUsageDesc": "View your own usage",
"organizationUsageLabel": "Organization Usage",
"yourOrganizationUsageLabel": "Your Organization Usage",
"organizationUsageDesc": "View organization-level usage",
"organizationUsageAdminDesc": "View usage across all organizations",
"organizationUsageNonAdminDesc": "View your organization's usage",
"teamUsageLabel": "Team Usage",
"teamUsageDesc": "View usage by team",
"customerUsageLabel": "Customer Usage",
"customerUsageDesc": "View usage by customer accounts",
"tagUsageLabel": "Tag Usage",
"tagUsageDesc": "View usage grouped by tags",
"agentUsageLabel": "Agent Usage (A2A)",
"agentUsageDesc": "View usage by AI agents",
"userUsageLabel": "User Usage",
"userUsageDesc": "View usage by individual users",
"userAgentActivityLabel": "User Agent Activity",
"userAgentActivityDesc": "View detailed user agent activity logs"
},
"usageAiChatPanel": {
"title": "Ask AI",
"subtitle": "Ask about your spend, models, keys, and trends",

View file

@ -4870,6 +4870,32 @@
}
},
"usagePage": {
"usageViewSelect": {
"title": "用量视图",
"description": "选择您要查看的用量数据",
"globalUsageLabel": "全局用量",
"globalUsageDesc": "查看所有资源的用量",
"yourUsageLabel": "我的用量",
"yourUsageDesc": "查看您的用量",
"myUsageDesc": "查看您自己的用量",
"organizationUsageLabel": "组织用量",
"yourOrganizationUsageLabel": "我的组织用量",
"organizationUsageDesc": "查看组织级别用量",
"organizationUsageAdminDesc": "查看所有组织的用量",
"organizationUsageNonAdminDesc": "查看您所在组织的用量",
"teamUsageLabel": "团队用量",
"teamUsageDesc": "按团队查看用量",
"customerUsageLabel": "客户用量",
"customerUsageDesc": "按客户账户查看用量",
"tagUsageLabel": "标签用量",
"tagUsageDesc": "按标签分组查看用量",
"agentUsageLabel": "Agent 用量 (A2A)",
"agentUsageDesc": "按 AI Agent 查看用量",
"userUsageLabel": "用户用量",
"userUsageDesc": "按单个用户查看用量",
"userAgentActivityLabel": "用户 Agent 活动",
"userAgentActivityDesc": "查看详细的用户 Agent 活动日志"
},
"usageAiChatPanel": {
"title": "询问 AI",
"subtitle": "询问您的花费、模型、密钥及趋势",