# Theme Localization

Learn about how FusionAuth Themes work with localization.

> For the index of this section of the site, see [llms.txt](https://fusionauth.io/docs/llms.txt)

The FusionAuth theme can be localized to better server your end users. In each theme you may specify one to many language-specific message bundles to translate text rendered in a theme into a user's preferred language.

If you're just looking into localizing your theme, take a look at our [community provided and maintained message bundles](https://github.com/FusionAuth/fusionauth-localization).

You may also want to review our [localization and internationalization documentation](https://fusionauth.io/docs/get-started/core-concepts/localization-and-internationalization.md).

## Messages

In the Messages tab of your theme editor you may specify one to many languages. Once you have specified a key and value the key may be used in any template to display a localized string.

Consider the following message bundle and theme usage example with English and German messages defined.

English

```properties
greeting=Good day
```

German

```properties
greeting=Guten Tag
optional-greeting=Mitmensch
```

Template

```html
<p>${theme.message('greeting')} ${theme.optionalMessage('optional-greeting')}</p>
```

If I have selected German as my locale, I will be greeted with `Guten Tag Mitmensch` rendered on the page.

If I have English selected I will instead find the greeting `Good day optional-greeting`.

Note

Prior to version `1.53.0`, the behavior of `theme.message` and `theme.optionalMessage` differed in that an exception would be thrown if you used `theme.message` and the message key could not be found. While a missing key should be a development time issue, returning the key should provide a better development experience than throwing an exception.

Beginning in version `1.53.0` there is no difference in behavior between these two methods and you should prefer `theme.message`.

The following example that demonstrates the difference in behavior between `theme.message` and `theme.optionalMessage` only pertains to versions of FusionAuth prior to `1.53.0.`

The behavior differs between `theme.message` and `theme.optionalMessage` only when the key doesn't exist in any of the messages files, including the default one.

When there is no suitable key found and `theme.message` is used, an exception is thrown and the template fails to completely render. When there is no suitable key found and `theme.optionalMessage` is used, the key value is returned: `optional-message` in the example above.

Here's an example of a template that will render for a user with a German locale but fail for a user with an English locale, because `message` fails when there is no key found:

Template Which Will Fail For Users With an English Locale

```html
<p>${theme.message('optional-greeting')}</p>
```

Here's a Freemarker function which returns an empty string when there is no value found for an optional message:

Freemarker Function to Return the Empty String When No Value is Found

```ftl
[#function getOptionalMessage key=""]
  [#if "${theme.optionalMessage(key)}" == "${key}"]
    [#return "" /]
  [/#if]
  [#return theme.optionalMessage(key) /]
[/#function]
```

If you add this to your `_helpers.ftl` file, you can call it like this:

Calling getOptionalMessage

```ftl
[@helpers.getOptionalMessage key="optional-greeting" /]
```

## Locale

The locale is determined by the [locale](https://fusionauth.io/docs/reference/data-types.md#locales) value. The locale is resolved on each request using the following precedence:

1.  The `locale` request parameter, if present, on the HTTP request (e.g. `locale=fr`). This is useful if you already know the user's preferred locale prior to redirecting them to FusionAuth to complete authentication.
2.  The user selects a language during login using the locale selector or there is a `fusionauth.locale` cookie present.
3.  The HTTP `Accept-Language` header, if present on the HTTP request.
4.  The system default locale, as determined by the underlying operating system.

Note

The user's **preferredLanguages** settings are not used to select a locale for the hosted login pages.

## Identity Provider Login Buttons

The button text displayed in the login pages for identity providers such as Google, Facebook or SAML, is retrieved from the identity provider configuration. The [API documentation](https://fusionauth.io/docs/apis/identity-providers/google.md) documents how to set and retrieve this value, which is `identityProvider.buttonText`.

This text is used in the default theme like so:

Login Template Excerpt

```html
<div class="text">${identityProvider.lookupButtonText(clientId)?trim}</div>
```

The `buttonText` value stored in the identity provider configuration cannot be localized.

However, you can replace this line in the theme template to pull a localized value from the messages bundle.

First, add the translated text to all messages bundles, including the default bundle:

English

```properties
google-login=Login With Google
```

German

```properties
google-login=Mit Google Einloggen
```

Then, update the relevant templates to display the localized text. Here's an excerpt of an updated login page:

Updated Login Template Excerpt

```html
<div class="text">${theme.message('google-login')}</div>
```

## OAuth Scope Consent Prompt

> **PLAN:** This feature requires [at least an Essentials plan](https://fusionauth.io/docs/get-started/core-concepts/plans-features.md#essentials-features).

Available since `1.50.0`

The `OAuth2 consent` template at `/oauth2/consent` has an expanded message lookup policy in order to allow customizing scope consent messages and details without requiring a separate theme.

OAuth scope consent messages and details follow an ordered theme message lookup policy from most-to least-specific. The theme will render the first option that contains a value using the `OAuth2 consent` template's `resolveScopeMessaging` function. For an example `data:read` scope attached to an Application with the Id `a2afb0f5-eb2d-4d8f-a55d-05e978e95fda`, below the options for overriding the message are listed from most to least preferred.

Any `:` or `=` characters in the scope name need to be escaped in the theme messages definition.

```properties
# Most preferred: Override at the application level using the application Id
[{application}a2afb0f5-eb2d-4d8f-a55d-05e978e95fda]{scope-message}data\:read=Application-specific consent message
[{application}a2afb0f5-eb2d-4d8f-a55d-05e978e95fda]{scope-detail}data\:read=Application-specific consent detail

# Override at the tenant level using the tenant Id
[{tenant}e122574f-6ec5-4399-b6b2-04ede9796380]{scope-message}data\:read=Tenant-specific consent message
[{tenant}e122574f-6ec5-4399-b6b2-04ede9796380]{scope-detail}data\:read=Tenant-specific consent detail

# Least preferred: Override at the theme level
{scope-message}data\:read=Themed consent message
{scope-detail}data\:read=Themed consent detail
```

If a themed message cannot be found using the given application, tenant, or theme, the **scope.defaultConsentMessage** and **scope.defaultConsentDetail** values will be used. If **scope.defaultConsentMessage** is empty, the **scope.name** will be used as the message. If **scope.defaultConsentDetail** is empty, no detail value will be displayed.

Related

[Get Started Localization and Internationalization Learn about localization, translations and internationalization in FusionAuth. internationalizationi18nlocale](https://fusionauth.io/docs/get-started/core-concepts/localization-and-internationalization.md)
---

## Other pages in Theme

> For the full index of this section, see [Theme](https://fusionauth.io/docs/llms-theme.txt).

- [Advanced Themes](https://fusionauth.io/docs/theme/advanced-themes.md): Learn how to theme and the FusionAuth login pages (including forgot password, two-factor authentication and others).
- [Application-Specific Themes](https://fusionauth.io/docs/theme/application-specific-themes.md): Learn how to specify a theme for a certain application.
- [Simple Themes](https://fusionauth.io/docs/theme/simple-theme-editor.md): Quickly and easily style FusionAuth with no code.
