HTTP

Header

Accept-Language Header

Learn how the Accept-Language header tells servers which languages your client prefers for localized content. Understand language tags and quality values.

4 min read beginner Try in Playground

TL;DR: Tells servers what languages your client prefers (en-US, es, fr, etc.). Used for content localization and serving appropriate language versions.

What is Accept-Language?

The Accept-Language header tells the server what human languages your client prefers. It’s like walking into a restaurant and saying “I speak English and a little Spanish” so they can give you the right menu.

Servers use this for content negotiation to serve localized versions of pages, error messages, and data.

How Accept-Language Works

Client specifies language preferences:

GET /welcome HTTP/1.1
Host: example.com
Accept-Language: en-US, en;q=0.9, es;q=0.8, fr;q=0.7
```text

**Server responds with appropriate language:**

```http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Language: en-US

<h1>Welcome to our site!</h1>

Language Tag Format

Basic Language Codes

Accept-Language: en          # English (any variant)
Accept-Language: es          # Spanish (any variant)
Accept-Language: fr          # French (any variant)
Accept-Language: de          # German (any variant)
```http

### Language with Region

```http
Accept-Language: en-US       # US English
Accept-Language: en-GB       # British English
Accept-Language: es-ES       # Spain Spanish
Accept-Language: es-MX       # Mexican Spanish
Accept-Language: fr-CA       # Canadian French

Quality Values (Preferences)

Accept-Language: en-US;q=1.0, en;q=0.9, es;q=0.8, fr;q=0.5
```text

This means:

- US English is most preferred (q=1.0)
- General English is second choice (q=0.9)
- Spanish is third choice (q=0.8)
- French is acceptable (q=0.5)

## Real-World Examples

### US Browser

```http
Accept-Language: en-US,en;q=0.9

European Browser

Accept-Language: de-DE,de;q=0.9,en;q=0.8
```text

### Multilingual User

```http
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7

Mobile App

Accept-Language: es-MX,es;q=0.9,en;q=0.8
```text

## Common Language Codes

### Major Languages

| Code    | Language   | Region         |
| ------- | ---------- | -------------- |
| `en-US` | English    | United States  |
| `en-GB` | English    | United Kingdom |
| `es-ES` | Spanish    | Spain          |
| `es-MX` | Spanish    | Mexico         |
| `fr-FR` | French     | France         |
| `fr-CA` | French     | Canada         |
| `de-DE` | German     | Germany        |
| `it-IT` | Italian    | Italy          |
| `pt-BR` | Portuguese | Brazil         |
| `pt-PT` | Portuguese | Portugal       |

### Asian Languages

| Code    | Language | Region               |
| ------- | -------- | -------------------- |
| `zh-CN` | Chinese  | China (Simplified)   |
| `zh-TW` | Chinese  | Taiwan (Traditional) |
| `ja-JP` | Japanese | Japan                |
| `ko-KR` | Korean   | South Korea          |
| `hi-IN` | Hindi    | India                |
| `ar-SA` | Arabic   | Saudi Arabia         |

## Server Response Strategies

### Exact Match

```http
# Client requests
Accept-Language: fr-CA

# Server has French Canadian content
Content-Language: fr-CA

Fallback to General Language

# Client requests
Accept-Language: es-AR

# Server only has general Spanish
Content-Language: es
```text

### Default Language

```http
# Client requests
Accept-Language: zh-CN

# Server only has English
Content-Language: en

Multiple Language Support

# Client requests
Accept-Language: de-DE,en;q=0.8

# Server responds in German
Content-Language: de-DE
```text

## Best Practices

### For Clients

**1. Include fallback languages**

```http
Accept-Language: fr-CA,fr;q=0.9,en;q=0.8

2. Be specific about regions when it matters

# Different Spanish variants
Accept-Language: es-MX,es;q=0.9,en;q=0.8
```text

**3. Use quality values for preferences**

```http
Accept-Language: de-DE;q=1.0,en;q=0.8,fr;q=0.6

For Servers

1. Implement graceful fallbacks

