Skip to content

feat(i18n): consume Polylang translated slugs in nav and routing #55

@JohnRDOrazio

Description

@JohnRDOrazio

Problem

URLs in the site's static navigation never use translated slugs. Example: in the Header dropdown under Governance, "Criteri di valutazione" links to:

https://catholicdigitalcommons.org/it/governance/project-governance/project-vetting-criteria

The page renders Italian content (because WPGraphQL+Polylang resolves the English URI to the Italian translation server-side), but the URL itself stays in English.

The Italian slugs do exist in WordPress — Polylang auto-generated them from translated post titles (e.g. governanza-del-progetto). They're simply never consumed by the Next.js front-end.

Why

Two missing pieces:

  1. src/i18n/routing.ts:7 defines no pathnames map. Without one, createNavigation(routing) (src/i18n/navigation.ts) only prepends the locale; it never translates path segments.
  2. components/Header.tsx (and components/Footer.tsx) hardcode English paths (/governance/project-governance/project-vetting-criteria, etc.). With no pathnames map, those strings pass through verbatim.

The catch-all route app/[lang]/[[...slug]]/page.tsx:27 then does getPage(slug.join('/'), lang) against a WPGraphQL query (page(id: $slug, idType: URI).translation(language: $language)) that resolves English URIs to translations — which is why the page loads at all, but explains why nobody noticed the URL stayed English.

Suggested implementation

  1. Generate a pathnames map at build time from getAllPages(locale) for each locale. Key: canonical English URI; values: per-locale translated paths. Keep as a generated file (e.g. src/i18n/pathnames.generated.ts) regenerated on deploy. (The getAllPages query already returns slug per locale; a small extension to include parent-slug chains is enough to compose translated paths.)
  2. Add pathnames to defineRouting in src/i18n/routing.ts.
  3. Update the catch-all route to look up pages by language-aware URI. Two options:
    • switch GET_PAGE_BY_SLUG to use nodeByUri(uri: $uri) and pass the locale-prefixed URI, or
    • reverse-map the incoming localized slug → canonical English slug before calling getPage (using the same pathnames map).
  4. Header/Footer remain unchanged — they keep their canonical English hrefs; next-intl substitutes the localized path automatically once pathnames is configured.

Dependencies

Depends on #53 and the sitemap fix being resolved first, since they share the WP query layer (GET_ALL_PAGES, GET_CHILD_PAGES).

Open questions

  • Italian governance root currently has slug governance-2 (WP collision suffix because English took governance). Worth renaming to governanza in WP admin before the pathnames map gets baked in, so users don't have to re-bookmark.
  • Whether to drive the Header from a Polylang-managed nav menu in WP (more work, more maintainable as pages get renamed) vs. keeping it hardcoded with a generated pathnames map.

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