DEV Community

Cover image for A Simple Way to Handle Locale-Specific URLs in Express
Sergey Li
Sergey Li

Posted on

A Simple Way to Handle Locale-Specific URLs in Express

Introduction

At TextPixie, as we expanded our AI Translator to support multiple languages, we needed a straightforward internationalization solution that would work with our existing Express-based backend, which doesn’t have built-in i18n support.

While we considered using i18next, we found that it offered much more than we needed and would complicate our backend. Instead, we decided to build a custom solution that focused on the two key requirements for our project:

  1. Setting up locale-specific URLs.
  2. Managing strings in Google Sheets and loading them onto pages based on the locale in the URL.

In this article, I’ll walk you through how we implemented locale-specific URLs using a simple Express middleware. In a follow-up article, I’ll dive into how we manage strings in Google Sheets and load them onto pages based on the locale in the URL.

The Problem

When we started expanding our AI Translator, we knew that to make the app truly multilingual, we needed clean, accessible URLs for each supported language. Ideally, our URLs would look something like this:

Our initial approach involved defining routes in Express like this:

app.get('/:lang/', homepageHandler);
app.get('/', defaultHomepageHandler);
app.get('/:lang/image-translator', imageTranslatorHandler);
app.get('/image-translator', defaultImageTranslatorHandler);
Enter fullscreen mode Exit fullscreen mode

However, this method quickly led to two significant issues:

  1. Route Conflicts: The /:lang/ route could unintentionally match URLs meant for other pages, such as /image-translator, leading to incorrect page rendering.
  2. Code Duplication: We had to define multiple routes for each page to handle different languages, which resulted in repetitive and hard-to-maintain code.

Our Middleware Solution

To overcome these challenges, we developed a simple Express middleware function:

function extractLocale(req, res, next) {
    const pathParts = req.path.split("/").filter(Boolean);
    const firstDir = pathParts[0];
    if (checkLocalsExisted(firstDir)) {
        req.lang = firstDir;
        req.url = req.url.replace(`/${firstDir}`, "");
    } else {
        req.lang = "en";
    }
    next();
}
Enter fullscreen mode Exit fullscreen mode

This middleware does two key things:

  1. Locale Extraction: It checks if the first part of the URL is a valid locale (e.g., “en” or “zh-tw”).
  2. URL Rewriting: If a valid locale is found, it removes the locale from the URL and stores it in req.lang, allowing the rest of the app to process the request without worrying about the locale prefix.

Implementation

We integrated this middleware into our Express application as follows:

const express = require('express');
const app = express();

app.use(extractLocale);

app.get('/', homeHandler);
app.get('/image-translator', imageTranslatorHandler);
Enter fullscreen mode Exit fullscreen mode

Here’s how the middleware processes different URLs:

This setup allows us to use a single route definition to handle multiple locales, simplifying our codebase and making it easier to maintain. The middleware ensures that the correct locale is extracted and handled without the need for duplicating routes.

Conclusion

By implementing this simple Express middleware, we were able to create a clean and efficient solution for handling locale-specific URLs in our web app. This approach helped us avoid route conflicts, reduce code duplication, and streamline our internationalization process.

In a follow-up article, I’ll dive into how we manage strings in Google Sheets and load them onto pages based on the locale in the URL. This second step is crucial for ensuring that the right content is displayed to users based on their language preference.

If you’re interested in seeing this solution in action, check out TextPixie AI Translator to experience how we handle multilingual content.


This article was originally published at TextPixie Blog.

Top comments (0)