@@ -39,6 +39,70 @@ interface ModelAddDialogProps {
3939
4040// Connectivity status type comes from utils
4141
42+ // Helper function to translate error messages from backend
43+ const translateError = ( errorMessage : string , t : ( key : string , params ?: any ) => string ) : string => {
44+ if ( ! errorMessage ) return errorMessage
45+
46+ const errorLower = errorMessage . toLowerCase ( )
47+
48+ // Extract model name from patterns like "Name 'xxx' is already in use"
49+ // Matches: "Name 'xxx' is already in use" or "Name xxx is already in use"
50+ const nameMatch = errorMessage . match ( / N a m e \s + (?: [ ' " ] ( [ ^ ' " ] + ) [ ' " ] | ( [ ^ \s , ] + ) ) \s + i s a l r e a d y i n u s e / i)
51+ if ( nameMatch ) {
52+ const modelName = nameMatch [ 1 ] || nameMatch [ 2 ]
53+ return t ( 'model.dialog.error.nameAlreadyInUse' , { name : modelName } )
54+ }
55+
56+ // Model not found pattern
57+ if ( errorLower . includes ( 'model not found' ) || errorLower . includes ( 'not found' ) ) {
58+ const modelNameMatch = errorMessage . match ( / (?: M o d e l n o t f o u n d | n o t f o u n d ) [: \s] + ( [ ^ \s , ] + ) / i)
59+ if ( modelNameMatch ) {
60+ return t ( 'model.dialog.error.modelNotFound' , { name : modelNameMatch [ 1 ] } )
61+ }
62+ return t ( 'model.dialog.error.modelNotFound' , { name : '' } )
63+ }
64+
65+ // Unsupported model type
66+ if ( errorLower . includes ( 'unsupported model type' ) ) {
67+ const typeMatch = errorMessage . match ( / u n s u p p o r t e d m o d e l t y p e [: \s] + ( [ ^ \s , ] + ) / i)
68+ if ( typeMatch ) {
69+ return t ( 'model.dialog.error.unsupportedModelType' , { type : typeMatch [ 1 ] } )
70+ }
71+ return t ( 'model.dialog.error.unsupportedModelType' , { type : 'unknown' } )
72+ }
73+
74+ // Connection failed patterns - extract model name and URL from backend error
75+ if ( errorLower . includes ( 'failed to connect' ) || errorLower . includes ( 'connection failed' ) ||
76+ errorLower . includes ( 'connection error' ) || errorLower . includes ( 'unable to connect' ) ) {
77+ // Try to extract model name and URL from pattern: "Failed to connect to model 'xxx' at https://..."
78+ // Match URL that may end with period before the next sentence (e.g., "https://api.example.com. Please verify...")
79+ // Match URL pattern: http:// or https:// followed by domain (may contain dots) and optional path
80+ // Example: "Failed to connect to model 'qwen-plus' at https://api.siliconflow.cn. Please verify..."
81+ const connectMatch = errorMessage . match ( / F a i l e d t o c o n n e c t t o m o d e l \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] \s + a t \s + ( h t t p s ? : \/ \/ [ ^ \s ] + ?) (?: \. \s | \. $ | $ ) / i)
82+ if ( connectMatch ) {
83+ // Remove trailing period if present (URL might end with period before next sentence)
84+ let url = connectMatch [ 2 ] . replace ( / \. $ / , '' )
85+ // Return fully translated message with model name and URL
86+ return t ( 'model.dialog.error.failedToConnect' , {
87+ modelName : connectMatch [ 1 ] ,
88+ url : url
89+ } )
90+ }
91+ // Fallback: return original error message (will be wrapped by connectivityFailed)
92+ return errorMessage
93+ }
94+
95+ // Invalid configuration
96+ if ( errorLower . includes ( 'invalid' ) && errorLower . includes ( 'config' ) ) {
97+ // Extract the actual error description
98+ const configError = errorMessage . replace ( / ^ .* ?i n v a l i d [ ^ : ] * : ? \s * / i, '' ) . trim ( ) || errorMessage
99+ return t ( 'model.dialog.error.invalidConfiguration' , { error : configError } )
100+ }
101+
102+ // Return original error if no pattern matches
103+ return errorMessage
104+ }
105+
42106export const ModelAddDialog = ( {
43107 isOpen,
44108 onClose,
@@ -66,7 +130,6 @@ export const ModelAddDialog = ({
66130 // For other errors, return generic error key without showing backend details
67131 return { key : 'model.dialog.error.addFailed' }
68132 }
69-
70133 const [ form , setForm ] = useState ( {
71134 type : MODEL_TYPES . LLM as ModelType ,
72135 name : "" ,
@@ -231,9 +294,14 @@ export const ModelAddDialog = ({
231294 status : "unavailable" ,
232295 message : t ( "model.dialog.connectivity.status.unavailable" )
233296 } ) ;
234- // Show detailed error message using message.error (same as add failure)
297+ // Show detailed error message using internationalized component (same as add failure)
235298 if ( result . error ) {
236- message . error ( result . error )
299+ const translatedError = translateError ( result . error , t )
300+ // Ensure translatedError is a valid string, fallback to original error if needed
301+ const errorText = ( translatedError && translatedError . length > 0 )
302+ ? translatedError
303+ : ( result . error || 'Unknown error' )
304+ message . error ( t ( 'model.dialog.error.connectivityFailed' , { error : errorText } ) )
237305 }
238306 }
239307 } catch ( error ) {
@@ -242,8 +310,11 @@ export const ModelAddDialog = ({
242310 status : "unavailable" ,
243311 message : t ( "model.dialog.connectivity.status.unavailable" ) ,
244312 } ) ;
245- // Show error message using message.error (same as add failure)
246- message . error ( errorMessage || t ( "model.dialog.connectivity.status.unavailable" ) )
313+ // Show error message using internationalized component (same as add failure)
314+ const translatedError = translateError ( errorMessage || t ( 'model.dialog.connectivity.status.unavailable' ) , t )
315+ // Ensure translatedError is a valid string
316+ const errorText = translatedError ? translatedError : ( errorMessage || t ( "model.dialog.connectivity.status.unavailable" ) )
317+ message . error ( t ( 'model.dialog.error.connectivityFailed' , { error : errorText } ) )
247318 } finally {
248319 setVerifyingConnectivity ( false ) ;
249320 }
@@ -280,8 +351,9 @@ export const ModelAddDialog = ({
280351 onSuccess ( ) ;
281352 }
282353 } catch ( error : any ) {
283- const errorInfo = parseModelError ( error ?. message || "" )
284- message . error ( t ( errorInfo . key , errorInfo . params ) )
354+ const errorMessage = error ?. message || t ( "model.dialog.error.addFailedLog" ) ;
355+ const translatedError = translateError ( errorMessage , t )
356+ message . error ( t ( "model.dialog.error.addFailed" , { error : translatedError } ) ) ;
285357 }
286358
287359 setForm ( ( prev ) => ( {
@@ -441,8 +513,8 @@ export const ModelAddDialog = ({
441513 onClose ( ) ;
442514 } catch ( error ) {
443515 const errorMessage = error instanceof Error ? error . message : String ( error )
444- const errorInfo = parseModelError ( errorMessage )
445- message . error ( t ( errorInfo . key , errorInfo . params ) ) ;
516+ const translatedError = translateError ( errorMessage , t )
517+ message . error ( t ( "model.dialog.error.addFailed" , { error : translatedError } ) ) ;
446518 log . error ( t ( "model.dialog.error.addFailedLog" ) , error ) ;
447519 } finally {
448520 setLoading ( false ) ;
0 commit comments