> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-fix-docs-5525.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Describes the languages you can choose to localize your login pages.

# Universal Login Internationalization

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

## Universal Login localization

The <Tooltip tip="Universal Login: Your application redirects to Universal Login, hosted on Auth0's Authorization Server, to verify a user's identity." cta="View Glossary" href="/docs/glossary?term=Universal+Login">Universal Login</Tooltip> experience is localized to the following languages. Entries marked with an asterisk are read right to left.

| Language                | Code     |
| ----------------------- | -------- |
| Albanian                | `sq`     |
| Amharic                 | `am`     |
| Arabic\*                | `ar`     |
| Arabic (Egypt)\*        | `ar-EG`  |
| Arabic (Saudi Arabia)\* | `ar-SA`  |
| Armenia                 | `hy`     |
| Azerbaijani             | `az`     |
| Basque                  | `eu-ES`  |
| Bengali                 | `bn`     |
| Bosnian                 | `bs`     |
| Bulgarian               | `bg`     |
| Catalan                 | `ca-ES`  |
| Chinese - Hong Kong     | `zh-HK`  |
| Chinese - Simplified    | `zh-CN`  |
| Chinese - Traditional   | `zh-TW`  |
| Croatian                | `hr`     |
| Czech                   | `cs`     |
| Danish                  | `da`     |
| Dutch                   | `nl`     |
| English                 | `en`     |
| English - Canada        | `en-CA`  |
| Estonian                | `et`     |
| Farsi (Persian)\*       | `fa`     |
| Finnish                 | `fi`     |
| French                  | `fr-FR`  |
| French - Canada         | `fr-CA`  |
| Galician                | `gl-ES`  |
| Georgian                | `ka`     |
| German                  | `de`     |
| Greek                   | `el`     |
| Gujrati                 | `gu`     |
| Hebrew\*                | `he`     |
| Hindi                   | `hi`     |
| Hungarian               | `hu`     |
| Icelandic               | `is`     |
| Indonesian              | `id`     |
| Italian                 | `it`     |
| Japanese                | `ja`     |
| Kannada                 | `kn`     |
| Korean                  | `ko`     |
| Latvian                 | `lv`     |
| Lithuanian              | `lt`     |
| Macedonian              | `mk`     |
| Malay                   | `ms`     |
| Malayalam               | `ml`     |
| Marathi                 | `mr`     |
| Mongolian               | `mn`     |
| Montenegrine            | `cnr`    |
| Myanmar                 | `my`     |
| Norwegian               | `no`     |
| Norwegian - Bokmål      | `nb`     |
| Norwegian - Nynorsk     | `nn`     |
| Polish                  | `pl`     |
| Portuguese - Brazil     | `pt-BR`  |
| Portuguese - Portugal   | `pt-PT`  |
| Punjabi                 | `pa`     |
| Romanian                | `ro`     |
| Russian                 | `ru`     |
| Serbian                 | `sr`     |
| Slovak                  | `sk`     |
| Slovenian               | `sl`     |
| Somali                  | `so`     |
| Spanish                 | `es`     |
| Spanish - Argentina     | `es-AR`  |
| Spanish - Latin America | `es-419` |
| Spanish - Mexico        | `es-MX`  |
| Swahili                 | `sw`     |
| Swedish                 | `sv`     |
| Tagalog                 | `tl`     |
| Tamazight               | `zgh`    |
| Tamil                   | `ta`     |
| Telugu                  | `te`     |
| Thai                    | `th`     |
| Turkish                 | `tr`     |
| Ukrainian               | `uk`     |
| Urdu\*                  | `ur`     |
| Vietnamese              | `vi`     |
| Welsh                   | `cy`     |

### Language selection

Auth0 selects the language to render the pages based on:

* The languages supported by Auth0, which are listed above
* The list of languages configured in the Auth0 Dashboard's [**Tenant Settings**](https://manage.auth0.com/#/tenant) section, where you can select the languages your tenant supports and select a default one. By default, the list has only English selected, but you can select the ones you need.
* The value of the `ui_locales` parameter sent to the [Authorization Request endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest), which can be used to constrain the language list for an application or session. You can provide a space-delimited list of locales. The first locale on the list must match the enabled locale in your tenant to reflect in the UI.
* The `Accept-Language` HTTP header sent by the browser, Auth0 renders the pages in this language if it is allowed by the settings above. If not, the pages render in the default language.

