mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
fix(i18n): localize Commit & Sync, Rebase, and Create PR hints in the source control dropdown (#14127)
The Commit & Sync tooltip, the Rebase label/tooltip, and the Create PR blocked hints were bare English literals while the labels beside them went through translate(). Route all 25 strings through translate() with named placeholders and add the keys to the English catalog. Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
This commit is contained in:
@@ -73,28 +73,52 @@ export function buildCommitDropdownItems(ctx: DropdownActionContext): CommitDrop
|
||||
|
||||
const commitSyncTitle = ((): string => {
|
||||
if (upstreamLoading) {
|
||||
return 'Checking branch status…'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.checkingBranchStatus',
|
||||
'Checking branch status…'
|
||||
)
|
||||
}
|
||||
if (publishBlockedByPRLoading) {
|
||||
return 'Checking PR status…'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titleCheckingPrStatus',
|
||||
'Checking PR status…'
|
||||
)
|
||||
}
|
||||
if (publishBlockedByMergedPR) {
|
||||
return 'PR is already merged'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titlePrAlreadyMerged',
|
||||
'PR is already merged'
|
||||
)
|
||||
}
|
||||
if (publishBlockedByDetachedHead) {
|
||||
return 'Check out a branch before syncing commits'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titleCheckOutBranchToSync',
|
||||
'Check out a branch before syncing commits'
|
||||
)
|
||||
}
|
||||
if (!hasUpstream) {
|
||||
// Point to the existing Publish Branch primary instead of naming a nonexistent compound action.
|
||||
return 'Publish the branch first to sync commits'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titlePublishBranchFirst',
|
||||
'Publish the branch first to sync commits'
|
||||
)
|
||||
}
|
||||
if (shouldForcePushWithLease) {
|
||||
return (
|
||||
commitDisabledReason ??
|
||||
'Use Commit & Force Push — remote only has older copies of local commits'
|
||||
translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titleUseForcePush',
|
||||
'Use Commit & Force Push — remote only has older copies of local commits'
|
||||
)
|
||||
)
|
||||
}
|
||||
return commitDisabledReason ?? 'Commit, then pull and push'
|
||||
return (
|
||||
commitDisabledReason ??
|
||||
translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.titleCommitThenPullPush',
|
||||
'Commit, then pull and push'
|
||||
)
|
||||
)
|
||||
})()
|
||||
const commitSync: DropdownItem = {
|
||||
kind: 'commit_sync',
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { i18n } from '@/i18n/i18n'
|
||||
import { PSEUDO_LOCALIZATION_LOCALE } from '@/i18n/pseudo-localization'
|
||||
import { resolveDropdownItems } from './source-control-dropdown-items'
|
||||
import type { DropdownActionInputs, DropdownItem } from './source-control-dropdown-item-types'
|
||||
import {
|
||||
@@ -645,6 +647,37 @@ describe('resolveDropdownItems', () => {
|
||||
'Try a fast-forward pull; git may reject local commits'
|
||||
)
|
||||
})
|
||||
|
||||
it('routes Commit & Sync, Rebase, and Create PR blocked copy through the active locale', async () => {
|
||||
await i18n.changeLanguage(PSEUDO_LOCALIZATION_LOCALE)
|
||||
try {
|
||||
const loading = resolveDropdownItems(inputs({ rebaseBaseRef: 'origin/main' }))
|
||||
const blocked = resolveDropdownItems(
|
||||
inputs({
|
||||
upstreamStatus: { hasUpstream: true, ahead: 0, behind: 0 },
|
||||
hostedReviewCreation: {
|
||||
provider: 'github',
|
||||
review: null,
|
||||
canCreate: false,
|
||||
blockedReason: 'dirty',
|
||||
nextAction: 'commit',
|
||||
reviewLookupOutcome: 'not_found'
|
||||
}
|
||||
})
|
||||
)
|
||||
const loadingByKind = Object.fromEntries(
|
||||
loading.filter((e) => e.kind !== 'separator').map((e) => [e.kind, e])
|
||||
)
|
||||
const blockedByKind = Object.fromEntries(
|
||||
blocked.filter((e) => e.kind !== 'separator').map((e) => [e.kind, e])
|
||||
)
|
||||
expect(loadingByKind.commit_sync.title).toBe('[Checking branch status…]')
|
||||
expect(loadingByKind.rebase_base.label).toBe('[Rebase from origin/main]')
|
||||
expect(blockedByKind.create_pr.hint).toBe('[Commit changes first]')
|
||||
} finally {
|
||||
await i18n.changeLanguage('en')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Exercise the real push-target resolution chain used by the component (#8196).
|
||||
|
||||
@@ -165,15 +165,34 @@ export function buildRemoteDropdownItems(ctx: DropdownActionContext): RemoteDrop
|
||||
const hasRemoteBaseRef = rebaseBaseLabel?.includes('/') === true
|
||||
const rebase: DropdownItem = {
|
||||
kind: 'rebase_base',
|
||||
label: rebaseBaseLabel ? `Rebase from ${rebaseBaseLabel}` : 'Rebase from Base',
|
||||
label: rebaseBaseLabel
|
||||
? translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.rebaseFromNamedBase',
|
||||
'Rebase from {{baseRef}}',
|
||||
{ baseRef: rebaseBaseLabel }
|
||||
)
|
||||
: translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.rebaseFromBase',
|
||||
'Rebase from Base'
|
||||
),
|
||||
title: ((): string => {
|
||||
if (!rebaseBaseLabel || !hasRemoteBaseRef) {
|
||||
return 'Choose a remote base branch to rebase from'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.rebaseChooseRemoteBase',
|
||||
'Choose a remote base branch to rebase from'
|
||||
)
|
||||
}
|
||||
if (hasDirtyLocalChanges) {
|
||||
return 'Try rebasing; git may require committing or stashing local changes first'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.rebaseDirtyHint',
|
||||
'Try rebasing; git may require committing or stashing local changes first'
|
||||
)
|
||||
}
|
||||
return `Rebase current branch with latest commits from ${rebaseBaseLabel}`
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.rebaseWithLatestFrom',
|
||||
'Rebase current branch with latest commits from {{baseRef}}',
|
||||
{ baseRef: rebaseBaseLabel }
|
||||
)
|
||||
})(),
|
||||
disabled: globalBusy || !rebaseBaseRef || !hasRemoteBaseRef
|
||||
}
|
||||
|
||||
@@ -39,30 +39,78 @@ export function buildHostedReviewDropdownItems(
|
||||
const createBlockedHint = ((): string => {
|
||||
switch (hostedReviewCreation?.blockedReason) {
|
||||
case 'dirty':
|
||||
return 'Commit changes first'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedCommitFirst',
|
||||
'Commit changes first'
|
||||
)
|
||||
case 'detached_head':
|
||||
return 'Check out a branch first'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedCheckOutBranchFirst',
|
||||
'Check out a branch first'
|
||||
)
|
||||
case 'default_branch':
|
||||
return 'Switch to a feature branch'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedSwitchToFeatureBranch',
|
||||
'Switch to a feature branch'
|
||||
)
|
||||
case 'no_upstream':
|
||||
return 'Publish Branch'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedPublishBranch',
|
||||
'Publish Branch'
|
||||
)
|
||||
case 'needs_push':
|
||||
return 'Push first'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedPushFirst',
|
||||
'Push first'
|
||||
)
|
||||
case 'needs_sync':
|
||||
return shouldForcePushWithLease ? 'Force Push first' : 'Sync first'
|
||||
return shouldForcePushWithLease
|
||||
? translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedForcePushFirst',
|
||||
'Force Push first'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedSyncFirst',
|
||||
'Sync first'
|
||||
)
|
||||
case 'auth_required':
|
||||
return `${createReviewCopy.authInstruction} in this environment`
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedAuthRequired',
|
||||
'{{authInstruction}} in this environment',
|
||||
{ authInstruction: createReviewCopy.authInstruction }
|
||||
)
|
||||
case 'unsupported_provider':
|
||||
return 'Unsupported provider'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedUnsupportedProvider',
|
||||
'Unsupported provider'
|
||||
)
|
||||
case 'existing_review':
|
||||
return `A ${createReviewCopy.reviewLabel} already exists`
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedExistingReview',
|
||||
'A {{reviewLabel}} already exists',
|
||||
{ reviewLabel: createReviewCopy.reviewLabel }
|
||||
)
|
||||
case 'fork_head_unsupported':
|
||||
return 'Fork head unsupported'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedForkHeadUnsupported',
|
||||
'Fork head unsupported'
|
||||
)
|
||||
case 'base_not_on_remote':
|
||||
return 'Base branch is not on the remote'
|
||||
return translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedBaseNotOnRemote',
|
||||
'Base branch is not on the remote'
|
||||
)
|
||||
case null:
|
||||
case undefined:
|
||||
return upstreamLoading ? 'Checking branch status…' : 'Branch is not ready'
|
||||
return upstreamLoading
|
||||
? translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.checkingBranchStatus',
|
||||
'Checking branch status…'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.right.sidebar.source.control.dropdown.items.blockedBranchNotReady',
|
||||
'Branch is not ready'
|
||||
)
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
@@ -14505,7 +14505,32 @@
|
||||
"226b85a3a7": "Fetch",
|
||||
"323bb614aa": "Commit & Sync",
|
||||
"2b8e6595fd": "Commit",
|
||||
"04d709801d": "Fetch from remote without merging"
|
||||
"04d709801d": "Fetch from remote without merging",
|
||||
"checkingBranchStatus": "Checking branch status…",
|
||||
"titleCheckingPrStatus": "Checking PR status…",
|
||||
"titlePrAlreadyMerged": "PR is already merged",
|
||||
"titleCheckOutBranchToSync": "Check out a branch before syncing commits",
|
||||
"titlePublishBranchFirst": "Publish the branch first to sync commits",
|
||||
"titleUseForcePush": "Use Commit & Force Push — remote only has older copies of local commits",
|
||||
"titleCommitThenPullPush": "Commit, then pull and push",
|
||||
"rebaseFromNamedBase": "Rebase from {{baseRef}}",
|
||||
"rebaseFromBase": "Rebase from Base",
|
||||
"rebaseChooseRemoteBase": "Choose a remote base branch to rebase from",
|
||||
"rebaseDirtyHint": "Try rebasing; git may require committing or stashing local changes first",
|
||||
"rebaseWithLatestFrom": "Rebase current branch with latest commits from {{baseRef}}",
|
||||
"blockedCommitFirst": "Commit changes first",
|
||||
"blockedCheckOutBranchFirst": "Check out a branch first",
|
||||
"blockedSwitchToFeatureBranch": "Switch to a feature branch",
|
||||
"blockedPublishBranch": "Publish Branch",
|
||||
"blockedPushFirst": "Push first",
|
||||
"blockedForcePushFirst": "Force Push first",
|
||||
"blockedSyncFirst": "Sync first",
|
||||
"blockedAuthRequired": "{{authInstruction}} in this environment",
|
||||
"blockedUnsupportedProvider": "Unsupported provider",
|
||||
"blockedExistingReview": "A {{reviewLabel}} already exists",
|
||||
"blockedForkHeadUnsupported": "Fork head unsupported",
|
||||
"blockedBaseNotOnRemote": "Base branch is not on the remote",
|
||||
"blockedBranchNotReady": "Branch is not ready"
|
||||
}
|
||||
},
|
||||
"primary": {
|
||||
|
||||
Reference in New Issue
Block a user