Skip to content

i18n hardening follow-up from PR #1993 review findingsΒ #1997

@plitzenberger

Description

@plitzenberger

Parent epic

Parent epic: #1996

Source

Outside diff range comments (8)


1) 🟠 Major β€” Don't repoint the existing network link in this translation change

File: packages/ui/src/organisms/footer.tsx around lines 51–57

This swaps the first NETWORK link over to https://hypha.services/, which looks like a user-visible footer behavior change rather than a pure localization update. If the intent is only to translate labels, keep the original destination here and add Hypha Services as a separate entry instead of replacing the current one.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/organisms/footer.tsx` around lines 51 - 57, The change
replaced the existing NETWORK link's href with "https://hypha.services/" causing
a visible behavior change; revert the href on the existing Link that renders the
NETWORK entry (the Link element that uses customLinkStyles and
hyphaServicesLabel) back to its original destination and instead add a separate
Link entry for Hypha Services (using hyphaServicesLabel or a new label constant)
so translation only updates labels and does not repoint the original NETWORK
link.

2) 🟠 Major β€” Add an accessible name for the mobile icon-only button

File: packages/epics/src/people/components/export-embedded-wallet-button.tsx around lines 17–27

On Line 27 the text is hidden below md, so this becomes icon-only on small screens. Right now the button has no accessible name in this component. Please wire label into aria-label on the <Button>.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/epics/src/people/components/export-embedded-wallet-button.tsx`
around lines 17 - 27, The mobile icon-only button in the
ExportEmbeddedWalletButton component lacks an accessible name; update the Button
element (used in ExportEmbeddedWalletButton, which currently uses
onExportEmbeededWallet and the label prop) to include an aria-label set to the
label prop (e.g., aria-label={label}) so the icon-only state on small screens is
announced to assistive tech.

3) 🟑 Minor β€” Missing lang in useEffect dependency array

File: apps/web/src/app/[lang]/profile/page.tsx around lines 35–39

The lang variable from useParams() is used inside the effect but not listed in the dependency array. While lang is unlikely to change during a session, including it ensures correctness and avoids React warnings.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/profile/page.tsx around lines 35 - 39, The useEffect
uses the lang variable from useParams() but does not include it in the
dependency array; update the dependency list for the useEffect that performs
router.replace(`/${lang}/profile/${person?.slug}`) to include lang along with
router, person, and isLoading so React re-runs the effect when lang changes and
avoids missing-dependency warnings.

4) 🟑 Minor β€” Untranslated string: "Created on" should use translation key

File: apps/web/src/app/[lang]/dho/[id]/layout.tsx around lines 161–165

The "Created on" text remains hardcoded while other UI strings in this file are translated. The Common.createdOn key with a {date} placeholder already exists in the translation files.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/dho/[id]/layout.tsx around lines 161 - 165, Replace
the hardcoded "Created on" text with the translation key Common.createdOn and
pass the formatted date as the {date} variable; specifically, use the translator
(e.g., t or useTranslations) to render t('Common.createdOn', { date:
formatDate(spaceFromDb.createdAt, true) }) in place of the literal string so
that formatDate(spaceFromDb.createdAt, true) is injected into the translation.

5) 🟠 Major β€” Category names are still locale-static

File: packages/epics/src/spaces/components/explore-spaces.tsx around lines 63–70 (also 172–180, 295)

allLabel is translated now, but the actual category names still come from categoryOptions.label. Because those labels are pulled from the shared core constant instead of next-intl, the chips and selected-category label will stay English on German/French pages.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/epics/src/spaces/components/explore-spaces.tsx` around lines 63 -
70, The UI still uses locale-static labels from categoryOptions, so category
names (in ExploreSpaces component) remain English; replace usages of
categoryOptions.find(...).label with localized labels using the next-intl
translator (e.g., useTranslations) β€” either compute a localizedLabel via
t(`categories.${category}`) or build a localizedCategoryOptions array where each
option's label is set to t(...) and then use that for rendering in the category
chips, the selected-category label, and the other places flagged (the
occurrences around the chips and the selected label). Ensure all references to
categoryOptions.label are swapped to the localizedLabel or the localized options
so the UI reflects the current locale.

6) 🟑 Minor β€” Translate the avatar alt text too

File: apps/web/src/app/[lang]/dho/[id]/_components/visible-spaces-list.tsx around lines 164–167 (also 230–233)

logo is still hardcoded in English here, so German screen-reader output remains partially untranslated in this panel.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/dho/[id]/_components/visible-spaces-list.tsx around
lines 164 - 167, The avatar alt text currently uses a hardcoded English word
"logo"; update the alt generation so it uses the app's i18n translation function
(e.g., t or translate) to produce a localized label and interpolate
rootSpace.name (used in AvatarImage's alt prop and the other occurrence
currently using rootSpace.name || DEFAULT_SPACE_AVATAR_IMAGE). Replace the
string template `${rootSpace.name} logo` with a translated string like
t('space.logoAlt', { name: rootSpace.name }) (or the project's equivalent
translation helper) in both AvatarImage usages so screen readers receive
localized text.

7) πŸ”΄ Critical β€” Avoid returning before useSpaceDiscoverability and useUserSpaceState

File: apps/web/src/app/[lang]/dho/[id]/_components/visible-spaces-list.tsx around lines 39–69

Lines 45–59 can exit before the hooks on lines 61–69. If web3SpaceId transitions from undefined to defined across renders, this violates React's Rules of Hooks by changing the hook call count. Extract conditional logic into separate components to ensure hooks are always called in the same order.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/dho/[id]/_components/visible-spaces-list.tsx around
lines 39 - 69, The early return in AddSpaceButton happens before calling
useSpaceDiscoverability and useUserSpaceState, which can change hook call order
across renders; fix by extracting the hook-dependent logic into a child
component (e.g., AddSpaceButtonWithHooks) that receives web3SpaceId, spaceSlug
and fullSpace as props, keep AddSpaceButton only to compute
fullSpace/web3SpaceId/spaceSlug and choose between rendering a disabled UI or
<AddSpaceButtonWithHooks .../>; implement the hooks (useSpaceDiscoverability,
useUserSpaceState) only inside that new child component so hook calls remain
stable across renders.

8) 🟠 Major β€” Add rel="noopener noreferrer" to external link with target="_blank"

File: apps/web/src/app/[lang]/profile/[personSlug]/@aside/actions/activate-spaces/page.tsx around lines 60–65

On line 64, this Link opens an external URL in a new tab without the rel attribute. This is inconsistent with all other external links in the codebase (e.g., packages/ui/src/organisms/footer.tsx, packages/ui/src/text-with-links.tsx) which include rel="noopener noreferrer" for security and tab isolation.

Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/web/src/app/`[lang]/profile/[personSlug]/@aside/actions/activate-spaces/page.tsx
around lines 60 - 65, The external Link in the activate-spaces page that sets
href and target="_blank" must include rel="noopener noreferrer" for security;
update the Link (the JSX element in page.tsx that currently has
href={process.env.NEXT_PUBLIC_HYPHA_TOKENOMICS_DOCS_URL ??
'https://assets.hypha.earth/files/Tokenomics_Paper.pdf'} and target="_blank") to
also pass rel="noopener noreferrer" so it matches other external links and
prevents tab-napping.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions