Skip to content

Fix homepage localization for chip labels and translations#2275

Open
SunayKulkarni wants to merge 7 commits into
nexu-io:mainfrom
SunayKulkarni:fix-homepage-i18n
Open

Fix homepage localization for chip labels and translations#2275
SunayKulkarni wants to merge 7 commits into
nexu-io:mainfrom
SunayKulkarni:fix-homepage-i18n

Conversation

@SunayKulkarni
Copy link
Copy Markdown

Fixes #2076

Why

This PR addresses incomplete localization on the homepage in 0.8.0-preview.

While using the Chinese language setting, several homepage UI elements were still displayed in English. This was mainly due to hardcoded chip labels and missing or inconsistent translation entries, leading to a mixed-language experience.

Additionally, some direct English-to-Chinese translations resulted in vague or unclear meanings. This PR improves those cases by choosing more context-appropriate translations for better clarity and UX.

What users will see

When switching to Chinese:

  • Homepage category chips (Prototype, Image, Video, etc.) are properly localized
  • "starter" section is now consistently translated as 官方入门
  • Previously untranslated items (e.g. HyperFrames handling) are now consistent
  • Ambiguous translations have been refined to better match intended meaning
  • No mixed English/Chinese UI remains on the homepage

Surface area

  • UI
  • i18n keys
  • Keyboard shortcut
  • CLI / env var
  • API / contract
  • Extension point
  • New top-level dependency
  • Default behavior change
  • None

Screenshots

Bug fix verification

Validation

  • Verified changes locally using pnpm dev
  • Switched language to Chinese and confirmed all homepage elements are localized
  • Ensured no raw i18n keys or English fallbacks remain in homepage UI

@lefarcen lefarcen requested a review from nettee May 19, 2026 14:02
@lefarcen lefarcen added size/S PR changes 20-100 lines risk/medium Medium risk: regular code changes type/bugfix Bug fix labels May 19, 2026
@lefarcen
Copy link
Copy Markdown
Contributor

Hi @SunayKulkarni — thanks for picking up #2076 and for keeping the fix focused on the homepage chip labels. I’ve requested @nettee for the pool review.

Heads-up: PR #2205 is also open in the same zh-CN localization area and touches apps/web/src/components/HomeHero.tsx, apps/web/src/components/home-hero/chips.ts, and apps/web/src/i18n/locales/zh-CN.ts. That one is a broader localization pass, while this PR is the focused homepage fix for #2076; you and @mcncarl may want to compare approaches so the overlapping pieces don’t duplicate effort. The maintainer team will decide how to land or consolidate them.

Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found two issues to address before this lands: the top chip bar still leaks an English tooltip in zh-CN, and the new labelKey path currently bypasses the typed i18n keys.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

