Skip to content

feat(redesign): i18n language selection#2197

Merged
g-francesca merged 93 commits intoredesignfrom
i18n-lang-selection
Mar 2, 2026
Merged

feat(redesign): i18n language selection#2197
g-francesca merged 93 commits intoredesignfrom
i18n-lang-selection

Conversation

@g-francesca
Copy link
Collaborator

@g-francesca g-francesca commented Feb 25, 2026

preview: https://deploy-preview-2197--expressjscom-preview.netlify.app/

This PR implements internationalization (i18n) support for the Express.js documentation site with a language selector component that allows users to switch between 10 supported languages.

Key Features

  • Language Selector: New dropdown component in the header to switch between supported languages (English, German, Spanish, French, Italian, Japanese, Korean, Portuguese (BR), Chinese (Simplified), Chinese (Traditional))
  • i18n Infrastructure:
    • Implemented useTranslations utility to replace hardcoded content throughout the site
    • Language-specific JSON files for UI translations (astro/src/i18n/locales/)
    • Language-aware routing and content structure
  • 404 Handling: Added a 404 page with i18n support to gracefully handle missing translations for specific languages

Important Notes

Large Diff Size: The PR appears very large (a lot of files under de/ content collection) because German markdown content was added for demo purposes only to showcase the full i18n functionality. These files can be removed to start with a clean folder structure if preferred. The 404 page ensures graceful fallback for missing language content.

Translation Review Needed: All UI translations in the locale JSON files were generated with AI assistance and should be reviewed by native speakers for accuracy and cultural appropriateness.

Technical Changes

  • Refactored components to use i18n utilities
  • Created primitive Select component used by LanguageSelect and VersionSwitcher
  • Updated routing to support language-prefixed URLs (/{lang}/...)
  • All hardcoded strings replaced with translation keys

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or

(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or

(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.

(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

@g-francesca g-francesca requested a review from a team as a code owner February 25, 2026 09:48
@netlify
Copy link

netlify bot commented Feb 25, 2026

Deploy Preview for expressjscom-preview ready!

Name Link
🔨 Latest commit 191930d
🔍 Latest deploy log https://app.netlify.com/projects/expressjscom-preview/deploys/69a30b09d84d8b000803cbfd
😎 Deploy Preview https://deploy-preview-2197--expressjscom-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 100 (🟢 up 4 from production)
Accessibility: 100 (🟢 up 13 from production)
Best Practices: 100 (no change from production)
SEO: 100 (🟢 up 6 from production)
PWA: 80 (🟢 up 50 from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@ShubhamOulkar
Copy link
Member

const docsCollection = defineCollection({
  loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/docs' }),
  schema: z.object({
    title: z.string(),
    description: z.string().optional(),
  }),
});

@g-francesca, Are we going to use .mdx file in future? Why underscore is excluded inside pattern?

Moved translation files from locales to ui under src/i18n and updated all corresponding references across the project.
@g-francesca
Copy link
Collaborator Author

Are we going to use .mdx file in future? Why underscore is excluded inside pattern?

@ShubhamOulkar I added mdx in case you want to use it in the future, but if this is not the case, we can remove it.
About the underscore, this is to exclude any file whose name starts with an underscore, in case you need to mark some files as draft. Let me know if you prefer to change this config.

@bjohansebas
Copy link
Member

Technically, using MDX is ideal if we want to use components inside our Markdown, so that’s fine.

Comment on lines +18 to +20
<div>
<Button as="a" href={`/${lang}/`} variant="primary">{t('404.goHome')}</Button>
</div>
Copy link
Member

Choose a reason for hiding this comment

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

We should add a call to action to report it in case it’s an error, like we have on the website.

@socket-security
Copy link

socket-security bot commented Feb 28, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​types/​node@​25.3.0 ⏵ 25.3.21001008196100
Updatednpm/​astro@​5.16.11 ⏵ 5.18.097 +11008898 +1100

View full report

Copy link
Member

Choose a reason for hiding this comment

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

While running locally, i18n works for this page. But once it’s built, it doesn’t work because the pages are static and Astro only compiles a single 404 page. I suppose that if the page weren’t static, i18n would work for this, but we can’t enable server rendering since the site is built with GitHub Actions, and changing the infrastructure isn’t something we want to do.

Copy link
Member

@bjohansebas bjohansebas left a comment

Choose a reason for hiding this comment

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

LGTM, you can merge it if no one else suggests changes. It’s been a heavy week and I only had the chance to review the PR today

Important note: on the current site we have a banner saying that translations might be outdated. We shouldn’t add that in this redesign, because they actually won’t be outdated anymore since we now have automation that ensures they’re always up to date.

It’s true that we still have some mixed content, though. So instead, we should add a button at the very end like ‘Want to help translate?’ and link it to the contribution section that explains how to translate the site.

Image Image

But that can be done in a future PR.

@g-francesca
Copy link
Collaborator Author

LGTM, you can merge it if no one else suggests changes. It’s been a heavy week and I only had the chance to review the PR today

Important note: on the current site we have a banner saying that translations might be outdated. We shouldn’t add that in this redesign, because they actually won’t be outdated anymore since we now have automation that ensures they’re always up to date.

It’s true that we still have some mixed content, though. So instead, we should add a button at the very end like ‘Want to help translate?’ and link it to the contribution section that explains how to translate the site.

Image Image
But that can be done in a future PR.

Thank you for the review @bjohansebas. I'm merging the PR, and I've noted your comment about the help with translations.

@g-francesca g-francesca merged commit d8ed488 into redesign Mar 2, 2026
10 checks passed
@bjohansebas bjohansebas deleted the i18n-lang-selection branch March 2, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants