Skip to content

Internationalization

Astro’s internationalization (i18n) features allow you to adapt your project for an international audience.

i18n Routing

Added in: astro@3.5.0

Astro’s i18n routing allows you to add your multilingual content with support for configuring a default language, computing relative page URLs, and accepting preferred languages provided by your visitor’s browser. You can also specify fallback languages on a per-language basis so that your visitors can always be directed to existing content on your site.

This routing API helps you generate, use, and verify the URLs that your multi-language site produces. Check back and update regularly for the latest new features as this API continues to develop!

Configure i18n routing

  1. Enable the routing option by adding an i18n object to your Astro configuration with a default location (defaultLocale) and a list of all languages to support (locales):

    astro.config.mjs
    import { defineConfig } from "astro/config"
    export default defineConfig({
    i18n: {
    defaultLocale: "en",
    locales: ["en", "es", "pt-br"]
    }
    })
  2. Choose and configure a routing based on the desired URL path for your defaultLocale:

  • "prefixDefaultLocale: false" (default): URLs in your default language will not have a /[locale]/ prefix. All other locales will.

  • "prefixDefaultLocale: true": All URLs, including your default language, will have a /[locale]/ prefix.

    astro.config.mjs
    import { defineConfig } from "astro/config"
    export default defineConfig({
    i18n: {
    defaultLocale: "en",
    locales: ["es", "en", "fr"],
    routing: {
    prefixDefaultLocale: false
    }
    }
    })
  1. Organize your content folders with localized content by language. Your folder names must match the items in locales exactly, and your folder organization must match the URL paths chosen for your routing.

    Include a localized folder for your defaultLocale only if you configure prefixDefaultLocale: false to show a localized URL path.

    • Directorysrc
      • Directorypages
        • about.astro
        • index.astro
        • Directoryes
          • about.astro
          • index.astro
        • Directorypt-br
          • about.astro
          • index.astro
  2. With i18n routing configured, you can now compute links to pages within your site using the getRelativeLocaleURL() helper available from the astro:i18n module. This will always provide the correct, localized route and can help you correctly use, or check, URLs on your site. You can also still write the links manually.

    src/pages/es/index.astro
    ---
    import { getRelativeLocaleUrl } from 'astro:i18n';
    // defaultLocale is "es"
    const aboutURL=getRelativeLocaleUrl("es", "about");
    ---
    <a href="/get-started/">¡Vamos!</a>
    <a href={getRelativeLocaleUrl('es', 'blog')}>Blog</a>
    <a href={aboutURL}>Acerca</a>

routing

Astro’s built-in file-based routing automatically creates URL routes for you based on your file structure within src/pages/. When you configure i18n routing, the routing value now allows you to specify your file structure (and corresponding URL paths generated) in order to use helper functions to generate, use, and verify the routes in your project.

prefixDefaultLocale: false

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
defaultLocale: "en",
locales: ["es", "en", "fr"],
routing: {
prefixDefaultLocale: false
}
}
})

This is the default value. Set this option when URLs in your default language will not have a /[locale]/ prefix and files in your default language exist at the root of src/pages/.

  • src/pages/blog.astro will produce the route example.com/blog/
  • src/pages/fr/blog.astro will produce the route example.com/fr/blog/
  • If there is no file at src/pages/es/blog.astro, then the route example.com/es/blog/ will 404 unless you specify a fallback strategy.

prefixDefaultLocale: true

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
defaultLocale: "en",
locales: ["es", "en", "fr"],
routing: {
prefixDefaultLocale: true
}
}
})

Set this option when all routes will have their /locale/ prefix in their URL and when all page content files, including those for your defaultLocale, exist in a localized folder:

  • Directorysrc
    • Directorypages
      • index.astro
      • Directoryen
        • index.astro
        • about.astro
      • Directoryes
        • about.astro
        • index.astro
      • Directorypt-br
        • about.astro
        • index.astro
  • URLs without a locale prefix, (e.g. example.com/blog/) will return a 404 (not found) status code.
  • The home URL (/) redirects to /<defaultLocale>.

