Fix conflict resolution from c14baf07

Two CI failures from PR #2461 root-caused to wrong picks in the
merge:

* apps/web/src/components/plugins-home/PluginCard.tsx — reverted to
  release-side. The release-side version uses `localizePluginTitle
  (locale, record)` / `localizePluginDescription(locale, record)`
  to read each plugin's `titleI18n` / `descriptionI18n` fields,
  driving the 'localizes plugin card titles' test in
  plugins-home-section.test.tsx (which asserts '瑞士国际主义 Deck'
  appears under zh-CN). The main-side version replaced that
  record-level i18n with hardcoded English + `t()` aria-label
  keys — a finer-grained i18n migration but a fundamental loss of
  the record-level localization the test exercises. Taking
  release-side keeps the test functionality; the aria-label i18n
  keys are micro-optimisation we can re-port in a follow-up.

* e2e/ui/settings-local-cli-codex-fallback.test.ts — added the
  `SETTINGS_MENU_LABEL` constant declaration that the menu-
  dismissal helper (kept from main in c14baf07) references at
  line 161. main's diff added the const at the top of the file but
  it didn't carry through auto-merge alongside the helper block;
  this restores it.

Both fixes verified locally:
- PluginCard now grep-finds locale + localizePluginTitle usage.
- fallback test grep-finds SETTINGS_MENU_LABEL declaration.
This commit is contained in:
lefarcen
2026-05-23 12:28:08 +08:00
parent c14baf07d3
commit f93c886411
2 changed files with 26 additions and 23 deletions
@@ -14,11 +14,12 @@
import { useMemo, useState } from 'react';
import type { InstalledPluginRecord } from '@open-design/contracts';
import type { PluginShareAction } from '../../state/projects';
import { useI18n } from '../../i18n';
import type { PluginShareAction } from '../../state/projects';
import { Icon } from '../Icon';
import { TrustBadge } from '../TrustBadge';
import { PreviewSurface } from './cards/PreviewSurface';
import { localizePluginDescription, localizePluginTitle } from './localization';
import { inferPluginPreview } from './preview';
import type { PluginUseAction } from './useActions';
@@ -54,10 +55,11 @@ export function PluginCard({
onSave,
onShareAction,
}: Props) {
const { t } = useI18n();
const { locale } = useI18n();
const [useMenuOpen, setUseMenuOpen] = useState(false);
const preview = useMemo(() => inferPluginPreview(record), [record]);
const description = record.manifest?.description ?? '';
const title = localizePluginTitle(locale, record);
const description = localizePluginDescription(locale, record);
const tags = useMemo(
() =>
(record.manifest?.tags ?? [])
@@ -94,7 +96,7 @@ export function PluginCard({
>
<PreviewSurface
pluginId={record.id}
pluginTitle={record.title}
pluginTitle={title}
preview={preview}
/>
@@ -108,8 +110,8 @@ export function PluginCard({
) : null}
</div>
<div className="plugins-home__card-overlay-body">
<span className="plugins-home__overlay-title" title={record.title}>
{record.title}
<span className="plugins-home__overlay-title" title={title}>
{title}
</span>
{description ? (
<p className="plugins-home__overlay-desc">{description}</p>
@@ -130,11 +132,11 @@ export function PluginCard({
type="button"
className="plugins-home__action plugins-home__action--secondary"
onClick={() => onOpenDetails(record)}
aria-label={t('pluginCard.detailsAria', { title: record.title })}
aria-label={`View details for ${title}`}
data-testid={`plugins-home-details-${record.id}`}
>
<Icon name="eye" size={12} />
<span>{t('pluginCard.details')}</span>
<span>Details</span>
</button>
<div
className={`plugins-home__use-menu${hasQuery ? ' has-options' : ''}`}
@@ -153,7 +155,7 @@ export function PluginCard({
aria-busy={isPending ? 'true' : undefined}
data-testid={`plugins-home-use-${record.id}`}
>
{isPending ? t('pluginCard.applying') : t('pluginCard.use')}
{isPending ? 'Applying…' : 'Use'}
</button>
{hasQuery ? (
<>
@@ -164,7 +166,7 @@ export function PluginCard({
disabled={useDisabled}
aria-haspopup="menu"
aria-expanded={useMenuOpen}
aria-label={t('pluginCard.chooseUseAria', { title: record.title })}
aria-label={`Choose how to use ${title}`}
data-testid={`plugins-home-use-menu-${record.id}`}
>
<Icon name="chevron-down" size={13} />
@@ -173,7 +175,7 @@ export function PluginCard({
<div
className="plugins-home__use-menu-list"
role="menu"
aria-label={t('pluginCard.useOptionsAria', { title: record.title })}
aria-label={`Use options for ${title}`}
>
<button
type="button"
@@ -183,7 +185,7 @@ export function PluginCard({
onClick={() => pickUseAction('use')}
data-testid={`plugins-home-use-context-${record.id}`}
>
{t('pluginCard.use')}
Use
</button>
<button
type="button"
@@ -193,7 +195,7 @@ export function PluginCard({
onClick={() => pickUseAction('use-with-query')}
data-testid={`plugins-home-use-with-query-${record.id}`}
>
{t('pluginCard.useWithQuery')}
Use with query
</button>
</div>
) : null}
@@ -204,7 +206,7 @@ export function PluginCard({
{onShareAction ? (
<div
className="plugins-home__share-actions"
aria-label={t('pluginCard.shareAria', { title: record.title })}
aria-label={`Share ${title}`}
>
<button
type="button"
@@ -212,15 +214,15 @@ export function PluginCard({
onClick={() => onShareAction(record, 'publish-github')}
disabled={pendingAny || shareBusy}
aria-busy={sharePendingAction === 'publish-github' ? 'true' : undefined}
aria-label={t('pluginCard.publishAria', { title: record.title })}
title={t('pluginCard.publishTitle')}
aria-label={`Publish ${title} as a GitHub repository`}
title="Publish plugin as a GitHub repository"
data-testid={`plugins-home-publish-github-${record.id}`}
>
<Icon
name={sharePendingAction === 'publish-github' ? 'spinner' : 'github'}
size={12}
/>
<span>{sharePendingAction === 'publish-github' ? t('pluginCard.starting') : t('pluginCard.publish')}</span>
<span>{sharePendingAction === 'publish-github' ? 'Starting…' : 'Publish'}</span>
</button>
<button
type="button"
@@ -228,15 +230,15 @@ export function PluginCard({
onClick={() => onShareAction(record, 'contribute-open-design')}
disabled={pendingAny || shareBusy}
aria-busy={sharePendingAction === 'contribute-open-design' ? 'true' : undefined}
aria-label={t('pluginCard.contributeAria', { title: record.title })}
title={t('pluginCard.contributeTitle')}
aria-label={`Contribute ${title} to Open Design`}
title="Contribute plugin to Open Design with a pull request"
data-testid={`plugins-home-contribute-open-design-${record.id}`}
>
<Icon
name={sharePendingAction === 'contribute-open-design' ? 'spinner' : 'share'}
size={12}
/>
<span>{sharePendingAction === 'contribute-open-design' ? t('pluginCard.starting') : t('pluginCard.contribute')}</span>
<span>{sharePendingAction === 'contribute-open-design' ? 'Starting…' : 'Contribute'}</span>
</button>
</div>
) : null}
@@ -254,15 +256,15 @@ export function PluginCard({
.join(' ')}
onClick={() => onSave(record)}
aria-pressed={isSaved}
aria-label={`${isSaved ? 'Saved' : 'Save'} ${record.title}`}
aria-label={`${isSaved ? 'Saved' : 'Save'} ${title}`}
title={isSaved ? 'Saved' : 'Save'}
data-testid={`plugins-home-save-${record.id}`}
>
<Icon name={isSaved ? 'check' : 'star'} size={12} />
<span className="sr-only">{isSaved ? 'Saved' : 'Save'}</span>
</button>
<span className="plugins-home__card-title" title={record.title}>
<span className="plugins-home__card-title-text">{record.title}</span>
<span className="plugins-home__card-title" title={title}>
<span className="plugins-home__card-title-text">{title}</span>
</span>
<TrustBadge trust={record.trust} />
</div>
@@ -4,6 +4,7 @@ import type { Page } from '@playwright/test';
const STORAGE_KEY = 'open-design:config';
const LOCALE_KEY = 'open-design:locale';
const OPEN_SETTINGS_LABEL = /Open settings|打开设置|開啟設定/i;
const SETTINGS_MENU_LABEL = /^Settings$|^设置$|^設定$/i;
const LOCAL_CLI_LABEL = /Local CLI|本机 CLI|本地 CLI/i;
test.describe.configure({ timeout: 30_000 });