Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions apps/docs/app/[lang]/privacy/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ const content = {
},
};

/**
* The locales this page is actually written in: the keys of the `content`
* record above, which is where this page's copy lives.
*
* `app/sitemap.ts` reads this rather than restating the pair, so a translation
* added to `content` is advertised to crawlers by that edit alone. The renderer
* below still serves English for any other locale, but that fallback is not a
* translation and must not be advertised as one — which is why this is derived
* from `content`, not from `i18n.languages`.
*
* A named export next to a page's default is valid App Router: Next's generated
* route validator (`.next/types/validator.ts`) constrains the *known* page
* exports and ignores additional ones.
*/
export const contentLocales = Object.keys(content);

export default async function PrivacyPage({
params,
}: {
Expand Down
16 changes: 16 additions & 0 deletions apps/docs/app/[lang]/terms/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ const content = {
},
};

/**
* The locales this page is actually written in: the keys of the `content`
* record above, which is where this page's copy lives.
*
* `app/sitemap.ts` reads this rather than restating the pair, so a translation
* added to `content` is advertised to crawlers by that edit alone. The renderer
* below still serves English for any other locale, but that fallback is not a
* translation and must not be advertised as one — which is why this is derived
* from `content`, not from `i18n.languages`.
*
* A named export next to a page's default is valid App Router: Next's generated
* route validator (`.next/types/validator.ts`) constrains the *known* page
* exports and ignores additional ones.
*/
export const contentLocales = Object.keys(content);

export default async function TermsPage({
params,
}: {
Expand Down
24 changes: 12 additions & 12 deletions apps/docs/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,11 @@ import type { MetadataRoute } from 'next';
import { source } from '@/lib/source';
import { i18n } from '@/lib/i18n';
import { languageAlternates, localeUrl, translatedLocales } from '@/lib/seo';
import { contentLocales as privacyLocales } from './[lang]/privacy/page';
import { contentLocales as termsLocales } from './[lang]/terms/page';

export const revalidate = false;

/**
* Locales in which `privacy` and `terms` are actually written. Those two pages
* carry their copy in a `content` record inside their own route component
* (`app/[lang]/privacy/page.tsx`, `app/[lang]/terms/page.tsx`), which falls back
* to English (`content[lang] ?? content.en`) for anything not listed there —
* the same fallback-shaped defect the docs pages have. Keep this in sync with
* those two records.
*/
const STATIC_PAGE_LOCALES = ['en', 'zh-Hans'];

export default function sitemap(): MetadataRoute.Sitemap {
const entries: MetadataRoute.Sitemap = [];

Expand All @@ -23,8 +15,16 @@ export default function sitemap(): MetadataRoute.Sitemap {
// The root exists in every locale: it is a language dispatch page that
// redirects to that locale's /docs.
{ path: '', priority: 1, locales: i18n.languages },
{ path: 'privacy', priority: 0.3, locales: STATIC_PAGE_LOCALES },
{ path: 'terms', priority: 0.3, locales: STATIC_PAGE_LOCALES },
// `privacy` and `terms` carry their copy in a `content` record inside their
// own route component, and render `content[lang] ?? content.en` for every
// other locale — the same fallback shape the docs pages had. So the locales
// they can honestly advertise are the keys of those records, and each module
// exports its own: this file derives the set instead of restating it, and a
// translation added to either record reaches the sitemap by that edit alone.
// Read separately because they are separate records — they agree today, and
// nothing makes them have to.
{ path: 'privacy', priority: 0.3, locales: privacyLocales },
{ path: 'terms', priority: 0.3, locales: termsLocales },
];

// Documentation pages. `source.getPages()` with no argument returns every
Expand Down