@@ -14,6 +14,7 @@ import { iife } from "@opencode-ai/util/iife"
1414import { createMemo , Match , onCleanup , onMount , Switch } from "solid-js"
1515import { createStore , produce } from "solid-js/store"
1616import { Link } from "@/components/link"
17+ import { useLanguage } from "@/context/language"
1718import { useGlobalSDK } from "@/context/global-sdk"
1819import { useGlobalSync } from "@/context/global-sync"
1920import { usePlatform } from "@/context/platform"
@@ -25,6 +26,7 @@ export function DialogConnectProvider(props: { provider: string }) {
2526 const globalSync = useGlobalSync ( )
2627 const globalSDK = useGlobalSDK ( )
2728 const platform = usePlatform ( )
29+ const language = useLanguage ( )
2830 const provider = createMemo ( ( ) => globalSync . data . provider . all . find ( ( x ) => x . id === props . provider ) ! )
2931 const methods = createMemo (
3032 ( ) =>
@@ -44,6 +46,12 @@ export function DialogConnectProvider(props: { provider: string }) {
4446
4547 const method = createMemo ( ( ) => ( store . methodIndex !== undefined ? methods ( ) . at ( store . methodIndex ! ) : undefined ) )
4648
49+ const methodLabel = ( value ?: { type ?: string ; label ?: string } ) => {
50+ if ( ! value ) return ""
51+ if ( value . type === "api" ) return language . t ( "provider.connect.method.apiKey" )
52+ return value . label ?? ""
53+ }
54+
4755 async function selectMethod ( index : number ) {
4856 const method = methods ( ) [ index ]
4957 setStore (
@@ -112,8 +120,8 @@ export function DialogConnectProvider(props: { provider: string }) {
112120 showToast ( {
113121 variant : "success" ,
114122 icon : "circle-check" ,
115- title : ` ${ provider ( ) . name } connected` ,
116- description : ` ${ provider ( ) . name } models are now available to use.` ,
123+ title : language . t ( "provider.connect.toast.connected.title" , { provider : provider ( ) . name } ) ,
124+ description : language . t ( "provider.connect.toast.connected.description" , { provider : provider ( ) . name } ) ,
117125 } )
118126 }
119127
@@ -142,16 +150,18 @@ export function DialogConnectProvider(props: { provider: string }) {
142150 < div class = "text-16-medium text-text-strong" >
143151 < Switch >
144152 < Match when = { props . provider === "anthropic" && method ( ) ?. label ?. toLowerCase ( ) . includes ( "max" ) } >
145- Login with Claude Pro/Max
153+ { language . t ( "provider.connect.title.anthropicProMax" ) }
146154 </ Match >
147- < Match when = { true } > Connect { provider ( ) . name } </ Match >
155+ < Match when = { true } > { language . t ( "provider.connect.title" , { provider : provider ( ) . name } ) } </ Match >
148156 </ Switch >
149157 </ div >
150158 </ div >
151159 < div class = "px-2.5 pb-10 flex flex-col gap-6" >
152160 < Switch >
153161 < Match when = { store . methodIndex === undefined } >
154- < div class = "text-14-regular text-text-base" > Select login method for { provider ( ) . name } .</ div >
162+ < div class = "text-14-regular text-text-base" >
163+ { language . t ( "provider.connect.selectMethod" , { provider : provider ( ) . name } ) }
164+ </ div >
155165 < div class = "" >
156166 < List
157167 ref = { ( ref ) => {
@@ -169,7 +179,7 @@ export function DialogConnectProvider(props: { provider: string }) {
169179 < div class = "w-4 h-2 rounded-[1px] bg-input-base shadow-xs-border-base flex items-center justify-center" >
170180 < div class = "w-2.5 h-0.5 bg-icon-strong-base hidden" data-slot = "list-item-extra-icon" />
171181 </ div >
172- < span > { i . label } </ span >
182+ < span > { methodLabel ( i ) } </ span >
173183 </ div >
174184 ) }
175185 </ List >
@@ -179,15 +189,15 @@ export function DialogConnectProvider(props: { provider: string }) {
179189 < div class = "text-14-regular text-text-base" >
180190 < div class = "flex items-center gap-x-2" >
181191 < Spinner />
182- < span > Authorization in progress... </ span >
192+ < span > { language . t ( "provider.connect.status.inProgress" ) } </ span >
183193 </ div >
184194 </ div >
185195 </ Match >
186196 < Match when = { store . state === "error" } >
187197 < div class = "text-14-regular text-text-base" >
188198 < div class = "flex items-center gap-x-2" >
189199 < Icon name = "circle-ban-sign" class = "text-icon-critical-base" />
190- < span > Authorization failed: { store . error } </ span >
200+ < span > { language . t ( "provider.connect.status. failed" , { error : store . error ?? "" } ) } </ span >
191201 </ div >
192202 </ div >
193203 </ Match >
@@ -206,7 +216,7 @@ export function DialogConnectProvider(props: { provider: string }) {
206216 const apiKey = formData . get ( "apiKey" ) as string
207217
208218 if ( ! apiKey ?. trim ( ) ) {
209- setFormStore ( "error" , "API key is required")
219+ setFormStore ( "error" , language . t ( "provider.connect.apiKey. required") )
210220 return
211221 }
212222
@@ -226,43 +236,37 @@ export function DialogConnectProvider(props: { provider: string }) {
226236 < Switch >
227237 < Match when = { provider ( ) . id === "opencode" } >
228238 < div class = "flex flex-col gap-4" >
239+ < div class = "text-14-regular text-text-base" > { language . t ( "provider.connect.opencodeZen.line1" ) } </ div >
240+ < div class = "text-14-regular text-text-base" > { language . t ( "provider.connect.opencodeZen.line2" ) } </ div >
229241 < div class = "text-14-regular text-text-base" >
230- OpenCode Zen gives you access to a curated set of reliable optimized models for coding
231- agents.
232- </ div >
233- < div class = "text-14-regular text-text-base" >
234- With a single API key you'll get access to models such as Claude, GPT, Gemini, GLM and more.
235- </ div >
236- < div class = "text-14-regular text-text-base" >
237- Visit{ " " }
242+ { language . t ( "provider.connect.opencodeZen.visit.prefix" ) }
238243 < Link href = "https://opencode.ai/zen" tabIndex = { - 1 } >
239244 opencode.ai/zen
240- </ Link > { " " }
241- to collect your API key.
245+ </ Link >
246+ { language . t ( "provider.connect.opencodeZen.visit.suffix" ) }
242247 </ div >
243248 </ div >
244249 </ Match >
245250 < Match when = { true } >
246251 < div class = "text-14-regular text-text-base" >
247- Enter your { provider ( ) . name } API key to connect your account and use { provider ( ) . name } models
248- in OpenCode.
252+ { language . t ( "provider.connect.apiKey.description" , { provider : provider ( ) . name } ) }
249253 </ div >
250254 </ Match >
251255 </ Switch >
252256 < form onSubmit = { handleSubmit } class = "flex flex-col items-start gap-4" >
253257 < TextField
254258 autofocus
255259 type = "text"
256- label = { ` ${ provider ( ) . name } API key` }
257- placeholder = "API key"
260+ label = { language . t ( "provider.connect.apiKey.label" , { provider : provider ( ) . name } ) }
261+ placeholder = { language . t ( "provider.connect.apiKey.placeholder" ) }
258262 name = "apiKey"
259263 value = { formStore . value }
260264 onChange = { setFormStore . bind ( null , "value" ) }
261265 validationState = { formStore . error ? "invalid" : undefined }
262266 error = { formStore . error }
263267 />
264268 < Button class = "w-auto" type = "submit" size = "large" variant = "primary" >
265- Submit
269+ { language . t ( "common.submit" ) }
266270 </ Button >
267271 </ form >
268272 </ div >
@@ -292,7 +296,7 @@ export function DialogConnectProvider(props: { provider: string }) {
292296 const code = formData . get ( "code" ) as string
293297
294298 if ( ! code ?. trim ( ) ) {
295- setFormStore ( "error" , "Authorization code is required")
299+ setFormStore ( "error" , language . t ( "provider.connect.oauth. code. required") )
296300 return
297301 }
298302
@@ -306,29 +310,30 @@ export function DialogConnectProvider(props: { provider: string }) {
306310 await complete ( )
307311 return
308312 }
309- setFormStore ( "error" , "Invalid authorization code" )
313+ setFormStore ( "error" , language . t ( "provider.connect.oauth. code.invalid" ) )
310314 }
311315
312316 return (
313317 < div class = "flex flex-col gap-6" >
314318 < div class = "text-14-regular text-text-base" >
315- Visit < Link href = { store . authorization ! . url } > this link</ Link > to collect your authorization
316- code to connect your account and use { provider ( ) . name } models in OpenCode.
319+ { language . t ( "provider.connect.oauth.code.visit.prefix" ) }
320+ < Link href = { store . authorization ! . url } > { language . t ( "provider.connect.oauth.code.visit.link" ) } </ Link >
321+ { language . t ( "provider.connect.oauth.code.visit.suffix" , { provider : provider ( ) . name } ) }
317322 </ div >
318323 < form onSubmit = { handleSubmit } class = "flex flex-col items-start gap-4" >
319324 < TextField
320325 autofocus
321326 type = "text"
322- label = { ` ${ method ( ) ?. label } authorization code` }
323- placeholder = "Authorization code"
327+ label = { language . t ( "provider.connect.oauth.code.label" , { method : method ( ) ?. label ?? "" } ) }
328+ placeholder = { language . t ( "provider.connect.oauth. code.placeholder" ) }
324329 name = "code"
325330 value = { formStore . value }
326331 onChange = { setFormStore . bind ( null , "value" ) }
327332 validationState = { formStore . error ? "invalid" : undefined }
328333 error = { formStore . error }
329334 />
330335 < Button class = "w-auto" type = "submit" size = "large" variant = "primary" >
331- Submit
336+ { language . t ( "common.submit" ) }
332337 </ Button >
333338 </ form >
334339 </ div >
@@ -361,13 +366,20 @@ export function DialogConnectProvider(props: { provider: string }) {
361366 return (
362367 < div class = "flex flex-col gap-6" >
363368 < div class = "text-14-regular text-text-base" >
364- Visit < Link href = { store . authorization ! . url } > this link</ Link > and enter the code below to
365- connect your account and use { provider ( ) . name } models in OpenCode.
369+ { language . t ( "provider.connect.oauth.auto.visit.prefix" ) }
370+ < Link href = { store . authorization ! . url } > { language . t ( "provider.connect.oauth.auto.visit.link" ) } </ Link >
371+ { language . t ( "provider.connect.oauth.auto.visit.suffix" , { provider : provider ( ) . name } ) }
366372 </ div >
367- < TextField label = "Confirmation code" class = "font-mono" value = { code ( ) } readOnly copyable />
373+ < TextField
374+ label = { language . t ( "provider.connect.oauth.auto.confirmationCode" ) }
375+ class = "font-mono"
376+ value = { code ( ) }
377+ readOnly
378+ copyable
379+ />
368380 < div class = "text-14-regular text-text-base flex items-center gap-4" >
369381 < Spinner />
370- < span > Waiting for authorization... </ span >
382+ < span > { language . t ( "provider.connect.status.waiting" ) } </ span >
371383 </ div >
372384 </ div >
373385 )
0 commit comments