@cat-factory/app 0.47.4 → 0.47.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@
6
6
  // successful connect the github store flips `connected`, which the host surfaces
7
7
  // react to. Shared by the GitHub panel and the bootstrap modal so the connect
8
8
  // flow lives in one place.
9
+ const { t } = useI18n()
9
10
  const github = useGitHubStore()
10
11
  const toast = useToast()
11
12
 
@@ -33,7 +34,7 @@ async function refreshInstallations() {
33
34
  await github.loadInstallations()
34
35
  } catch (e) {
35
36
  // A 503 (integration off) is handled by the host; surface anything else.
36
- notifyError('Could not list GitHub installations', e)
37
+ notifyError(t('github.connect.errors.listInstallations'), e)
37
38
  }
38
39
  }
39
40
 
@@ -42,7 +43,7 @@ async function install() {
42
43
  try {
43
44
  window.location.href = await github.getInstallUrl()
44
45
  } catch (e) {
45
- notifyError('Could not start the GitHub App install', e)
46
+ notifyError(t('github.connect.errors.startInstall'), e)
46
47
  installing.value = false
47
48
  }
48
49
  }
@@ -53,9 +54,13 @@ async function connect(id: number, onDone?: () => void) {
53
54
  try {
54
55
  await github.connect(id)
55
56
  onDone?.()
56
- toast.add({ title: 'GitHub connected', icon: 'i-lucide-check', color: 'success' })
57
+ toast.add({
58
+ title: t('github.connect.toast.connected'),
59
+ icon: 'i-lucide-check',
60
+ color: 'success',
61
+ })
57
62
  } catch (e) {
58
- notifyError('Could not connect', e)
63
+ notifyError(t('github.connect.errors.connect'), e)
59
64
  } finally {
60
65
  connecting.value = false
61
66
  connectingId.value = null
@@ -77,7 +82,7 @@ async function connectManually() {
77
82
  <section class="space-y-2">
78
83
  <div class="flex items-center justify-between">
79
84
  <span class="text-xs font-medium uppercase tracking-wide text-slate-500">
80
- Your installations
85
+ {{ t('github.connect.yourInstallations') }}
81
86
  </span>
82
87
  <UButton
83
88
  size="xs"
@@ -87,7 +92,7 @@ async function connectManually() {
87
92
  :loading="github.loadingInstallations"
88
93
  @click="refreshInstallations"
89
94
  >
90
- Refresh
95
+ {{ t('github.connect.refresh') }}
91
96
  </UButton>
92
97
  </div>
93
98
 
@@ -95,14 +100,15 @@ async function connectManually() {
95
100
  v-if="github.loadingInstallations && !github.installations.length"
96
101
  class="flex items-center gap-2 py-3 text-sm text-slate-400"
97
102
  >
98
- <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" /> Looking for installations…
103
+ <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" />
104
+ {{ t('github.connect.lookingForInstallations') }}
99
105
  </div>
100
106
 
101
107
  <p
102
108
  v-else-if="!github.installations.length"
103
109
  class="rounded-md border border-dashed border-slate-800 px-3 py-3 text-sm text-slate-400"
104
110
  >
105
- No installations found for the App yet. Install it below, or connect by ID.
111
+ {{ t('github.connect.noInstallations') }}
106
112
  </p>
107
113
 
108
114
  <div
@@ -121,7 +127,12 @@ async function connectManually() {
121
127
  <div class="min-w-0">
122
128
  <div class="truncate text-sm text-slate-200">{{ inst.accountLogin }}</div>
123
129
  <div class="text-[11px] text-slate-500">
124
- {{ inst.targetType }} · installation {{ inst.installationId }}
130
+ {{
131
+ t('github.connect.installationMeta', {
132
+ targetType: inst.targetType,
133
+ id: inst.installationId,
134
+ })
135
+ }}
125
136
  </div>
126
137
  </div>
127
138
  </div>
@@ -130,18 +141,18 @@ async function connectManually() {
130
141
  color="success"
131
142
  variant="subtle"
132
143
  size="sm"
133
- title="Already linked to this workspace"
144
+ :title="t('github.connect.linkedTitle')"
134
145
  >
135
- linked
146
+ {{ t('github.connect.linked') }}
136
147
  </UBadge>
137
148
  <UBadge
138
149
  v-else-if="inst.connected === 'other'"
139
150
  color="neutral"
140
151
  variant="subtle"
141
152
  size="sm"
142
- title="Already connected to another workspace"
153
+ :title="t('github.connect.inUseTitle')"
143
154
  >
144
- in use
155
+ {{ t('github.connect.inUse') }}
145
156
  </UBadge>
146
157
  <UButton
147
158
  v-else
@@ -153,19 +164,19 @@ async function connectManually() {
153
164
  :disabled="connecting"
154
165
  @click="connect(inst.installationId)"
155
166
  >
156
- Connect
167
+ {{ t('github.connect.connect') }}
157
168
  </UButton>
158
169
  </div>
159
170
  </section>
160
171
 
161
- <USeparator label="or" />
172
+ <USeparator :label="t('github.connect.or')" />
162
173
  <UButton color="primary" icon="i-lucide-github" :loading="installing" @click="install">
163
- Install GitHub App
174
+ {{ t('github.connect.installApp') }}
164
175
  </UButton>
165
176
 
166
- <USeparator label="or connect by ID" />
177
+ <USeparator :label="t('github.connect.orConnectById')" />
167
178
  <div class="flex items-end gap-2">
168
- <UFormField label="Installation ID" class="flex-1">
179
+ <UFormField :label="t('github.connect.installationId')" class="flex-1">
169
180
  <UInput v-model="installationId" type="number" placeholder="12345678" class="w-full" />
170
181
  </UFormField>
171
182
  <UButton
@@ -176,7 +187,7 @@ async function connectManually() {
176
187
  :disabled="!installationId.trim()"
177
188
  @click="connectManually"
178
189
  >
179
- Connect
190
+ {{ t('github.connect.connect') }}
180
191
  </UButton>
181
192
  </div>
182
193
  </div>
@@ -9,6 +9,7 @@
9
9
  // user who needs to switch GitHub accounts.
10
10
  import GitHubConnect from '~/components/github/GitHubConnect.vue'
11
11
 
12
+ const { t } = useI18n()
12
13
  const auth = useAuthStore()
13
14
  </script>
14
15
 
@@ -21,11 +22,9 @@ const auth = useAuthStore()
21
22
  >
22
23
  <div class="mb-5 text-center">
23
24
  <UIcon name="i-lucide-github" class="mx-auto mb-3 h-10 w-10 text-indigo-400" />
24
- <h1 class="mb-1 text-lg font-semibold text-white">Connect cat-factory to GitHub</h1>
25
+ <h1 class="mb-1 text-lg font-semibold text-white">{{ t('github.onboarding.title') }}</h1>
25
26
  <p class="text-sm text-slate-400">
26
- cat-factory works by opening pull requests on your repositories. Install the GitHub App on
27
- your account or organization to continue — you can grant it every repository or pick a
28
- subset.
27
+ {{ t('github.onboarding.intro') }}
29
28
  </p>
30
29
  </div>
31
30
 
@@ -35,9 +34,9 @@ const auth = useAuthStore()
35
34
  v-if="auth.required && auth.user"
36
35
  class="mt-6 border-t border-slate-800 pt-4 text-center text-xs text-slate-500"
37
36
  >
38
- Signed in as {{ auth.user.login }} ·
37
+ {{ t('github.onboarding.signedInAs', { login: auth.user.login }) }} ·
39
38
  <button class="text-slate-300 underline-offset-2 hover:underline" @click="auth.logout()">
40
- Sign out
39
+ {{ t('github.onboarding.signOut') }}
41
40
  </button>
42
41
  </p>
43
42
  </div>
@@ -12,6 +12,7 @@ import type { GitHubPullRequest, GitHubRepo } from '~/types/domain'
12
12
  import GitHubConnect from './GitHubConnect.vue'
13
13
  import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
14
14
 
15
+ const { t } = useI18n()
15
16
  const ui = useUiStore()
16
17
  const github = useGitHubStore()
17
18
  const toast = useToast()
@@ -47,29 +48,33 @@ function notifyError(title: string, e: unknown) {
47
48
  async function disconnect() {
48
49
  try {
49
50
  await github.disconnect()
50
- toast.add({ title: 'GitHub disconnected', icon: 'i-lucide-unplug' })
51
+ toast.add({ title: t('github.panel.toast.disconnected'), icon: 'i-lucide-unplug' })
51
52
  } catch (e) {
52
- notifyError('Could not disconnect', e)
53
+ notifyError(t('github.panel.errors.disconnect'), e)
53
54
  }
54
55
  }
55
56
 
56
57
  async function resync(full = false) {
57
58
  try {
58
59
  const { status } = await github.resync({ full })
59
- toast.add({ title: `Resync ${status}`, icon: 'i-lucide-refresh-cw', color: 'info' })
60
+ toast.add({
61
+ title: t('github.panel.toast.resync', { status }),
62
+ icon: 'i-lucide-refresh-cw',
63
+ color: 'info',
64
+ })
60
65
  } catch (e) {
61
- notifyError('Could not resync', e)
66
+ notifyError(t('github.panel.errors.resync'), e)
62
67
  }
63
68
  }
64
69
 
65
70
  // ---- browse ----------------------------------------------------------------
66
71
  type Tab = 'repos' | 'pulls' | 'issues'
67
72
  const tab = ref<Tab>('repos')
68
- const tabs: { id: Tab; label: string; icon: string }[] = [
69
- { id: 'repos', label: 'Repositories', icon: 'i-lucide-folder-git-2' },
70
- { id: 'pulls', label: 'Pull requests', icon: 'i-lucide-git-pull-request' },
71
- { id: 'issues', label: 'Issues', icon: 'i-lucide-circle-dot' },
72
- ]
73
+ const tabs = computed<{ id: Tab; label: string; icon: string }[]>(() => [
74
+ { id: 'repos', label: t('github.panel.tabs.repos'), icon: 'i-lucide-folder-git-2' },
75
+ { id: 'pulls', label: t('github.panel.tabs.pulls'), icon: 'i-lucide-git-pull-request' },
76
+ { id: 'issues', label: t('github.panel.tabs.issues'), icon: 'i-lucide-circle-dot' },
77
+ ])
73
78
 
74
79
  // Manage which repos this board links (the installation is shared across the
75
80
  // account; each board picks its own repos).
@@ -82,7 +87,7 @@ async function openManage() {
82
87
  await github.loadAvailableRepos()
83
88
  selected.value = new Set(github.availableRepos.filter((r) => r.linked).map((r) => r.githubId))
84
89
  } catch (e) {
85
- notifyError('Could not load repositories', e)
90
+ notifyError(t('github.panel.errors.loadRepos'), e)
86
91
  managing.value = false
87
92
  }
88
93
  }
@@ -98,9 +103,13 @@ async function saveRepos() {
98
103
  try {
99
104
  await github.setLinkedRepos([...selected.value])
100
105
  managing.value = false
101
- toast.add({ title: 'Linked repositories updated', icon: 'i-lucide-check', color: 'success' })
106
+ toast.add({
107
+ title: t('github.panel.toast.reposUpdated'),
108
+ icon: 'i-lucide-check',
109
+ color: 'success',
110
+ })
102
111
  } catch (e) {
103
- notifyError('Could not update repositories', e)
112
+ notifyError(t('github.panel.errors.updateRepos'), e)
104
113
  }
105
114
  }
106
115
 
@@ -120,7 +129,7 @@ async function toggleRepo(repo: GitHubRepo) {
120
129
  try {
121
130
  await github.loadBranches(repo.githubId)
122
131
  } catch (e) {
123
- notifyError('Could not load branches', e)
132
+ notifyError(t('github.panel.errors.loadBranches'), e)
124
133
  }
125
134
  }
126
135
  }
@@ -133,9 +142,13 @@ async function createBranch(repo: GitHubRepo) {
133
142
  try {
134
143
  await github.createBranch(repo.githubId, { name, fromSha })
135
144
  branchForm.value = { name: '', fromSha: '' }
136
- toast.add({ title: `Branch ${name} created`, icon: 'i-lucide-check', color: 'success' })
145
+ toast.add({
146
+ title: t('github.panel.toast.branchCreated', { name }),
147
+ icon: 'i-lucide-check',
148
+ color: 'success',
149
+ })
137
150
  } catch (e) {
138
- notifyError('Could not create branch', e)
151
+ notifyError(t('github.panel.errors.createBranch'), e)
139
152
  } finally {
140
153
  creatingBranch.value = false
141
154
  }
@@ -181,22 +194,37 @@ async function openPr() {
181
194
  })
182
195
  showPrForm.value = false
183
196
  prForm.value = { repoGithubId: null, title: '', head: '', base: '' }
184
- toast.add({ title: 'Pull request opened', icon: 'i-lucide-check', color: 'success' })
197
+ toast.add({ title: t('github.panel.toast.prOpened'), icon: 'i-lucide-check', color: 'success' })
185
198
  } catch (e) {
186
- notifyError('Could not open pull request', e)
199
+ notifyError(t('github.panel.errors.openPr'), e)
187
200
  } finally {
188
201
  openingPr.value = false
189
202
  }
190
203
  }
191
204
 
205
+ // PR / issue state labels. The states are a statically-known enum (open/closed,
206
+ // plus the derived `merged` for PRs), so the labels are literal `t()` keys — one
207
+ // per member — which keeps the typed-message-keys drift guard live.
208
+ function prStateLabel(pr: GitHubPullRequest): string {
209
+ if (pr.merged) return t('github.panel.prState.merged')
210
+ return pr.state === 'open' ? t('github.panel.prState.open') : t('github.panel.prState.closed')
211
+ }
212
+ function issueStateLabel(state: GitHubPullRequest['state']): string {
213
+ return state === 'open' ? t('github.panel.issueState.open') : t('github.panel.issueState.closed')
214
+ }
215
+
192
216
  const merging = ref<number | null>(null)
193
217
  async function merge(pr: GitHubPullRequest) {
194
218
  merging.value = pr.number
195
219
  try {
196
220
  await github.mergePullRequest(pr.repoGithubId, pr.number, { method: 'squash' })
197
- toast.add({ title: `PR #${pr.number} merged`, icon: 'i-lucide-git-merge', color: 'success' })
221
+ toast.add({
222
+ title: t('github.panel.toast.prMerged', { number: pr.number }),
223
+ icon: 'i-lucide-git-merge',
224
+ color: 'success',
225
+ })
198
226
  } catch (e) {
199
- notifyError('Could not merge', e)
227
+ notifyError(t('github.panel.errors.merge'), e)
200
228
  } finally {
201
229
  merging.value = null
202
230
  }
@@ -213,8 +241,7 @@ async function merge(pr: GitHubPullRequest) {
213
241
  <!-- not connected: connect -->
214
242
  <template v-if="!github.connected">
215
243
  <p class="text-sm text-slate-400">
216
- Connect a GitHub App installation to back board blocks with repositories, browse pull
217
- requests and issues, and let agents push branches and open PRs.
244
+ {{ t('github.panel.connectIntro') }}
218
245
  </p>
219
246
 
220
247
  <GitHubConnect />
@@ -233,8 +260,12 @@ async function merge(pr: GitHubPullRequest) {
233
260
  {{ github.connection?.accountLogin }}
234
261
  </div>
235
262
  <div class="text-[11px] text-slate-500">
236
- {{ github.connection?.targetType }} · installation
237
- {{ github.connection?.installationId }}
263
+ {{
264
+ t('github.panel.installationMeta', {
265
+ targetType: github.connection?.targetType,
266
+ id: github.connection?.installationId,
267
+ })
268
+ }}
238
269
  </div>
239
270
  </div>
240
271
  </div>
@@ -247,7 +278,7 @@ async function merge(pr: GitHubPullRequest) {
247
278
  :loading="github.syncing"
248
279
  @click="resync(false)"
249
280
  >
250
- Resync
281
+ {{ t('github.panel.resync') }}
251
282
  </UButton>
252
283
  <UButton
253
284
  size="xs"
@@ -257,13 +288,14 @@ async function merge(pr: GitHubPullRequest) {
257
288
  :disabled="github.syncing"
258
289
  @click="resync(true)"
259
290
  >
260
- Backfill
291
+ {{ t('github.panel.backfill') }}
261
292
  </UButton>
262
293
  <UButton
263
294
  size="xs"
264
295
  color="error"
265
296
  variant="ghost"
266
297
  icon="i-lucide-unplug"
298
+ :aria-label="t('github.panel.disconnect')"
267
299
  @click="disconnect"
268
300
  />
269
301
  </div>
@@ -272,20 +304,21 @@ async function merge(pr: GitHubPullRequest) {
272
304
  <!-- tabs -->
273
305
  <div class="flex gap-1">
274
306
  <UButton
275
- v-for="t in tabs"
276
- :key="t.id"
307
+ v-for="tabItem in tabs"
308
+ :key="tabItem.id"
277
309
  size="sm"
278
- :color="tab === t.id ? 'primary' : 'neutral'"
279
- :variant="tab === t.id ? 'soft' : 'ghost'"
280
- :icon="t.icon"
281
- @click="tab = t.id"
310
+ :color="tab === tabItem.id ? 'primary' : 'neutral'"
311
+ :variant="tab === tabItem.id ? 'soft' : 'ghost'"
312
+ :icon="tabItem.icon"
313
+ @click="tab = tabItem.id"
282
314
  >
283
- {{ t.label }}
315
+ {{ tabItem.label }}
284
316
  </UButton>
285
317
  </div>
286
318
 
287
319
  <div v-if="github.loading" class="flex items-center gap-2 py-6 text-sm text-slate-400">
288
- <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" /> Loading…
320
+ <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" />
321
+ {{ t('github.panel.loading') }}
289
322
  </div>
290
323
 
291
324
  <!-- repositories -->
@@ -293,7 +326,7 @@ async function merge(pr: GitHubPullRequest) {
293
326
  <!-- manage which repos this board links -->
294
327
  <div class="flex items-center justify-between">
295
328
  <span class="text-[11px] uppercase tracking-wide text-slate-500">
296
- Linked to this board
329
+ {{ t('github.panel.linkedToBoard') }}
297
330
  </span>
298
331
  <UButton
299
332
  size="xs"
@@ -302,7 +335,7 @@ async function merge(pr: GitHubPullRequest) {
302
335
  icon="i-lucide-list-checks"
303
336
  @click="managing ? (managing = false) : openManage()"
304
337
  >
305
- {{ managing ? 'Close' : 'Manage repos' }}
338
+ {{ managing ? t('common.close') : t('github.panel.manageRepos') }}
306
339
  </UButton>
307
340
  </div>
308
341
 
@@ -311,17 +344,17 @@ async function merge(pr: GitHubPullRequest) {
311
344
  class="space-y-2 rounded-md border border-slate-700 bg-slate-900/80 p-3"
312
345
  >
313
346
  <p class="text-[12px] text-slate-400">
314
- Pick the repositories this board should track. The GitHub connection is shared
315
- across the account; each board links its own repos.
347
+ {{ t('github.panel.manageHint') }}
316
348
  </p>
317
349
  <div
318
350
  v-if="github.loadingAvailable"
319
351
  class="flex items-center gap-2 py-3 text-sm text-slate-400"
320
352
  >
321
- <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" /> Loading repositories…
353
+ <UIcon name="i-lucide-loader" class="h-4 w-4 animate-spin" />
354
+ {{ t('github.panel.loadingRepos') }}
322
355
  </div>
323
356
  <p v-else-if="!github.availableRepos.length" class="py-2 text-sm text-slate-400">
324
- The installation can’t access any repositories yet.
357
+ {{ t('github.panel.noAvailableRepos') }}
325
358
  </p>
326
359
  <div v-else class="max-h-64 space-y-1 overflow-y-auto">
327
360
  <button
@@ -338,13 +371,13 @@ async function merge(pr: GitHubPullRequest) {
338
371
  />
339
372
  <span class="truncate text-sm text-slate-200">{{ r.owner }}/{{ r.name }}</span>
340
373
  <UBadge v-if="r.private" color="neutral" variant="subtle" size="sm">
341
- private
374
+ {{ t('github.panel.private') }}
342
375
  </UBadge>
343
376
  </button>
344
377
  </div>
345
378
  <div class="flex items-center justify-end gap-2 pt-1">
346
379
  <UButton color="neutral" variant="ghost" size="sm" @click="managing = false">
347
- Cancel
380
+ {{ t('common.cancel') }}
348
381
  </UButton>
349
382
  <UButton
350
383
  color="primary"
@@ -353,14 +386,13 @@ async function merge(pr: GitHubPullRequest) {
353
386
  :loading="github.savingRepos"
354
387
  @click="saveRepos"
355
388
  >
356
- Save selection
389
+ {{ t('github.panel.saveSelection') }}
357
390
  </UButton>
358
391
  </div>
359
392
  </div>
360
393
 
361
394
  <p v-if="!github.repos.length && !managing" class="py-4 text-sm text-slate-400">
362
- No repositories linked yet. Use “Manage repos” to pick which repositories this board
363
- tracks.
395
+ {{ t('github.panel.noLinkedRepos') }}
364
396
  </p>
365
397
  <div
366
398
  v-for="repo in github.repos"
@@ -381,7 +413,7 @@ async function merge(pr: GitHubPullRequest) {
381
413
  {{ repo.owner }}/{{ repo.name }}
382
414
  </span>
383
415
  <UBadge v-if="repo.private" color="neutral" variant="subtle" size="sm">
384
- private
416
+ {{ t('github.panel.private') }}
385
417
  </UBadge>
386
418
  </button>
387
419
  <div class="flex items-center gap-2">
@@ -393,7 +425,7 @@ async function merge(pr: GitHubPullRequest) {
393
425
  target="_blank"
394
426
  class="text-[11px] text-indigo-400 hover:underline"
395
427
  >
396
- Open
428
+ {{ t('github.panel.open') }}
397
429
  </ULink>
398
430
  </div>
399
431
  </div>
@@ -411,7 +443,7 @@ async function merge(pr: GitHubPullRequest) {
411
443
  <UIcon name="i-lucide-git-branch" class="h-3.5 w-3.5 text-slate-500" />
412
444
  {{ b.name }}
413
445
  <UBadge v-if="b.protected" color="warning" variant="subtle" size="sm">
414
- protected
446
+ {{ t('github.panel.protected') }}
415
447
  </UBadge>
416
448
  </span>
417
449
  <code class="text-[10px] text-slate-500">{{ b.headSha.slice(0, 7) }}</code>
@@ -419,7 +451,7 @@ async function merge(pr: GitHubPullRequest) {
419
451
 
420
452
  <!-- new branch -->
421
453
  <div class="flex items-end gap-2 pt-1">
422
- <UFormField label="New branch" class="flex-1">
454
+ <UFormField :label="t('github.panel.newBranch')" class="flex-1">
423
455
  <UInput
424
456
  v-model="branchForm.name"
425
457
  placeholder="feature/x"
@@ -427,10 +459,10 @@ async function merge(pr: GitHubPullRequest) {
427
459
  class="w-full"
428
460
  />
429
461
  </UFormField>
430
- <UFormField label="From SHA" class="flex-1">
462
+ <UFormField :label="t('github.panel.fromSha')" class="flex-1">
431
463
  <UInput
432
464
  v-model="branchForm.fromSha"
433
- placeholder="commit sha"
465
+ :placeholder="t('github.panel.commitShaPlaceholder')"
434
466
  size="sm"
435
467
  class="w-full"
436
468
  />
@@ -440,6 +472,7 @@ async function merge(pr: GitHubPullRequest) {
440
472
  color="neutral"
441
473
  variant="subtle"
442
474
  icon="i-lucide-git-branch-plus"
475
+ :aria-label="t('github.panel.createBranch')"
443
476
  :loading="creatingBranch"
444
477
  :disabled="!branchForm.name.trim() || !branchForm.fromSha.trim()"
445
478
  @click="createBranch(repo)"
@@ -459,7 +492,7 @@ async function merge(pr: GitHubPullRequest) {
459
492
  icon="i-lucide-plus"
460
493
  @click="showPrForm = !showPrForm"
461
494
  >
462
- Open PR
495
+ {{ t('github.panel.openPr') }}
463
496
  </UButton>
464
497
  </div>
465
498
 
@@ -467,7 +500,7 @@ async function merge(pr: GitHubPullRequest) {
467
500
  v-if="showPrForm"
468
501
  class="space-y-2 rounded-md border border-slate-700 bg-slate-900/80 p-3"
469
502
  >
470
- <UFormField label="Repository">
503
+ <UFormField :label="t('github.panel.repository')">
471
504
  <UDropdownMenu :items="repoMenu" :content="{ align: 'start' }">
472
505
  <UButton
473
506
  color="neutral"
@@ -476,19 +509,23 @@ async function merge(pr: GitHubPullRequest) {
476
509
  class="w-full justify-between"
477
510
  >
478
511
  <span class="truncate">
479
- {{ prRepo ? `${prRepo.owner}/${prRepo.name}` : 'Choose a repository' }}
512
+ {{
513
+ prRepo
514
+ ? `${prRepo.owner}/${prRepo.name}`
515
+ : t('github.panel.chooseRepository')
516
+ }}
480
517
  </span>
481
518
  </UButton>
482
519
  </UDropdownMenu>
483
520
  </UFormField>
484
- <UFormField label="Title">
521
+ <UFormField :label="t('github.panel.prTitle')">
485
522
  <UInput v-model="prForm.title" class="w-full" />
486
523
  </UFormField>
487
524
  <div class="grid grid-cols-2 gap-2">
488
- <UFormField label="Head branch">
525
+ <UFormField :label="t('github.panel.headBranch')">
489
526
  <UInput v-model="prForm.head" placeholder="feature/x" class="w-full" />
490
527
  </UFormField>
491
- <UFormField label="Base branch">
528
+ <UFormField :label="t('github.panel.baseBranch')">
492
529
  <UInput v-model="prForm.base" placeholder="main" class="w-full" />
493
530
  </UFormField>
494
531
  </div>
@@ -500,13 +537,13 @@ async function merge(pr: GitHubPullRequest) {
500
537
  :disabled="!canOpenPr"
501
538
  @click="openPr"
502
539
  >
503
- Open pull request
540
+ {{ t('github.panel.openPullRequest') }}
504
541
  </UButton>
505
542
  </div>
506
543
  </div>
507
544
 
508
545
  <p v-if="!github.pulls.length" class="py-4 text-sm text-slate-400">
509
- No pull requests synced.
546
+ {{ t('github.panel.noPulls') }}
510
547
  </p>
511
548
  <div
512
549
  v-for="pr in github.pulls"
@@ -527,7 +564,7 @@ async function merge(pr: GitHubPullRequest) {
527
564
  variant="subtle"
528
565
  size="sm"
529
566
  >
530
- {{ pr.merged ? 'merged' : pr.state }}
567
+ {{ prStateLabel(pr) }}
531
568
  </UBadge>
532
569
  <UButton
533
570
  v-if="pr.state === 'open' && !pr.merged"
@@ -535,6 +572,7 @@ async function merge(pr: GitHubPullRequest) {
535
572
  color="neutral"
536
573
  variant="ghost"
537
574
  icon="i-lucide-git-merge"
575
+ :aria-label="t('github.panel.mergePr')"
538
576
  :loading="merging === pr.number"
539
577
  @click="merge(pr)"
540
578
  />
@@ -543,7 +581,7 @@ async function merge(pr: GitHubPullRequest) {
543
581
  target="_blank"
544
582
  class="text-[11px] text-indigo-400 hover:underline"
545
583
  >
546
- Open
584
+ {{ t('github.panel.open') }}
547
585
  </ULink>
548
586
  </div>
549
587
  </div>
@@ -552,7 +590,7 @@ async function merge(pr: GitHubPullRequest) {
552
590
  <!-- issues -->
553
591
  <section v-else class="space-y-2">
554
592
  <p v-if="!github.issues.length" class="py-4 text-sm text-slate-400">
555
- No issues synced.
593
+ {{ t('github.panel.noIssues') }}
556
594
  </p>
557
595
  <div
558
596
  v-for="issue in github.issues"
@@ -574,14 +612,14 @@ async function merge(pr: GitHubPullRequest) {
574
612
  variant="subtle"
575
613
  size="sm"
576
614
  >
577
- {{ issue.state }}
615
+ {{ issueStateLabel(issue.state) }}
578
616
  </UBadge>
579
617
  <ULink
580
618
  :to="github.issueUrl(issue) ?? '#'"
581
619
  target="_blank"
582
620
  class="text-[11px] text-indigo-400 hover:underline"
583
621
  >
584
- Open
622
+ {{ t('github.panel.open') }}
585
623
  </ULink>
586
624
  </div>
587
625
  </div>