Strategy
Paraglide JS comes with various strategies to determine the locale out of the box.
The strategy is defined with the strategy
option. The priority is determined by the order of the strategies in the array. The first strategy that returns a locale will be used.
In the example below, the cookie
strategy first determines the locale. If no cookie is found, the baseLocale
is used.
Built-in strategies
cookie
The cookie strategy determines the locale from a cookie.
baseLocale
Returns the baseLocale
defined in the settings.
It is useful as a fallback strategy if no other strategy returns a locale, for example, if a cookie has not been set yet.
globalVariable
Uses a global variable to determine the locale.
This strategy is only useful in testing environments or to get started quickly. Setting a global variable can lead to cross-request issues in server-side environments, and the locale is not persisted between page reloads in client-side environments.
preferredLanguage
Automatically detects the user's preferred language from browser settings or HTTP headers.
- On the client: Uses navigator.languages
- On the server: Uses the Accept-Language header
The strategy attempts to match locale in order of user preference:
- First try exact matches (e.g., "en-US" if supported)
- Falls back to base language codes (e.g., "en")
For example:
- If user prefers
fr-FR,fr;q=0.9,en;q=0.7
and your app supports["en", "fr"]
, it will usefr
- If user prefers
en-US
and your app only supports["en", "de"]
, it will useen
localStorage
Determine the locale from the user's local storage.
url
Determine the locale from the URL (pathname, domain, etc).
The URL-based strategy uses the web standard URLPattern to match and localize URLs.
Locale prefixing
Translated pathnames
For pathnames where you want to localize the structure and path segments of the URL, you can use different patterns for each locale. This approach enables language-specific routes like /about
in English and /ueber-uns
in German.
Here's a simple example with translated path segments:
Domain-based localization
Adding a base path
You can add a base path to your URL patterns to support localized URLs with a common base path.
For example, with the base path set to "shop":
runtime.localizeHref("/about")
will return/shop/en/about
runtime.deLocalizeHref("/about")
will return/shop/about
When using a base path, it's important to make it optional using the {basepath/}?
syntax with curly braces and the ?
modifier. This ensures that paths without the base path will still be properly matched and have the base path added during localization.
This configuration enables:
The curly braces {}
with the ?
modifier ensure that the group is treated as optional, allowing both URLs with and without the base path to be matched and properly localized.
Making URL patterns unavailable in specific locales
You can configure certain URL patterns to be unavailable in specific locales by redirecting them to a 404 page or any other designated error page.
This is useful when some content or features should only be accessible in certain languages.
To implement this, map the pattern to your 404 page URL for the locales where the content should be unavailable:
When a user tries to access /specific-path
in German, they will be redirected to /de/404
instead. This approach allows you to:
- Make certain content available only in specific languages
- Create locale-specific restrictions for particular routes
- Implement gradual rollouts of features by language
- Handle legacy URLs that might only exist in certain locales
Note that other paths will still work normally through the catch-all pattern, so only the specifically configured paths will be unavailable.
Troubleshooting URL patterns
When working with URL patterns, there are a few important considerations to keep in mind:
Excluding paths is not supported
URLPattern does not support negative lookahead regex patterns.
The decision to not support negative lookaheads is likely related to ReDoS (Regular Expression Denial of Service) attacks. Read this blog post or the CVE on GitHub.
Pattern order matters
URL patterns are evaluated in the order they appear in the urlPatterns
array. The first pattern that matches a URL will be used. This means that more specific patterns should come before more general patterns.
Localized pattern order matters too
Within each pattern's localized
array, the order of locale patterns also matters. When localizing a URL, the first matching pattern for the target locale will be used. Similarly, when delocalizing a URL, patterns are checked in order.
This is especially important for path-based localization where one locale has a prefix (like /de/
) and another doesn't. In these cases, put the more specific pattern (with prefix) first.
Example: Multi-tenant application with specific routes
For a multi-tenant application with specific routes, proper pattern ordering is crucial:
With this configuration:
- Product URLs like
https://acme.example.com/products/123
will use the specific product pattern - Category URLs like
https://acme.example.com/categories/electronics
will use the specific category pattern - All other URLs will fall back to the general pattern
Write your own strategy
Write your own cookie, http header, or i18n routing based locale strategy to integrate Paraglide into any framework or app.
Only two APIs are needed to define this behaviour and adapt Paraglide JS to your requirements:
overwriteGetLocale
defines thegetLocale()
function that messages use to determine the localeoverwriteSetLocale
defines thesetLocale()
function that apps call to change the locale
Because the client and server have separate Paraglide runtimes, you will need to define these behaviours separately on the client and server.
The steps are usually the same, irrespective of the strategy and framework you use:
- Use
overwriteGetLocale()
function that reads the locale from a cookie, HTTP header, or i18n routing. - Handle any side effects of changing the locale and trigger a re-render in your application via
overwriteSetLocale()
(for many apps, this may only be required on the client side).
Read the architecture documentation to learn more about's Paraglide's inner workings.
Dynamically resolving the locale (cookies, http headers, i18n routing, etc.)
To dynamically resolve the locale, pass a function that returns the locale to getLocale()
. You can use this to get the locale from the documentElement.lang
attribute, a cookie, a locale route, or any other source.
On the server, you might determine the locale from a cookie, a locale route, a http header, or anything else. When calling overwriteGetLocale()
on the server, you need to be mindful of race conditions caused when multiple requests come in at the same time with different locales.
To avoid this, use AsyncLocaleStorage
in Node, or its equivalent for other server-side JS runtimes.