function selectLanguage(acceptLanguage, availableLanguages) {
  const requested = parseAcceptLanguage(acceptLanguage)

  // Try exact match first
  for (const lang of requested) {
    if (availableLanguages.includes(lang.code)) {
      return lang.code
    }
  }

  // Try language without region
  for (const lang of requested) {
    const baseLanguage = lang.code.split('-')[0]
    const match = availableLanguages.find((l) => l.startsWith(baseLanguage))
    if (match) return match
  }

  // Default to English or primary language
  return 'en'
}
```javascript

**2. Set Content-Language in responses**

```javascript
app.get('/content', (req, res) => {
  const language = selectLanguage(req.headers['accept-language'], ['en', 'es', 'fr'])
  const content = getLocalizedContent(language)

  res.set('Content-Language', language)
  res.json(content)
})

3. Handle missing translations gracefully

function getLocalizedMessage(key, language) {
  const messages = {
    en: { welcome: 'Welcome!' },
    es: { welcome: '¡Bienvenido!' },
    fr: { welcome: 'Bienvenue!' }
  }

  // Try requested language
  if (messages[language] && messages[language][key]) {
    return messages[language][key]
  }

  // Fallback to English
  return messages['en'][key] || key
}
```text

## Browser Behavior

### Automatic Headers

Browsers automatically send Accept-Language based on:

- User's OS language settings
- Browser language preferences
- Manually configured language preferences

### Typical Browser Headers

```http
# Chrome on Windows (US)
Accept-Language: en-US,en;q=0.9

# Firefox on macOS (Germany)
Accept-Language: de-DE,de;q=0.8,en-US;q=0.5,en;q=0.3

# Safari on iOS (Spain)
Accept-Language: es-ES,es;q=0.9,en;q=0.8

API Localization

Error Messages

app.use((err, req, res, next) => {
  const language = selectLanguage(req.headers['accept-language'], ['en', 'es', 'fr'])

  const errorMessages = {
    en: 'An error occurred',
    es: 'Ocurrió un error',
    fr: "Une erreur s'est produite"
  }

  res.status(500).json({
    error: errorMessages[language] || errorMessages['en']
  })
})
```javascript

### Data Localization

```javascript
app.get('/products', (req, res) => {
  const language = selectLanguage(req.headers['accept-language'], ['en', 'es', 'fr'])

  const products = getProducts().map((product) => ({
    id: product.id,
    name: product.names[language] || product.names['en'],
    description: product.descriptions[language] || product.descriptions['en'],
    price: formatPrice(product.price, language)
  }))

  res.set('Content-Language', language)
  res.json(products)
})

Testing Language Negotiation

Using curl

# Test English
curl -H "Accept-Language: en-US" https://example.com/api/messages

# Test Spanish
curl -H "Accept-Language: es-ES" https://example.com/api/messages

# Test with fallbacks
curl -H "Accept-Language: de-DE,en;q=0.8" https://example.com/api/messages
```text

### Using JavaScript

```javascript
fetch('/api/content', {
  headers: {
    'Accept-Language': 'fr-FR,fr;q=0.9,en;q=0.8'
  }
})

Common Patterns

Progressive Language Support

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
```text

Prefer Chinese (China), fall back to general Chinese, then English.

### Regional Preferences

```http
Accept-Language: en-AU,en-GB;q=0.9,en;q=0.8

Prefer Australian English, then British English, then general English.

Multilingual User

Accept-Language: ru-RU,ru;q=0.9,en;q=0.8,de;q=0.7

Russian speaker who also knows English and German.

Frequently Asked Questions

What is Accept-Language?

Accept-Language tells the server which languages the client prefers. Servers use this for content negotiation to return localized content. Example: Accept-Language: en-US, en;q=0.9, fr;q=0.8.

How does language preference work?

Languages are listed with optional quality values (q). Higher q means higher preference. en-US,en;q=0.9 prefers US English, then any English. Default q is 1.0.

Should I use Accept-Language for localization?

Use it as a default, but let users override. Store user preference in cookies or profiles. Accept-Language reflects browser settings, not necessarily user preference.

What is the difference between en and en-US?

en is generic English. en-US is US English specifically. en-GB is British English. Servers may match en-US to en if no specific variant exists.

Keep Learning