Skip to content

🎃 Set up i18n in the frontend and translate the sidebar and sign-in form (DE, IT) #1008

Closed

Description

@helpcodeai

Part of the October Challenge #997.

Why

The website guides and the README already exist in German and Italian (content/guides/de, content/guides/it, README.de.md), but the admin UI is English only. Every string is hard-coded in JSX, <html lang="en"> is fixed (app/layout.tsx:72), and there is no i18n library. The only translated UI is the cookie banner (components/cookie-consent.tsx:37-391, browser language detection at :424-426), which only renders when GTM is configured. Teams whose staff work in German or Italian have to put up with an English admin UI, and adding a language later gets harder with every new page.

This issue lays the foundation and proves it on two surfaces: the sidebar and the sign-in form. Other pages follow in separate issues, one area at a time.

Self-hosted vs Cloud

  • Self-hosted: same in Community and Business. Frontend only: no backend or database change, no ee/ code.
  • Cloud (DEPLOYMENT_MODE=cloud): same image, same behaviour. The language is a per-browser preference stored in a cookie, not a workspace or instance setting, so members of one workspace can use different languages.
  • Who can use it: everyone, including signed-out visitors on /login.

What to build

  1. Library: next-intl in its "without i18n routing" setup. Reasons: it supports the App Router with server and client components, ICU messages (plurals such as "1 tool" / "3 tools") and typed message keys. Without routing there are no /de/... URL prefixes, so the auth gate in proxy.ts, the backend rewrites in next.config.ts and every ?redirect= link keep working unchanged. Almost every page is a client component, so the messages are passed once through NextIntlClientProvider in the root layout. Before you start, check that the current next-intl release supports the next version in packages/frontend/package.json (16.x) and name the version in the PR. This Next.js version has breaking changes (see packages/frontend/AGENTS.md), so read the docs it ships in node_modules/next/dist/docs/ as well. If next-intl does not fit, comment here before building an alternative.
  2. Locale resolution (server side): the cookie amcp_locale if it holds a supported locale, otherwise the best match from Accept-Language, otherwise en. Supported: en, de, it. Set <html lang> from it in app/layout.tsx:72. The root layout is already force-dynamic (:58), so reading the cookie per request costs nothing extra. app/global-error.tsx:30 can stay en.
  3. Messages: packages/frontend/messages/{en,de,it}.json, nested by area (nav.*, signIn.*). English is the source. A key missing in de or it falls back to English and never shows a raw key.
  4. Sidebar (components/app-sidebar.tsx): the group titles and item labels in NAV (:45-73), "Switch workspace" (:156), "Log out" (:188), "Settings" (:205), the "Workspace" fallback (:216) and the "Star on GitHub" texts (components/github-star-button.tsx:54-60). hrefs and the active-item logic stay as they are.
  5. Sign-in form (app/login/page.tsx:851-1144, sign-in mode only, !isRegister): heading, labels, placeholders, the submit button states, "Forgot password?", the recovery-code texts, the "or" divider, "Don't have an account? Register", "Email verified successfully!…", "Signing you in…", and the client-side messages shown in this mode. The registration and Cloud sign-up variants and the verification and licence steps stay English in this issue.
  6. Language switcher: a select (English, Deutsch, Italiano) in Settings → Profile (app/settings/page.tsx) and a small one under the sign-in card. It writes the cookie (one year, SameSite=Lax, Path=/) and calls router.refresh().
  7. Translations: match the tone of the existing German and Italian guides in content/guides/de and content/guides/it. If you are not a native speaker of one of the languages, say so in the PR so a maintainer can review those strings.
  8. Contributor note: a short "Translating the UI" section in .github/CONTRIBUTING.md: where the messages live, how to add a key, English is the source.

Where to look

  • packages/frontend/src/app/layout.tsx:51-89: root layout (force-dynamic, <html lang>).
  • packages/frontend/src/app/providers.tsx: client providers to wrap.
  • packages/frontend/src/proxy.ts: auth gate and public paths; must keep working unchanged.
  • packages/frontend/src/components/app-sidebar.tsx:45-73, :156, :188, :205, :216.
  • packages/frontend/src/app/login/page.tsx:851-1144: the auth form.
  • packages/frontend/src/components/cookie-consent.tsx:37-391, :424-426: the banner's own translations (leave them as they are).
  • packages/frontend/src/lib/translation-safe-dom.ts: keeps browser page translation from crashing React; keep it.
  • packages/frontend/tests/e2e/: many tests match English text, so English must stay the result for Accept-Language: en-US, Playwright's default.

