jan/web-app/src/containers/ApiKeyInput.tsx
Sam Hoang Van c32dd092d0
Enhance i18n and add missing i18n for all component (#5314)
* Refactor translation imports and update text for localization across settings and system monitor routes

- Changed translation import from 'react-i18next' to '@/i18n/react-i18next-compat' in multiple files.
- Updated various text strings to use translation keys for better localization support in:
  - Local API Server settings
  - MCP Servers settings
  - Privacy settings
  - Provider settings
  - Shortcuts settings
  - System Monitor
  - Thread details
- Ensured consistent use of translation keys for all user-facing text.

Update web-app/src/routes/settings/appearance.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

Update web-app/src/routes/settings/appearance.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

Update web-app/src/locales/vn/settings.json

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

Update web-app/src/containers/dialogs/DeleteMCPServerConfirm.tsx

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

Update web-app/src/locales/id/common.json

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Add Chinese (Simplified and Traditional) localization files for various components

- Created `tools.json`, `updater.json`, `assistants.json`, `chat.json`, `common.json`, `hub.json`, `logs.json`, `mcp-servers.json`, `provider.json`, `providers.json`, `settings.json`, `setup.json`, `system-monitor.json`, `tool-approval.json` in both `zh-CN` and `zh-TW` locales.
- Added translations for tool approval, updater notifications, assistant management, chat interface, common UI elements, hub interactions, logging messages, MCP server configurations, provider management, settings options, setup instructions, and system monitoring.

* Refactor localization strings for improved clarity and consistency in English, Indonesian, and Vietnamese settings files

* Fix missing key and reword

* fix pr comment

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-06-20 15:33:54 +07:00

91 lines
2.6 KiB
TypeScript

import { Input } from '@/components/ui/input'
import { useLocalApiServer } from '@/hooks/useLocalApiServer'
import { useState, useEffect, useCallback } from 'react'
import { Eye, EyeOff } from 'lucide-react'
import { useTranslation } from '@/i18n/react-i18next-compat'
interface ApiKeyInputProps {
showError?: boolean
onValidationChange?: (isValid: boolean) => void
}
export function ApiKeyInput({
showError = false,
onValidationChange,
}: ApiKeyInputProps) {
const { apiKey, setApiKey } = useLocalApiServer()
const [inputValue, setInputValue] = useState(apiKey.toString())
const [showPassword, setShowPassword] = useState(false)
const [error, setError] = useState('')
const { t } = useTranslation()
const validateApiKey = useCallback((value: string) => {
if (!value || value.trim().length === 0) {
setError(t('common:apiKeyRequired'))
onValidationChange?.(false)
return false
}
setError('')
onValidationChange?.(true)
return true
}, [onValidationChange, t])
useEffect(() => {
if (showError) {
validateApiKey(inputValue)
}
}, [showError, inputValue, validateApiKey])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
setInputValue(value)
// Clear error when user starts typing
if (error && value.trim().length > 0) {
setError('')
onValidationChange?.(true)
}
}
const handleBlur = () => {
setApiKey(inputValue)
// Validate on blur if showError is true
if (showError) {
validateApiKey(inputValue)
}
}
const hasError = error && showError
return (
<div className="relative w-full">
<Input
type={showPassword ? 'text' : 'password'}
value={inputValue}
onChange={handleChange}
onBlur={handleBlur}
className={`w-full text-sm pr-10 ${
hasError
? 'border-1 border-destructive focus:border-destructive focus:ring-destructive'
: ''
}`}
placeholder={t('common:enterApiKey')}
/>
<div className="absolute right-2 top-1/2 transform -translate-y-1/2 flex items-center gap-1">
<button
onClick={() => setShowPassword(!showPassword)}
className="p-1 rounded hover:bg-main-view-fg/5 text-main-view-fg/70"
type="button"
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
{hasError && (
<p className="text-destructive text-xs mt-1 absolute -bottom-5 left-0">
{error}
</p>
)}
</div>
)
}