defaultLocale and locales

Both a default language (defaultLocale) and a list of all supported languages (locales) must be specified in your i18n routing configuration.

Each entry in the locales configuration array must be either a string (e.g. "fr", "pt-br") or a custom locale path. locales may contain a combination of strings and custom paths.

Your /[locale]/ folder names must match exactly the locales in the list (either the string or the path value), and your routing configuration must correspond to whether or not you have a localized folder for your default language. Every other supported language must have its own localized folder.

Depending on your deploy host, you may discover transformations in URL paths, so check your deployed site to determine the best syntax for your locale values.

Custom locale paths

In addition to defining your site’s supported locales as strings (e.g. “en”, “pt-br”), Astro also allows you to map an arbitrary number of browser-recognized language codes to a custom URL path. While locales can be strings of any format as long as they correspond to your project folder structure, codes must follow the browser’s accepted syntax.

Pass an object to the locales array with a path key to define a custom URL prefix, and codes to indicate the languages mapped to this URL. In this case, your /[locale]/ folder name must match exactly the value of the path and your URLs will be generated using the path value.

This is useful if you support multiple variations of a language (e.g. "fr", "fr-BR", and "fr-CA") and you want to have all these variations mapped under the same URL /fr/, or even customize it entirely (e.g. /french/):

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
defaultLocale: "en",
locales: ["es", "en", "fr"],
locales: ["es", "en", {
path: "french", // no slashes included
codes: ["fr", "fr-BR", "fr-CA"]
}],
routing: {
prefixDefaultLocale: true
}
}
})

When using functions from the astro:i18n virtual module to compute valid URL paths based on your configuration (e.g. getRelativeLocaleUrl()), use the path as the value for locale.

Browser language detection

Astro’s i18n routing combined with one of Astro’s on-demand server rendering modes (output:'server' or output:'hybrid') allow you to access two properties for browser language detection: Astro.preferredLocale and Astro.preferredLocaleList.

These combine the browser’s Accept-Langauge header, and your locales (strings or codes) to automatically respect your visitor’s preferred languages.

  • Astro.preferredLocale: Astro can compute a preferred locale for your visitor if their browser’s preferred locale is included in your locales array. This value is undefined if no such match exists.
  • Astro.preferredLocaleList: An array of all locales that are both requested by the browser and supported by your website. This produces a list of all compatible languages between your site and your visitor. The value is [] if none of the browser’s requested languages are found in your locales array. If the browser does not specify any preferred languages, then this value will be i18n.locales.
  • Astro.currentLocale: The locale computed from the current URL, using the syntax specified in your locales configuration. If the URL does not contain a /[locale]/ prefix, then the value will default to i18n.defaultLocale.

In order to successfully match your visitors’ preferences, provide your codes using the same pattern used by the browser.

Fallback

Astro’s i18n routing allows you to configure a fallback routing strategy. When a page in one language doesn’t exist (e.g. a page that is not yet translated), instead of displaying a 404 page, you can redirect a user from one locale to another on a per-language basis. This is useful when you do not yet have a page for every route, but you want to still provide some content to your visitors.

For example, the configuration below sets es as the fallback locale for any missing fr routes. This means that a user visiting example.com/fr/my-page/ will be redirected to and shown the content for example.com/es/my-page/ instead of being taken to a 404 page when src/pages/fr/my-page.astro does not exist.

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
defaultLocale: "en",
locales: ["es", "en", "fr"],
fallback: {
fr: "es"
}
}
})

Astro will ensure that a page is built in src/pages/fr for every page that exists in src/pages/es/. If the page does not already exist, then a page with a redirect to the corresponding es route will be created.

Virtual module astro:i18n

This module provides functions that can help you create URLs using your project’s configured locales.

