> ## Documentation Index
> Fetch the complete documentation index at: https://docs-staging-quickstart-revamp.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

## 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.

<table class="table">
  <thead>
    <tr>
      <th><strong>Language</strong></th>
      <th><strong>Code</strong></th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Albanian</td>
      <td><code>sq</code></td>
    </tr>

    <tr>
      <td>Amharic</td>
      <td><code>am</code></td>
    </tr>

    <tr>
      <td>Arabic\*</td>
      <td><code>ar</code></td>
    </tr>

    <tr>
      <td>Arabic (Egypt)\*</td>
      <td><code>ar-EG</code></td>
    </tr>

    <tr>
      <td>Arabic (Saudi Arabia)\*</td>
      <td><code>ar-SA</code></td>
    </tr>

    <tr>
      <td>Armenia</td>
      <td><code>hy</code></td>
    </tr>

    <tr>
      <td>Azerbaijani</td>
      <td><code>az</code></td>
    </tr>

    <tr>
      <td>Basque</td>
      <td><code>eu-ES</code></td>
    </tr>

    <tr>
      <td>Bengali</td>
      <td><code>bn</code></td>
    </tr>

    <tr>
      <td>Bosnian</td>
      <td><code>bs</code></td>
    </tr>

    <tr>
      <td>Bulgarian</td>
      <td><code>bg</code></td>
    </tr>

    <tr>
      <td>Catalan</td>
      <td><code>ca-ES</code></td>
    </tr>

    <tr>
      <td>Chinese - Hong Kong</td>
      <td><code>zh-HK</code></td>
    </tr>

    <tr>
      <td>Chinese - Simplified</td>
      <td><code>zh-CN</code></td>
    </tr>

    <tr>
      <td>Chinese - Traditional</td>
      <td><code>zh-TW</code></td>
    </tr>

    <tr>
      <td>Croatian</td>
      <td><code>hr</code></td>
    </tr>

    <tr>
      <td>Czech</td>
      <td><code>cs</code></td>
    </tr>

    <tr>
      <td>Danish</td>
      <td><code>da</code></td>
    </tr>

    <tr>
      <td>Dutch</td>
      <td><code>nl</code></td>
    </tr>

    <tr>
      <td>English</td>
      <td><code>en</code></td>
    </tr>

    <tr>
      <td>English - Canada</td>
      <td><code>en-CA</code></td>
    </tr>

    <tr>
      <td>Estonian</td>
      <td><code>et</code></td>
    </tr>

    <tr>
      <td>Farsi (Persian)\*</td>
      <td><code>fa</code></td>
    </tr>

    <tr>
      <td>Finnish</td>
      <td><code>fi</code></td>
    </tr>

    <tr>
      <td>French</td>
      <td><code>fr-FR</code></td>
    </tr>

    <tr>
      <td>French - Canada</td>
      <td><code>fr-CA</code></td>
    </tr>

    <tr>
      <td>Galician</td>
      <td><code>gl-ES</code></td>
    </tr>

    <tr>
      <td>Georgian</td>
      <td><code>ka</code></td>
    </tr>

    <tr>
      <td>German</td>
      <td><code>de</code></td>
    </tr>

    <tr>
      <td>Greek</td>
      <td><code>el</code></td>
    </tr>

    <tr>
      <td>Gujrati</td>
      <td><code>gu</code></td>
    </tr>

    <tr>
      <td>Hebrew\*</td>
      <td><code>he</code></td>
    </tr>

    <tr>
      <td>Hindi</td>
      <td><code>hi</code></td>
    </tr>

    <tr>
      <td>Hungarian</td>
      <td><code>hu</code></td>
    </tr>

    <tr>
      <td>Icelandic</td>
      <td><code>is</code></td>
    </tr>

    <tr>
      <td>Indonesian</td>
      <td><code>id</code></td>
    </tr>

    <tr>
      <td>Italian</td>
      <td><code>it</code></td>
    </tr>

    <tr>
      <td>Japanese</td>
      <td><code>ja</code></td>
    </tr>

    <tr>
      <td>Kannada</td>
      <td><code>kn</code></td>
    </tr>

    <tr>
      <td>Korean</td>
      <td><code>ko</code></td>
    </tr>

    <tr>
      <td>Latvian</td>
      <td><code>lv</code></td>
    </tr>

    <tr>
      <td>Lithuanian</td>
      <td><code>lt</code></td>
    </tr>

    <tr>
      <td>Macedonian</td>
      <td><code>mk</code></td>
    </tr>

    <tr>
      <td>Malay</td>
      <td><code>ms</code></td>
    </tr>

    <tr>
      <td>Malayalam</td>
      <td><code>ml</code></td>
    </tr>

    <tr>
      <td>Marathi</td>
      <td><code>mr</code></td>
    </tr>

    <tr>
      <td>Mongolian</td>
      <td><code>mn</code></td>
    </tr>

    <tr>
      <td>Montenegrine</td>
      <td><code>cnr</code></td>
    </tr>

    <tr>
      <td>Myanmar</td>
      <td><code>my</code></td>
    </tr>

    <tr>
      <td>Norwegian</td>
      <td><code>no</code></td>
    </tr>

    <tr>
      <td>Norwegian - Bokmål</td>
      <td><code>nb</code></td>
    </tr>

    <tr>
      <td>Norwegian - Nynorsk</td>
      <td><code>nn</code></td>
    </tr>

    <tr>
      <td>Polish</td>
      <td><code>pl</code></td>
    </tr>

    <tr>
      <td>Portuguese - Brazil</td>
      <td><code>pt-BR</code></td>
    </tr>

    <tr>
      <td>Portuguese - Portugal</td>
      <td><code>pt-PT</code></td>
    </tr>

    <tr>
      <td>Punjabi</td>
      <td><code>pa</code></td>
    </tr>

    <tr>
      <td>Romanian</td>
      <td><code>ro</code></td>
    </tr>

    <tr>
      <td>Russian</td>
      <td><code>ru</code></td>
    </tr>

    <tr>
      <td>Serbian</td>
      <td><code>sr</code></td>
    </tr>

    <tr>
      <td>Slovak</td>
      <td><code>sk</code></td>
    </tr>

    <tr>
      <td>Slovenian</td>
      <td><code>sl</code></td>
    </tr>

    <tr>
      <td>Somali</td>
      <td><code>so</code></td>
    </tr>

    <tr>
      <td>Spanish</td>
      <td><code>es</code></td>
    </tr>

    <tr>
      <td>Spanish - Argentina</td>
      <td><code>es-AR</code></td>
    </tr>

    <tr>
      <td>Spanish - Latin America</td>
      <td><code>es-419</code></td>
    </tr>

    <tr>
      <td>Spanish - Mexico</td>
      <td><code>es-MX</code></td>
    </tr>

    <tr>
      <td>Swahili</td>
      <td><code>sw</code></td>
    </tr>

    <tr>
      <td>Swedish</td>
      <td><code>sv</code></td>
    </tr>

    <tr>
      <td>Tagalog</td>
      <td><code>tl</code></td>
    </tr>

    <tr>
      <td>Tamazight</td>
      <td><code>zgh</code></td>
    </tr>

    <tr>
      <td>Tamil</td>
      <td><code>ta</code></td>
    </tr>

    <tr>
      <td>Telugu</td>
      <td><code>te</code></td>
    </tr>

    <tr>
      <td>Thai</td>
      <td><code>th</code></td>
    </tr>

    <tr>
      <td>Turkish</td>
      <td><code>tr</code></td>
    </tr>

    <tr>
      <td>Ukrainian</td>
      <td><code>uk</code></td>
    </tr>

    <tr>
      <td>Urdu\*</td>
      <td><code>ur</code></td>
    </tr>

    <tr>
      <td>Vietnamese</td>
      <td><code>vi</code></td>
    </tr>

    <tr>
      <td>Welsh</td>
      <td><code>cy</code></td>
    </tr>
  </tbody>
