Storing Locale Preference

+15 Mana ✨

Introduction

Remembering a user's language preference improves UX. They shouldn't have to switch languages on every visit.

Key Concepts

Storage options:

  • Cookies: Work with SSR, read by middleware
  • localStorage: Client-only, persists across sessions
  • Database: For authenticated users

Deep Dive

typescript
// proxy.ts
import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

const locales = ['en', 'fr', 'de'];
const defaultLocale = 'en';

export function proxy(request: NextRequest) {
  // 1. Check cookie first
  const cookieLocale = request.cookies.get('NEXT_LOCALE')?.value;
  if (cookieLocale && locales.includes(cookieLocale)) {
    return redirectToLocale(request, cookieLocale);
  }

  // 2. Fall back to browser preference
  const browserLocale = getBrowserLocale(request);
  return redirectToLocale(request, browserLocale);
}

function getBrowserLocale(request: NextRequest): string {
  const headers = { 'accept-language': request.headers.get('accept-language') || '' };
  const languages = new Negotiator({ headers }).languages();
  return match(languages, locales, defaultLocale);
}
typescript
// app/api/locale/route.ts
import { cookies } from 'next/headers';

export async function POST(request: Request) {
  const { locale } = await request.json();
  
  const cookieStore = await cookies();
  cookieStore.set('NEXT_LOCALE', locale, {
    maxAge: 60 * 60 * 24 * 365, // 1 year
    path: '/',
  });
  
  return Response.json({ success: true });
}

Summary

Use cookies to store locale preference—they work with the proxy and SSR. Check cookie first, then fall back to browser Accept-Language header. Save preferences when users explicitly switch languages.

✓ Completed