Use the Auth0 <Tooltip tip="Management API: A product to allow customers to perform administrative tasks." cta="View Glossary" href="/docs/glossary?term=Management+API">Management API</Tooltip> to make a `PATCH` call to the [Tenants endpoint](https://auth0.com/docs/api/management/v2/tenants/patch-settings) with the following body, replacing `he` with the language code you want to add:

```json lines theme={null}
{
  "enabled_locales": [
    "en","he"
  ]
}
```

After it is added, specify the language in the`ui_locales` query parameter of the login request.

You can also specify the enabled languages for the tenant via the Management API using the [Update Tenants endpoint](https://auth0.com/docs/api/management/v2#!/Tenants/patch_settings). The default language is the first one in the list.

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/tenants/settings' \
    --header 'authorization: Bearer API2_ACCESS_TOKEN' \
    --header 'content-type: application/json' \
    --data '{ "enabled_locales" : [ "en", "es"]}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/tenants/settings");
  var request = new RestRequest(Method.PATCH);
  request.AddHeader("content-type", "application/json");
  request.AddHeader("authorization", "Bearer API2_ACCESS_TOKEN");
  request.AddParameter("application/json", "{ "enabled_locales" : [ "en", "es"]}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/api/v2/tenants/settings"

  	payload := strings.NewReader("{ "enabled_locales" : [ "en", "es"]}")

  	req, _ := http.NewRequest("PATCH", url, payload)

  	req.Header.Add("content-type", "application/json")
  	req.Header.Add("authorization", "Bearer API2_ACCESS_TOKEN")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.patch("https://{yourDomain}/api/v2/tenants/settings")
    .header("content-type", "application/json")
    .header("authorization", "Bearer API2_ACCESS_TOKEN")
    .body("{ "enabled_locales" : [ "en", "es"]}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'PATCH',
    url: 'https://{yourDomain}/api/v2/tenants/settings',
    headers: {'content-type': 'application/json', authorization: 'Bearer API2_ACCESS_TOKEN'},
    data: {enabled_locales: ['en', 'es']}
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/tenants/settings",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_POSTFIELDS => "{ "enabled_locales" : [ "en", "es"]}",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer API2_ACCESS_TOKEN",
      "content-type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{ "enabled_locales" : [ "en", "es"]}"

  headers = {
      'content-type': "application/json",
      'authorization': "Bearer API2_ACCESS_TOKEN"
      }

  conn.request("PATCH", "/{yourDomain}/api/v2/tenants/settings", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/tenants/settings")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  request = Net::HTTP::Patch.new(url)
  request["content-type"] = 'application/json'
  request["authorization"] = 'Bearer API2_ACCESS_TOKEN'
  request.body = "{ "enabled_locales" : [ "en", "es"]}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

### Right-to-left languages

<Warning>
  Right-to-left language support is available in Early Access. To request this feature, [contact Auth0 Support](https://support.auth0.com/).  By using this feature, you agree to the applicable Free Trial terms in Okta’s [Master Subscription Agreement](https://www.okta.com/legal/). To learn more about Auth0's product release cycle, read [Product release stages](/docs/troubleshoot/product-lifecycle/product-release-stages).
</Warning>

Right-to-left (RtL) language support allows your tenant to display Arabic (standard, Egyptian, and Saudi Arabian), Persian, Hebrew, and Urdu text. Tenants that use RtL text must be [WCAG 2.2 AA compliant](/docs/authenticate/login/auth0-universal-login#accessibility), and if your tenant uses page templates, you must update the HTML tag to include the `dir` element.

```liquid lines theme={null}
{% assign resolved_dir = dir | default: "auto" %}
<html lang="{{locale}}" dir="{{resolved_dir}}">
```

### Limitations

* The `ui_locales` parameter can only be used in <Tooltip tip="OAuth 2.0: Authorization framework that defines authorization protocols and workflows." cta="View Glossary" href="/docs/glossary?term=OAuth">OAuth</Tooltip> flows, as it is not available with Security Assertion Markup Language <Tooltip tip="OAuth 2.0: Authorization framework that defines authorization protocols and workflows." cta="View Glossary" href="/docs/glossary?term=SAML">(SAML)</Tooltip> or WS-Federation.
* The `ui_locales` parameter is not forwarded to upstream identity providers <Tooltip tip="Identity Provider (IdP): Service that stores and manages digital identities." cta="View Glossary" href="/docs/glossary?term=IdPs">IdPs</Tooltip>. To learn more about passing parameters to IdPs, read [Pass Parameters to Identity Providers](/docs/authenticate/identity-providers/pass-parameters-to-idps).
* It is not possible to localize the scopes in the Consent page.

### Known issues

* The Universal Login Page renders the HTML `lang` attribute for the language code `fr-FR` as `fr`.
* The Universal Login Page renders the HTML `lang` attribute for the language code `pt-PT` as `pt`.

## Classic Login localization

In the Classic Login experience, localization uses Auth0 JavaScript widgets for [login](/docs/customize/internationalization-and-localization/lock-internationalization), the [password reset page](/docs/customize/login-pages/classic-login/customize-password-reset-page) and [password policies](/docs/customize/internationalization-and-localization/password-options-translation).

The [Multi-factor authentication (MFA) page](/docs/secure/multi-factor-authentication/customize-mfa/customize-mfa-classic-login) by default uses the Auth0 <Tooltip tip="Multi-factor authentication (MFA): User authentication process that uses a factor in addition to username and password such as a code via SMS." cta="View Glossary" href="/docs/glossary?term=MFA">MFA</Tooltip> Widget, which cannot be localized. You can create localized versions by using [guardian.js](https://github.com/auth0/auth0-guardian.js).

It is not possible to localize the [Consent](/docs/customize/login-pages/customize-consent-prompts) page.

## Learn more

* [Customize Universal Login Page Templates](/docs/customize/login-pages/universal-login/customize-templates)
* [Customize Classic Login Pages with Lock or SDK](/docs/customize/login-pages/classic-login/customize-with-lock-sdk)