</table>

### Language selection

The language to render the pages will be selected based on:

* The languages supported by Auth0, which are listed above.
* The list of languages configured in the 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. The pages will be rendered in this language if it is allowed by the settings above. If not, pages will be rendered in the default language.

To add a language that's not listed above, use the <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
{
  "enabled_locales": [
    "en","he"
  ]
}
```

After it's 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 Tenant Settings endpoint](https://auth0.com/docs/api/management/v2#!/Tenants/patch_settings). The first language in the list will be the default one.

<CodeGroup>
  ```bash cURL lines
  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# lines
  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 lines expandable
  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 lines
  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 lines
  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);
  });
  ```

  ```obj-c Obj-C lines expandable
  #import <Foundation/Foundation.h>

  NSDictionary *headers = @{ @"content-type": @"application/json",
                             @"authorization": @"Bearer API2_ACCESS_TOKEN" };
  NSDictionary *parameters = @{ @"enabled_locales": @[ @"en", @"es" ] };

  NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/tenants/settings"]
                                                         cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                     timeoutInterval:10.0];
  [request setHTTPMethod:@"PATCH"];
  [request setAllHTTPHeaderFields:headers];
  [request setHTTPBody:postData];

  NSURLSession *session = [NSURLSession sharedSession];
  NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                              completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                  if (error) {
                                                      NSLog(@"%@", error);
                                                  } else {
                                                      NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                      NSLog(@"%@", httpResponse);
                                                  }
                                              }];
  [dataTask resume];
  ```

  ```php PHP lines expandable
  $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 lines
  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 lines
  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
  ```

  ```swift Swift lines expandable
  import Foundation

  let headers = [
    "content-type": "application/json",
    "authorization": "Bearer API2_ACCESS_TOKEN"
  ]
  let parameters = ["enabled_locales": ["en", "es"]] as [String : Any]

  let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

  let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/tenants/settings")! as URL,
                                          cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
  request.httpMethod = "PATCH"
  request.allHTTPHeaderFields = headers
  request.httpBody = postData as Data

  let session = URLSession.shared
  let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
    if (error != nil) {
      print(error)
    } else {
      let httpResponse = response as? HTTPURLResponse
      print(httpResponse)
    }
  })

  dataTask.resume()
  ```
</CodeGroup>

### Right-to-left languages

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Right-to-left text is currently in Early Access. To request this feature, [contact Auth0 Support](https://support.auth0.com/), and to learn more about Auth0's product release cycle, read [Product release stages](/docs/troubleshoot/product-lifecycle/product-release-stages).
</Callout>

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
{% assign resolved_dir = dir | default: "auto" %}
<html lang="{{locale}}" dir="{{resolved_dir}}">
```

Go to [Tenant Settings > Advanced](https://manage.auth0.com/#/tenant/advanced) and ensure the toggle shown below is disabled, then test any RtL languages in a dev environment with a custom page template before using them in production. To learn more, read [Customize Universal Login Page Templates](/docs/customize/login-pages/universal-login/customize-templates).

<Frame>
  <img src="https://mintcdn.com/docs-staging-quickstart-revamp/8NcGJxT9i9TCdLH_/images/screenshot.png?fit=max&auto=format&n=8NcGJxT9i9TCdLH_&q=85&s=095f773f8409b068947a00652975365c" alt="A photo of the right-to-left toggle in the Auth0 Tenant Settings." width="1064" height="362" data-path="images/screenshot.png" />
</Frame>

### 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’s not available in <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 <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 ULP renders the HTML `lang` attribute for the language code `fr-FR` as `fr`.
* The ULP renders the HTML `lang` attribute for the language code `pt-PT` as `pt`.

## Classic Login localization

In the Classic Login experience, localization is done using our 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 [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 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)