Comment thread apps/web/src/components/HomeHero.tsx Outdated
disabled={pluginsLoading || isPending || pendingPluginId !== null}
aria-selected={isActive}
title={chip.hint ?? chip.label}
title={chip.hint ?? t(chip.labelKey as any)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still leaves the HyperFrames tooltip untranslated in zh-CN. chip.hint comes from the hardcoded English string in apps/web/src/components/home-hero/chips.ts, so hovering the top-row HyperFrames tab shows Author HTML-based motion... even though homeHero.chip.hyperframesHint already exists and the lower rail uses it via homeHeroChipTitle(). Since this PR’s goal is to remove mixed-language homepage UI, please route the top tab bar through the same localized title helper (or otherwise translate the hint source) instead of reading chip.hint directly.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

{
id: 'create-plugin',
label: 'Create plugin',
labelKey: 'homeHero.chip.create-plugin',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new labelKey field already contains an invalid key here: the locale dictionaries and apps/web/src/i18n/types.ts define homeHero.chip.createPlugin, not homeHero.chip.create-plugin. Right now that mismatch is hidden because labelKey is typed as plain string and the caller does t(chip.labelKey as any), so the compiler can’t catch bad keys. Please switch this entry to the existing createPlugin key and tighten labelKey to a typed i18n-key union (then drop the as any cast) so future localization regressions fail at compile time.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

@SunayKulkarni
Copy link
Copy Markdown
Author

Good catch, thanks!

  • Fixed the incorrect key (create-plugin → createPlugin)
  • Removed the as any cast so invalid keys are no longer hidden
  • Updated the top tab bar to use homeHeroChipTitle(chip, t) so tooltips are fully localized (including HyperFrames)

Let me know if anything else needs adjustment.

@lefarcen lefarcen requested a review from nettee May 19, 2026 14:41
Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rechecked the follow-up head and the visible zh-CN homepage regressions are fixed. One maintainability issue remains in the new translation-key path.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

export interface HomeHeroChip {
id: string;
label: string;
labelKey: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

labelKey is still widened to plain string, so this follow-up does not actually restore compile-time protection for chip translation keys. useT() only accepts keyof Dict in apps/web/src/i18n/index.tsx, but this metadata shape now allows any arbitrary string, which is how the earlier homeHero.chip.create-plugin typo slipped in unnoticed until runtime. That matters because future chip additions can reintroduce missing-translation regressions even though this PR moved the UI over to labelKey. Please type this field as a real i18n key (for example keyof Dict, or a narrower HomeHeroChipLabelKey union derived from Dict) and import that type here so bad keys fail during development instead of shipping to users.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rechecked the current head and the visible zh-CN homepage regressions look fixed. One maintainability issue remains in the new chip-label metadata path.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

export interface HomeHeroChip {
id: string;
label: string;
labelKey: keyof Dict;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

labelKey is now type-safe here, but the lower rail still does not read it: RailGroup renders homeHeroChipLabel(chip.id, t) in apps/web/src/components/HomeHero.tsx:1587, and homeHeroChipTitle() also switches on chip.id for the migrate chips at apps/web/src/components/HomeHero.tsx:1616-1619. That means the new metadata entries you changed here (create-plugin, figma, folder, template) are not actually the source of truth for the labels/tooltips users see in that rail. This matters because future homepage i18n edits can compile cleanly while silently updating only one of the two paths. Please either drive both rail labels/titles from chip metadata (for example labelKey plus a typed hint/title key) or keep the switch helpers as the single source of truth and drop the unused migrate-chip labelKey fields.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking issue remains in the current head: the chip metadata type now requires labelKey, but the same patch removes that property from every migrate-chip entry, so this change no longer satisfies the declared HomeHeroChip contract.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

export interface HomeHeroChip {
id: string;
label: string;
labelKey: keyof Dict;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HomeHeroChip still requires labelKey here, but this patch removes that property from the create-plugin, figma, folder, and template entries below. That leaves HOME_HERO_CHIPS out of sync with its declared ReadonlyArray<HomeHeroChip> type, so the i18n-safety follow-up now turns into a type/build break instead of a clean refactor. Please either keep labelKey on those migrate chips, or split the model into separate create/migrate chip types so only the create chips are required to carry labelKey.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

@SunayKulkarni
Copy link
Copy Markdown
Author

Restored labelKey on the migrate chips to satisfy the HomeHeroChip type

  • Kept the switch-based helpers as the current source of truth for rendering (since the lower rail still uses them)

I see the concern about multiple sources of truth here. With labelKey restored, the migrate chips now carry the key but still rely on the helpers for labels/tooltips.

For now I’ve kept this approach to avoid breaking the contract and keep the change scoped.

Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rechecked the current head: the chip labels/tooltips now route through the localized helpers, and the zh-CN starter copy is consistent. One follow-up regression-coverage gap remains.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

disabled={pluginsLoading || isPending || pendingPluginId !== null}
aria-selected={isActive}
title={chip.hint ?? chip.label}
title={homeHeroChipTitle(chip, t)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apps/web/src/components/HomeHero.tsx:1534-1536 adds the localized label/title path, but there still is no regression test covering that zh-CN behavior. apps/web/tests/components/HomeHero.rail.test.tsx currently only checks that each chip renders, routes clicks, and toggles state; it never asserts translated text or tooltips, so the earlier labelKey typo and English HyperFrames tooltip both would have passed the suite. Because this PR's goal is to eliminate mixed-language homepage UI, please extend that rail test to render under zh-CN and assert at least one translated create-chip label plus the localized HyperFrames tooltip.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

@lefarcen lefarcen requested a review from nettee May 19, 2026 18:00
Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rechecked the current head: the zh-CN chip labels/tooltips regression and the new locale-specific rail test both look good. One non-blocking maintainability issue remains in the chip metadata path.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

{
id: 'create-plugin',
label: 'Create plugin',
labelKey: 'homeHero.chip.createPlugin',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

labelKey is type-safe now, but the migrate-chip metadata you changed here still is not the source of truth for what the homepage renders. RailGroup still reads homeHeroChipLabel(chip.id, t) in apps/web/src/components/HomeHero.tsx:1587, and homeHeroChipTitle() still switches on chip.id for these same create-plugin / figma / folder / template entries at apps/web/src/components/HomeHero.tsx:1616-1619. That matters because a future homepage i18n edit can update HOME_HERO_CHIPS and assume the UI changed, while the rendered label/tooltip keeps coming from the separate switch tables. Please either derive both label and tooltip from the chip metadata (for example labelKey plus a typed hintKey) or split the chip model so migrate chips do not carry localized fields that the renderer ignores.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

@SunayKulkarni
Copy link
Copy Markdown
Author

I’ve taken the second approach here and split the chip model into create/migrate variants, so migrate chips no longer carry localized fields like labelKey that the renderer doesn’t actually consume.

With this change, the data model now reflects the current rendering path more accurately — create chips derive their labels from metadata, while migrate chips continue to use the existing switch-based helpers (homeHeroChipLabel / homeHeroChipTitle). This avoids the mismatch where updates to HOME_HERO_CHIPS could imply UI changes that wouldn’t actually be reflected.

I’ve kept the switch helpers as the source of truth for migrate chips to keep the scope of this PR focused and avoid touching multiple rendering paths. That said, I agree that moving both label and tooltip fully to metadata (e.g., labelKey + a typed hintKey) would be a cleaner long-term direction, and I’d be happy to follow up with that in a separate PR if preferred.

Copy link
Copy Markdown
Contributor

@nettee nettee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SunayKulkarni I rechecked the current head and reviewed the changed ranges in HomeHero, the chip metadata split, the zh-CN copy update, and the new rail regression test. The localized label/title path now lines up with the current create-vs-migrate rendering split, and the added zh-CN test covers the regression this PR is fixing. Nice cleanup getting this homepage pass into a consistent state.

🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk/medium Medium risk: regular code changes size/S PR changes 20-100 lines type/bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Homepage is not properly localized in Chinese in 0.8.0

3 participants