Creating routes for your project with the i18n router will depend on certain configuration values you have set that affect your page routes. When creating routes with these functions, be sure to take into account your individual settings for:

Also, note that the returned URLs created by these functions for your defaultLocale will reflect your i18n.routing configuration.

URLs created when prefixDefaultLocale: true is configured will include a /lang/ path in the URL. URLs created with prefixDefaultLocale: false will not include a language prefix.

getRelativeLocaleUrl()

getRelativeLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string

Use this function to retrieve a relative path for a locale. If the locale doesn’t exist, Astro throws an error.

---
getRelativeLocaleUrl("fr", "");
// returns /fr
getRelativeLocaleUrl("fr", "getting-started");
// returns /fr/getting-started
getRelativeLocaleUrl("fr_CA", "getting-started", {
prependWith: "blog"
});
// returns /blog/fr-ca/getting-started
getRelativeLocaleUrl("fr_CA", "getting-started", {
prependWith: "blog",
normalizeLocale: false
});
// returns /blog/fr_CA/getting-started
---

getAbsoluteLocaleUrl()

getAbsoluteLocaleUrl(locale: string, path: string, options?: GetLocaleOptions): string

Use this function to retrieve an absolute path for a locale when site has a value. If site isn’t configured, the function returns a relative URL. If the locale doesn’t exist, Astro throws an error.

src/pages/index.astro
---
// If `site` is set to be `https://example.com`
getAbsoluteLocaleUrl("fr", "");
// returns https://example.com/fr
getAbsoluteLocaleUrl("fr", "getting-started");
// returns https://example.com/fr/getting-started
getAbsoluteLocaleUrl("fr_CA", "getting-started", {
prependWith: "blog"
});
// returns https://example.com/blog/fr-ca/getting-started
getAbsoluteLocaleUrl("fr_CA", "getting-started", {
prependWith: "blog",
normalizeLocale: false
});
// returns https://example.com/blog/fr_CA/getting-started
---

getRelativeLocaleUrlList()

Use this like getRelativeLocaleUrl to return a list of relative paths for all the locales.

getRelativeLocaleUrlList(locale: string, options?: GetLocaleOptions): string[]

getAbsoluteLocaleUrlList()

getAbsoluteLocaleUrlList(locale: string, options?: GetLocaleOptions): string[]

Use this like getAbsoluteLocaleUrl to return a list of absolute paths for all the locales.

getPathByLocale(locale: string): string

A function that returns the path associated to one or more codes when custom locale paths are configured.

Generating URLs from custom paths

When a locale is a custom path, use the path as the value for locale.

For example, use french in the i18n helper functions for the locales configuration below:

locales: ["es", "en", {
path: "french",
codes: ["fr", "fr-BR", "fr-CA"]
}],
src/pages/index.astro
---
import { getPathByLocale, getRelativeLocaleUrl, getLocaleByPath } from "astro:i18n";
getRelativeLocaleUrl("french", "blog"); // returns /french/blog
---

Note that other astro:i18n functions will return the following results for the same configuration:

src/pages/index.astro
---
getPathByLocale("fr"); // returns "french"
getPathByLocale("fr-CA"); // returns "french"
getLocaleByPath("french"); // returns "fr" because that's the first code configured
---

getLocaleByPath(path: string): string

A function that returns the code associated to a locale path.

Retrieve the locale for a custom path

Given a custom path configured with multiple codes, the function will return the first code configured:

astro.config.mjs
import {defineConfig} from "astro/config"
export default defineConfig({
i18n: {
defaultLocale: 'en',
locales: ['en', 'es', 'fr', {
path: "portugues",
codes: ["pt-AO", "pt", "pt-BR"]
}]
}
})
src/pages/index.astro
---
import { getLocaleByPath } from "astro:18n";
console.log(getLocaleByPath('en')) // will log "en"
console.log(getLocaleByPath('fr')) // will log "fr"
console.log(getLocaleByPath('portugues')) // will log "pt-AO"
---