🎉 v1.0

Get started

  • Welcome
  • Documentation
  • Pricing
    Soon

Tools

  • I18n MCP
  • CLI
  • CI/CD Integrations
  • Compiler
    Alpha
  • Connect Your Engine

Resources

  • Languages
  • LLM Models
  • Guides

Company

  • Enterprise
  • CareersHiring!
Dashboard

Lingo.dev Compiler

  • How it works
  • Setup

Framework Integration

  • Next.js
  • Vite + React

Configuration

  • Configuration Reference
  • Translation Providers
  • Build Modes

Features

  • Manual Overrides
  • Custom Locale Resolvers
  • Automatic Pluralization
  • Locale Switching

Development

  • Development Tools
  • Project Structure

Guides

  • Best Practices
  • Migration Guide
  • Troubleshooting

Custom Locale Resolvers

Max PrilutskiyMax Prilutskiy·Updated 5 days ago·3 min read

Alpha

The Lingo.dev Compiler is in alpha. It is unstable, not recommended for production use, and APIs may change between releases.

Custom locale resolvers let you override how the Lingo.dev Compiler detects and persists the user's locale. By default, the compiler uses cookie-based persistence configured via the localePersistence option. For more control - URL-based routing, header detection, localStorage, or any custom logic - create resolver files in the .lingo/ directory.

Resolver files#

The compiler looks for two optional files:

FileEnvironmentExports
.lingo/locale-resolver.server.tsServer-side (SSR, RSC)resolveLocale(request: Request): string
.lingo/locale-resolver.client.tsClient-side (browser)resolveLocale(): string and persistLocale(locale: string): void

If a resolver file exists, the compiler uses it instead of the default cookie-based behavior. If only one file exists, the other environment falls back to the default.

Server-side resolver#

The server resolver receives the incoming Request object and returns a locale code string:

ts
// .lingo/locale-resolver.server.ts

export function resolveLocale(request: Request): string {
  const url = new URL(request.url);

  // Check URL path prefix: /es/about -> "es"
  const pathLocale = url.pathname.split("/")[1];
  const supportedLocales = ["en", "es", "de", "fr", "ja"];

  if (supportedLocales.includes(pathLocale)) {
    return pathLocale;
  }

  // Fall back to Accept-Language header
  const acceptLanguage = request.headers.get("Accept-Language");
  if (acceptLanguage) {
    const preferred = acceptLanguage.split(",")[0].split("-")[0];
    if (supportedLocales.includes(preferred)) {
      return preferred;
    }
  }

  return "en";
}

Client-side resolver#

The client resolver has two functions: one to read the current locale and one to persist a locale change:

ts
// .lingo/locale-resolver.client.ts

export function resolveLocale(): string {
  // Check URL path prefix
  const pathLocale = window.location.pathname.split("/")[1];
  const supportedLocales = ["en", "es", "de", "fr", "ja"];

  if (supportedLocales.includes(pathLocale)) {
    return pathLocale;
  }

  // Fall back to localStorage
  const stored = localStorage.getItem("locale");
  if (stored && supportedLocales.includes(stored)) {
    return stored;
  }

  return "en";
}

export function persistLocale(locale: string): void {
  localStorage.setItem("locale", locale);

  // Navigate to the locale-prefixed URL
  const path = window.location.pathname.replace(/^\/[a-z]{2}/, "");
  window.location.href = `/${locale}${path}`;
}

Common resolver patterns#

Route by URL path prefix (/es/about, /de/pricing):

ts
// .lingo/locale-resolver.server.ts
export function resolveLocale(request: Request): string {
  const url = new URL(request.url);
  const locale = url.pathname.split("/")[1];
  const supported = ["en", "es", "de", "fr"];
  return supported.includes(locale) ? locale : "en";
}
ts
// .lingo/locale-resolver.client.ts
export function resolveLocale(): string {
  const locale = window.location.pathname.split("/")[1];
  const supported = ["en", "es", "de", "fr"];
  return supported.includes(locale) ? locale : "en";
}

export function persistLocale(locale: string): void {
  const path = window.location.pathname.replace(/^\/[a-z]{2}/, "");
  window.location.href = `/${locale}${path}`;
}

The resolveLocale function must return a locale code that matches one of your configured targetLocales or sourceLocale. Returning an unsupported locale code causes the compiler to fall back to the source locale.

Next Steps#

Locale Switching
Build a language switcher component
Configuration Reference
localePersistence options
Project Structure
The .lingo/ directory layout
Next.js Integration
Server-side locale resolution in Next.js

Was this page helpful?