fix: Add i18n and accessibility to TokenUsageIndicator

This commit is contained in:
Marco Beretta 2025-12-14 02:33:10 +01:00
parent 841a37e8cb
commit 8cedd5f45e
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
3 changed files with 29 additions and 5 deletions

View file

@ -1,6 +1,6 @@
import { memo } from 'react';
import { TooltipAnchor } from '@librechat/client';
import { useTokenUsage } from '~/hooks';
import { useLocalize, useTokenUsage } from '~/hooks';
import { cn } from '~/utils';
function formatTokens(n: number): string {
@ -14,6 +14,7 @@ function formatTokens(n: number): string {
}
const TokenUsageIndicator = memo(function TokenUsageIndicator() {
const localize = useLocalize();
const { inputTokens, outputTokens, maxContext } = useTokenUsage();
const totalUsed = inputTokens + outputTokens;
@ -28,10 +29,21 @@ const TokenUsageIndicator = memo(function TokenUsageIndicator() {
const offset = circumference - (percentage / 100) * circumference;
const tooltipText = hasMaxContext
? `Input: ${formatTokens(inputTokens)} | Output: ${formatTokens(outputTokens)} | Max: ${formatTokens(maxContext)}`
: `Input: ${formatTokens(inputTokens)} | Output: ${formatTokens(outputTokens)} | Max: N/A`;
? localize('com_ui_token_usage_with_max', {
0: formatTokens(inputTokens),
1: formatTokens(outputTokens),
2: formatTokens(maxContext),
})
: localize('com_ui_token_usage_no_max', {
0: formatTokens(inputTokens),
1: formatTokens(outputTokens),
});
// Color based on percentage
const ariaLabel = hasMaxContext
? localize('com_ui_token_usage_aria', { 0: Math.round(percentage).toString() })
: localize('com_ui_token_usage_indicator');
// Color based on percentage (using raw colors to match existing patterns in AudioRecorder.tsx)
const getProgressColor = () => {
if (!hasMaxContext) {
return 'stroke-text-secondary';
@ -49,12 +61,17 @@ const TokenUsageIndicator = memo(function TokenUsageIndicator() {
<TooltipAnchor
description={tooltipText}
render={
<div className="flex size-9 items-center justify-center rounded-full p-1 transition-colors hover:bg-surface-hover">
<div
className="flex size-9 items-center justify-center rounded-full p-1 transition-colors hover:bg-surface-hover"
role="img"
aria-label={ariaLabel}
>
<svg
width={size}
height={size}
viewBox={`0 0 ${size} ${size}`}
className="rotate-[-90deg]"
aria-hidden="true"
>
{/* Background ring */}
<circle

View file

@ -1322,6 +1322,10 @@
"com_ui_token": "token",
"com_ui_token_exchange_method": "Token Exchange Method",
"com_ui_token_url": "Token URL",
"com_ui_token_usage_aria": "Context window {{0}}% used",
"com_ui_token_usage_indicator": "Token usage indicator",
"com_ui_token_usage_no_max": "Input: {{0}} | Output: {{1}} | Max: N/A",
"com_ui_token_usage_with_max": "Input: {{0}} | Output: {{1}} | Max: {{2}}",
"com_ui_tokens": "tokens",
"com_ui_tool_collection_prefix": "A collection of tools from",
"com_ui_tool_list_collapse": "Collapse {{serverName}} tool list",

View file

@ -12,9 +12,11 @@ import lang from './language';
import settings from './settings';
import misc from './misc';
import isTemporary from './temporary';
import * as tokenUsage from './tokenUsage';
export * from './agents';
export * from './mcp';
export * from './favorites';
export * from './tokenUsage';
export default {
...artifacts,
@ -31,4 +33,5 @@ export default {
...settings,
...misc,
...isTemporary,
...tokenUsage,
};