Decouple feature copy from locale parity (#8512)

* Decouple feature copy from locale parity

* Fix undeclared dynamic localization key check

* Fix localization code owner
This commit is contained in:
Brennan Benson
2026-07-29 17:44:41 -07:00
committed by GitHub
parent 32926bc831
commit 5e00a30e4e
19 changed files with 819 additions and 150 deletions
@@ -58,6 +58,11 @@ describe('main-i18n lazy locale loading', () => {
expect(translateMain('menu.file', 'File')).not.toBe('File')
})
it('uses caller English when a target catalog omits a key', async () => {
await setMainUiLanguage(UI_LANGUAGE_SPANISH)
expect(translateMain('missing.main.feature', 'English fallback')).toBe('English fallback')
})
it('returns to English from a lazily-loaded locale', async () => {
await setMainUiLanguage(UI_LANGUAGE_SPANISH)
expect(translateMain('menu.file', 'File')).toBe('Archivo')
@@ -129,11 +129,12 @@ export function NativeChatToolRun({
const callCount = countToolCalls(blocks) || blocks.length
const summary = summarizeToolRun(blocks)
const fallbackLabel = translate(
callCount === 1 ? 'components.native-chat.tool.countOne' : 'components.native-chat.tool.countN',
callCount === 1 ? '1 tool call' : `${callCount} tool calls`,
{ count: callCount }
)
const fallbackLabel =
callCount === 1
? translate('components.native-chat.tool.countOne', '1 tool call')
: translate('components.native-chat.tool.countN', '{{value0}} tool calls', {
value0: callCount
})
return (
// Extra top margin sets the tool run apart from the assistant prose above it
@@ -181,7 +181,7 @@ export function useHostedReviewActions({
toast.success(
isClosing
? translate(
'auto.components.right.sidebar.HostedReviewActions.fa3ee9a515',
'auto.components.right.sidebar.HostedReviewActions.closedToast',
'{{value0}} closed',
{ value0: shortLabel }
)
@@ -38,7 +38,7 @@ export const getShortcutsPaneSearchEntries = createLocalizedCatalog(() => [
...KEYBINDING_DEFINITIONS.map((item) => ({
title: item.title,
description: translate(
'auto.components.settings.shortcuts.search.ca6a0c2df7',
'auto.components.settings.shortcuts.search.groupShortcut',
'{{value0}} shortcut',
{ value0: item.group }
),
@@ -137,12 +137,17 @@ export function CloneStep({
value={cloneDestination}
onChange={(e) => onDestChange(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={translate(
placeholder={
isRemoteClone
? 'auto.components.sidebar.AddRepoSteps.remoteCloneParentPlaceholder'
: 'auto.components.sidebar.AddRepoSteps.2ce3f6edf8',
isRemoteClone ? '/home/user/projects' : '/path/to/destination'
)}
? translate(
'auto.components.sidebar.AddRepoSteps.remoteCloneParentPlaceholder',
'/home/user/projects'
)
: translate(
'auto.components.sidebar.AddRepoSteps.2ce3f6edf8',
'/path/to/destination'
)
}
className="h-8 text-xs flex-1"
disabled={isCloning}
/>
@@ -26,12 +26,10 @@ export function UsageBreakdownSection({
rows,
eventsOrTurns
}: UsageBreakdownSectionProps): React.JSX.Element {
const eventsOrTurnsKey =
const eventsOrTurnsLabel =
eventsOrTurns === 'turns'
? 'auto.components.stats.UsageBreakdownSection.32176e1d44'
: 'auto.components.stats.UsageBreakdownSection.79a69522a5'
const eventsOrTurnsLabel = eventsOrTurns === 'turns' ? 'turns' : 'events'
const sessionsKey = 'auto.components.stats.UsageBreakdownSection.02a046792e'
? translate('auto.components.stats.UsageBreakdownSection.32176e1d44', 'turns')
: translate('auto.components.stats.UsageBreakdownSection.79a69522a5', 'events')
return (
<section className="rounded-lg border border-border/60 bg-card/40 p-4">
@@ -50,8 +48,9 @@ export function UsageBreakdownSection({
<span className="shrink-0 text-muted-foreground">{formatTokens(row.tokens)}</span>
</div>
<div className="text-xs text-muted-foreground">
{row.sessions} {translate(sessionsKey, 'sessions •')} {row.eventsOrTurns}{' '}
{translate(eventsOrTurnsKey, eventsOrTurnsLabel)}
{row.sessions}{' '}
{translate('auto.components.stats.UsageBreakdownSection.02a046792e', 'sessions •')}{' '}
{row.eventsOrTurns} {eventsOrTurnsLabel}
{row.hasInferredPricing
? ` ${translate('auto.components.stats.UsageBreakdownSection.247c93ca92', '• inferred pricing')}`
: ''}
@@ -37,6 +37,13 @@ describe('renderer i18n lazy locale loading', () => {
expect(i18n.t('menu.file', { defaultValue: 'File' })).not.toBe('File')
})
it('uses the inline English default when a target catalog omits a key', async () => {
await setRendererUiLanguage(UI_LANGUAGE_SPANISH)
expect(i18n.t('missing.renderer.feature', { defaultValue: 'English fallback' })).toBe(
'English fallback'
)
})
it('returns to English from a lazily-loaded locale', async () => {
await setRendererUiLanguage(UI_LANGUAGE_SPANISH)
expect(i18n.t('menu.file', { defaultValue: 'File' })).toBe('Archivo')
+11 -3
View File
@@ -3714,7 +3714,10 @@
},
"UsageBreakdownSection": {
"7765a4c3e1": "n/a",
"247c93ca92": "• inferred pricing"
"247c93ca92": "• inferred pricing",
"32176e1d44": "turns",
"79a69522a5": "events",
"02a046792e": "sessions •"
},
"UsageSessionsTable": {
"1afc25eb06": "Turns",
@@ -4042,7 +4045,8 @@
"32a7256d85": "Clone",
"69f5b5380d": "Cloning...",
"cloneOnHostDescription": "Enter the Git URL and choose where to clone it on {{value0}}.",
"cloneParentFolder": "Parent folder"
"cloneParentFolder": "Parent folder",
"remoteCloneParentPlaceholder": "/home/user/projects"
},
"AutoRenameFailedDialog": {
"aed1623b1e": "Close",
@@ -8650,6 +8654,7 @@
"shortcuts": {
"search": {
"ca6a0c2df7": "shortcut",
"groupShortcut": "{{value0}} shortcut",
"4811a8264a": "terminal first",
"afda131738": "orca first",
"0ecfc47434": "conflict",
@@ -10001,6 +10006,7 @@
"2bfaf4379c": "More {{value0}} actions",
"377269db6f": "{{value0}} reopened",
"fa3ee9a515": "closed",
"closedToast": "{{value0}} closed",
"78f5ff294c": "This will reopen the {{value0}}.",
"a3d572a4de": "This will close the {{value0}}.",
"e4aca40024": "Delete Workspace",
@@ -14165,7 +14171,9 @@
},
"tool": {
"running": "Running…",
"result": "Result"
"result": "Result",
"countOne": "1 tool call",
"countN": "{{value0}} tool calls"
},
"status": {
"responding": "Agent is responding"