Acceptance criteria

  • Without the cookie, Accept-Language: de-DE renders /login and the sidebar in German with <html lang="de">; it-IT gives Italian; fr-FR gives English.
  • A language chosen in Settings persists across reloads and sign-out.
  • Playwright tests for the cases above (test.use({ locale: 'de-DE' })), plus a key-parity test that loads the three JSON files and fails when de or it misses or adds a key. All existing tests pass unchanged (cd packages/frontend && npm run test:e2e).
  • URLs are unchanged: login-redirect-query.spec.ts and login-redirect-safe.spec.ts pass.
  • npm run lint, npx tsc --noEmit -p tsconfig.json and npm run build pass in packages/frontend.
  • Screenshots of the sidebar and the sign-in form in German and Italian in the PR.

Out of scope

  • Other pages (follow-up issues), the backend-rendered OAuth sign-in and consent pages (packages/backend/src/auth/auth-page.ts), emails and API error messages.
  • Locale-prefixed URLs, right-to-left languages, languages other than German and Italian.
  • Storing the language on the user account.
  • Changing date or number formatting.

Size

L (several days, may be split: library, locale resolution and sidebar first; sign-in form and switcher second).

How to claim

Comment "I'd like to work on this" and we'll assign you. Rules in #997.

Activity

  1. sapatmohit commented on Oct 24, 2026

    @sapatmohit
    Contributor

    I'd like to work on this

  2. helpcodeai commented on Oct 24, 2026

    @helpcodeai
    ContributorAuthor

    @sapatmohit it's yours, thanks! GitHub only lets us formally assign repository members, so this comment is the assignment.

    This one is sized L, so please split it as the issue suggests, and open the first PR within the 7 days from #997:

    1. First PR: next-intl without i18n routing, locale resolution (cookie amcp_locale, then Accept-Language, then en), <html lang>, the three message files with the key-parity test, and the sidebar.
    2. Second PR: the sign-in form and the two language switchers.

    Before writing code, check that the current next-intl release supports our Next.js 16 and name the version in the PR. If it doesn't fit, comment here first. Many Playwright tests match English text, so Accept-Language: en-US must keep rendering exactly what it renders today.

    If German or Italian isn't your native language, just say so in the PR and we'll review those strings.

  3. sapatmohit commented on Oct 25, 2026

    @sapatmohit
    Contributor

    Thanks for the quick reviews on #1248 and #1257! Now that the foundation is in, only nav, signIn and language are translated, so most of the UI is still English-only in DE and IT.

    I'd like to keep going and translate the rest, in the same small-PR style. A rough split, smallest and most-seen first:

    1. Auth and onboarding: rest of /login, /forgot-password, /reset-password, /verify-email, /accept-invite, /welcome, /start-trial
    2. Logs and analytics: /logs, /analytics
    3. MCP servers: /mcp-server, /mcp-server/[id]
    4. Connectors (list, store, setup): /connectors, /connectors/store, /connectors/setup/[slug], /connectors/new
    5. Connector detail: /connectors/[id]
    6. Settings and admin: /settings/*, /admin/* (likely split in two, it's the biggest area)
    7. Knowledge graph and memory: /knowledge-graph, /knowledge-graph/skills, /memory

    Each PR adds one namespace per area to en.json, de.json and it.json, keeps the key-parity test green and doesn't change any behaviour. Shared components get translated in the first PR that touches them.

    A few questions before I start:

    • Is this split OK, or would you rather track it as a new issue with sub-issues?
    • Should backend error messages shown in the UI stay in English for now? I'd leave them out of scope unless you want them in.
    • Is there someone on your side who can check the DE and IT wording, or should I keep flagging the strings I'm unsure about in the PR description like before?

    Happy to start with the auth and onboarding pages as soon as you give the go-ahead.

  4. helpcodeai commented on Oct 26, 2026

    @helpcodeai
    ContributorAuthor

    @sapatmohit thanks, #1248 and #1257 were a pleasure to review. Yes, please keep going.

    • Split: it's good, smallest and most seen first. Please open one new issue with your seven areas as a checklist and link each PR to it. Then we can close this one, since its scope is done.
    • One PR at a time: open the next PR when the previous one is merged. That keeps conflicts in the three message files small.
    • Backend errors: keep them in English for now and out of scope.
    • DE and IT wording: we check both ourselves. Keep flagging the strings you are unsure about in the PR description, like before.
    • Tests: Accept-Language: en-US must keep rendering exactly what it renders today, so the Playwright tests stay green.

    Go ahead with auth and onboarding.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthacktoberfestGood for Hacktoberfest contributorshelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions