11import React , { useState , useEffect } from 'react' ;
22import './ApiKeyModal.css' ;
33import queuedFetch from '../utils/requestQueue' ;
4+ import { useTranslation } from 'react-i18next' ;
45
56const ApiKeyModal = ( { isOpen, onClose, missingKeys, modelType, onSubmit, serverUrl } ) => {
7+ const { t } = useTranslation ( ) ;
68 const [ selectedService , setSelectedService ] = useState ( '' ) ;
79 const [ apiKeyValue , setApiKeyValue ] = useState ( '' ) ;
810 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
911 const [ error , setError ] = useState ( '' ) ;
1012
11- // Define all available API services
12- const apiServices = [
13- { value : 'OPENAI_API_KEY' , label : 'OpenAI API Key' , description : 'For GPT models (starts with sk-)' } ,
14- { value : 'ANTHROPIC_API_KEY' , label : 'Anthropic API Key' , description : 'For Claude models' } ,
15- { value : 'GEMINI_API_KEY' , label : 'Gemini API Key' , description : 'For Google Gemini models' } ,
16- { value : 'GROQ_API_KEY' , label : 'Groq API Key' , description : 'For Groq models' } ,
17- { value : 'TOGETHER_API_KEY' , label : 'Together AI API Key' , description : 'For Together AI models' } ,
18- { value : 'AZURE_API_KEY' , label : 'Azure OpenAI API Key' , description : 'For Azure OpenAI service' } ,
19- { value : 'AZURE_BASE_URL' , label : 'Azure Base URL' , description : 'Azure OpenAI endpoint URL' } ,
20- { value : 'AZURE_API_VERSION' , label : 'Azure API Version' , description : 'e.g., 2024-09-01-preview' } ,
21- { value : 'AWS_ACCESS_KEY_ID' , label : 'AWS Access Key ID' , description : 'For AWS Bedrock' } ,
22- { value : 'AWS_SECRET_ACCESS_KEY' , label : 'AWS Secret Access Key' , description : 'For AWS Bedrock' } ,
23- { value : 'AWS_REGION' , label : 'AWS Region' , description : 'e.g., us-east-1' } ,
13+ // Define all available API services using translations
14+ const getApiServices = ( ) => [
15+ { value : 'OPENAI_API_KEY' , label : t ( 'settings.modals.apiKey.services.OPENAI_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.OPENAI_API_KEY.description' ) } ,
16+ { value : 'ANTHROPIC_API_KEY' , label : t ( 'settings.modals.apiKey.services.ANTHROPIC_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.ANTHROPIC_API_KEY.description' ) } ,
17+ { value : 'GEMINI_API_KEY' , label : t ( 'settings.modals.apiKey.services.GEMINI_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.GEMINI_API_KEY.description' ) } ,
18+ { value : 'GROQ_API_KEY' , label : t ( 'settings.modals.apiKey.services.GROQ_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.GROQ_API_KEY.description' ) } ,
19+ { value : 'TOGETHER_API_KEY' , label : t ( 'settings.modals.apiKey.services.TOGETHER_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.TOGETHER_API_KEY.description' ) } ,
20+ { value : 'AZURE_API_KEY' , label : t ( 'settings.modals.apiKey.services.AZURE_API_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.AZURE_API_KEY.description' ) } ,
21+ { value : 'AZURE_BASE_URL' , label : t ( 'settings.modals.apiKey.services.AZURE_BASE_URL.label' ) , description : t ( 'settings.modals.apiKey.services.AZURE_BASE_URL.description' ) } ,
22+ { value : 'AZURE_API_VERSION' , label : t ( 'settings.modals.apiKey.services.AZURE_API_VERSION.label' ) , description : t ( 'settings.modals.apiKey.services.AZURE_API_VERSION.description' ) } ,
23+ { value : 'AWS_ACCESS_KEY_ID' , label : t ( 'settings.modals.apiKey.services.AWS_ACCESS_KEY_ID.label' ) , description : t ( 'settings.modals.apiKey.services.AWS_ACCESS_KEY_ID.description' ) } ,
24+ { value : 'AWS_SECRET_ACCESS_KEY' , label : t ( 'settings.modals.apiKey.services.AWS_SECRET_ACCESS_KEY.label' ) , description : t ( 'settings.modals.apiKey.services.AWS_SECRET_ACCESS_KEY.description' ) } ,
25+ { value : 'AWS_REGION' , label : t ( 'settings.modals.apiKey.services.AWS_REGION.label' ) , description : t ( 'settings.modals.apiKey.services.AWS_REGION.description' ) } ,
2426 ] ;
2527
28+ const apiServices = getApiServices ( ) ;
29+
2630 const getKeyPlaceholder = ( keyName ) => {
2731 const placeholders = {
2832 'OPENAI_API_KEY' : 'sk-...' ,
@@ -32,7 +36,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
3236 'AZURE_API_VERSION' : '2024-09-01-preview' ,
3337 'AWS_REGION' : 'us-east-1' ,
3438 } ;
35- return placeholders [ keyName ] || 'Enter your API key...' ;
39+ return placeholders [ keyName ] || t ( 'settings.modals.apiKey.enterKeyPlaceholder' ) ;
3640 } ;
3741
3842 const isMissingKeysMode = missingKeys && missingKeys . length > 0 ;
@@ -50,7 +54,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
5054 const handleSubmit = async ( e ) => {
5155 e . preventDefault ( ) ;
5256 setIsSubmitting ( true ) ;
53- setError ( '⏳ Saving API keys...' ) ;
57+ setError ( `⏳ ${ t ( 'settings.modals.apiKey.savingKeys' ) } ` ) ;
5458
5559 try {
5660 if ( isMissingKeysMode ) {
@@ -85,7 +89,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
8589 } else {
8690 // Handle manual update mode - submit selected service
8791 if ( ! selectedService || ! apiKeyValue ) {
88- setError ( 'Please select a service and enter an API key' ) ;
92+ setError ( t ( 'settings.modals.apiKey.pleaseSelectService' ) ) ;
8993 setIsSubmitting ( false ) ;
9094 return ;
9195 }
@@ -108,7 +112,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
108112 }
109113
110114 // Show success message
111- setError ( '✅ API keys saved successfully!' ) ;
115+ setError ( `✅ ${ t ( 'settings.modals.apiKey.keysSuccessfullySaved' ) } ` ) ;
112116
113117 // Small delay to show the message before closing
114118 await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
@@ -117,7 +121,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
117121 onSubmit ( ) ;
118122 onClose ( ) ;
119123 } catch ( err ) {
120- setError ( err . message || 'Failed to update API keys' ) ;
124+ setError ( err . message || t ( 'settings.modals.apiKey.failedToUpdate' ) ) ;
121125 } finally {
122126 setIsSubmitting ( false ) ;
123127 }
@@ -139,14 +143,14 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
139143 < div className = "api-key-modal-overlay" >
140144 < div className = "api-key-modal" >
141145 < div className = "api-key-modal-header" >
142- < h2 > 🔑 { isMissingKeysMode ? 'API Keys Required' : 'Update API Keys' } </ h2 >
146+ < h2 > 🔑 { isMissingKeysMode ? t ( 'settings.modals.apiKey.titleRequired' ) : t ( 'settings.modals.apiKey.title' ) } </ h2 >
143147 { isMissingKeysMode ? (
144148 < p >
145- The < strong > { modelType } </ strong > model requires the following API keys to function properly:
149+ { t ( 'settings.modals.apiKey.requiredDescription' , { modelType } ) }
146150 </ p >
147151 ) : (
148152 < p >
149- Select the API service you want to update and enter your new API key:
153+ { t ( 'settings.modals.apiKey.manualDescription' ) }
150154 </ p >
151155 ) }
152156 </ div >
@@ -177,8 +181,8 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
177181 < >
178182 < div className = "api-key-field" >
179183 < label htmlFor = "service-select" >
180- < strong > Select API Service </ strong >
181- < span className = "key-description" > Choose which API service you want to update </ span >
184+ < strong > { t ( 'settings.modals.apiKey.selectService' ) } </ strong >
185+ < span className = "key-description" > { t ( 'settings.modals.apiKey.selectServiceDescription' ) } </ span >
182186 </ label >
183187 < select
184188 id = "service-select"
@@ -187,7 +191,7 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
187191 required
188192 className = "api-key-select"
189193 >
190- < option value = "" > -- Select a service -- </ option >
194+ < option value = "" > { t ( 'settings.modals.apiKey.selectServicePlaceholder' ) } </ option >
191195 { apiServices . map ( ( service ) => (
192196 < option key = { service . value } value = { service . value } >
193197 { service . label }
@@ -217,8 +221,8 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
217221 ) }
218222
219223 { error && (
220- < div className = { `api-key-error ${ error . includes ( 'successfully' ) || error . includes ( 'Saving' ) ? 'api-key-info' : '' } ` } >
221- { error . includes ( 'successfully' ) || error . includes ( 'Saving' ) ? error : `❌ ${ error } ` }
224+ < div className = { `api-key-error ${ error . includes ( t ( 'settings.modals.apiKey.keysSuccessfullySaved' ) ) || error . includes ( t ( 'settings.modals.apiKey.savingKeys' ) ) ? 'api-key-info' : '' } ` } >
225+ { error . includes ( t ( 'settings.modals.apiKey.keysSuccessfullySaved' ) ) || error . includes ( t ( 'settings.modals.apiKey.savingKeys' ) ) ? error : `❌ ${ error } ` }
222226 </ div >
223227 ) }
224228
@@ -229,21 +233,21 @@ const ApiKeyModal = ({ isOpen, onClose, missingKeys, modelType, onSubmit, server
229233 className = "api-key-cancel-btn"
230234 disabled = { isSubmitting }
231235 >
232- Cancel
236+ { t ( 'settings.modals.apiKey.cancel' ) }
233237 </ button >
234238 < button
235239 type = "submit"
236240 className = "api-key-submit-btn"
237241 disabled = { isSubmitting || ( isMissingKeysMode ? false : ( ! selectedService || ! apiKeyValue ) ) }
238242 >
239- { isSubmitting ? ( error . includes ( 'successfully' ) ? '✅ Saved!' : '⏳ Saving...' ) : '✅ Save API Keys' }
243+ { isSubmitting ? ( error . includes ( t ( 'settings.modals.apiKey.keysSuccessfullySaved' ) ) ? `✅ ${ t ( 'settings.modals.apiKey.saved' ) } ` : `⏳ ${ t ( 'settings.modals.apiKey.saving' ) } ` ) : `✅ ${ t ( 'settings.modals.apiKey.save' ) } ` }
240244 </ button >
241245 </ div >
242246 </ form >
243247
244248 < div className = "api-key-note" >
245249 < p >
246- < strong > Note: </ strong > Your API keys will be saved securely to your local database for permanent storage and will persist across sessions.
250+ < strong > { t ( 'settings.modals.apiKey.noteLabel' ) } </ strong > { t ( 'settings.modals.apiKey.note' ) }
247251 </ p >
248252 </ div >
249253 </ div >
0 commit comments