Docs

Localization prop (experimental)

Warning

This feature is currently experimental and may not behave as expected. If you encounter any issues, please reach out to support with as much detail as possible.

Clerk offers the ability to override the strings for all of the elements in each of the Clerk components. This allows you to provide localization for your users or change the wording to suit your brand.

@clerk/localizations

The @clerk/localizations package contains predefined localizations for the Clerk components.

Languages

Clerk currently supports the following languages with English as the default:

English nameLanguage tag (BCP 47)Key
Arabic (Saudi)ar-SAarSA
Belarusbe-BYbeBY
Bulgarianbg-BGbgBG
Catalanca-EScaES
Czechcs-CZcsCZ
Danishda-DKdaDK
Germande-DEdeDE
Greekel-GRelGR
English (US)en-USenUS
Spanishes-ESesES
Spanish (Mexico)es-MXesMX
Finnishfi-FIfiFI
Frenchfr-FRfrFR
Hebrewhe-ILheIL
Croatianhr-HRhrHR
Hungarianhu-HUhuHU
Icelandicis-ISisIS
Italianit-ITitIT
Japaneseja-JPjaJP
Koreanko-KRkoKR
Mongolianmn-MNmnMN
Norwegiannb-NOnbNO
Dutchnl-BEnlBE
Dutchnl-NLnlNL
Polishpl-PLplPL
Portuguese (BR)pt-BRptBR
Portuguese (PT)pt-PTptPT
Romanianro-ROroRO
Russianru-RUruRU
Slovaksk-SKskSK
Swedishsv-SEsvSE
Thaith-THthTH
Turkishtr-TRtrTR
Ukrainianuk-UAukUA
Vietnamesevi-VNviVN
Chinese (Simplified)zh-CNzhCN
Chinese (Traditional)zh-TWzhTW

Usage

Caution

The localizations will only update the text in the Clerk components used in your application. The hosted Clerk Account Portal will remain in English.

To get started, install the @clerk/localizations package.

terminal
npm install @clerk/localizations
terminal
yarn add @clerk/localizations
terminal
pnpm add @clerk/localizations

Once the @clerk/localizations package is installed, you can import the localizations you need by removing the "-" from the locale.

In the following example, the fr-FR locale is imported as frFR. The imported localization is then passed to the localization prop on the <ClerkProvider>.

app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'
import './globals.css'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider localization={frFR}>
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}
_app.tsx
import { ClerkProvider } from '@clerk/nextjs'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    // Add the localization prop to the ClerkProvider
    <ClerkProvider localization={frFR} {...pageProps}>
      <Component {...pageProps} />
    </ClerkProvider>
  )
}

export default MyApp

In the following example, the fr-FR locale is imported as frFR. The imported localization is then passed to the localization prop in the ClerkApp options.

app/root.tsx
import type { MetaFunction, LoaderFunction } from '@remix-run/node'
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'
import { rootAuthLoader } from '@clerk/remix/ssr.server'
// Import ClerkApp
import { ClerkApp } from '@clerk/remix'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'

export const meta: MetaFunction = () => [
  {
    charset: 'utf-8',
    title: 'New Remix App',
    viewport: 'width=device-width,initial-scale=1',
  },
]

export const loader: LoaderFunction = (args) => rootAuthLoader(args)

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  )
}

function App() {
  return <Outlet />
}

export default ClerkApp(App, {
  localization: frFR,
})
astro.config.mjs
import clerk from '@clerk/astro'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'

export default defineConfig({
  integrations: [
    clerk({
      localization: frFR,
    }),
  ],
})

In the following example, the fr-FR locale is imported as frFR. The imported localization is then passed to the localization prop on the clerk.load() method.

Use the following tabs to view the code necessary for each file.

main.js
import { Clerk } from '@clerk/clerk-js'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'

const clerkPubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

const clerk = new Clerk(clerkPubKey)
await clerk.load({
  localization: frFR,
})

if (clerk.user) {
  document.getElementById('app').innerHTML = `
      <div id="user-button"></div>
    `

  const userButtonDiv = document.getElementById('user-button')

  clerk.mountUserButton(userButtonDiv)
} else {
  document.getElementById('app').innerHTML = `
      <div id="sign-in"></div>
    `

  const signInDiv = document.getElementById('sign-in')

  clerk.mountSignIn(signInDiv)
}
index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Clerk + JavaScript App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="main.js" async crossorigin="anonymous"></script>
  </body>
</html>

Adding or updating a localization

Our localizations are customer-sourced and we encourage customers to add or update localizations. To do so, follow these steps:

  1. Fork the https://github.com/clerk/javascript/ repo.
  2. Clone it locally to edit it.
  3. Review our Contributing guide.
  4. If you are updating an existing localization locate the file in packages/localizations/src
  5. If you are adding a new language, copy the en-US.ts file and name it according to your language. The naming is the abbreviated language-region. For example, for French in Canada, it would be fr-CA.ts.
  6. Go through the file and edit the entries.
  7. If you are adding a new localization, add the language to the packages/localizations/src/index.ts file.
  8. Commit your changes to git and push them to your fork. Create a Pull Request from your fork to Clerk's repo against the main branch. We will review and either approve or ask for updates.

Custom localizations

You can also provide your own localizations for the Clerk components. This is useful if you want to provide limited or quick localization for a language that Clerk doesn't currently support or if you want to change the wording to suit your brand.

Usage

app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'
import './globals.css'
// fr-FR locale is imported as frFR
import { frFR } from '@clerk/localizations'

const localization = {
  socialButtonsBlockButton: 'Sign In with {{provider|titleize}}',
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider localization={localization}>
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}

To find the key for your translation (like the socialButtonsBlockButton from the code example below), open up our English localization file. Search the file for the term that you want to customize.

For example, if you want to change the 'to continue to' string from the <SignIn /> and <SignUp /> components, you would search for 'to continue to'. You will find several instances of this. Some of those are in the the following signUp object:

signUp: {
  start: {
    title: 'Create your account',
    subtitle: 'to continue to {{applicationName}}',
    actionText: 'Have an account?',
    actionLink: 'Sign in',
  },
  emailLink: {
    title: 'Verify your email',
    subtitle: 'to continue to {{applicationName}}',
    formTitle: 'Verification link',
    formSubtitle: 'Use the verification link sent to your email address',
    resendButton: "Didn't receive a link? Resend",
    verified: {
      title: 'Successfully signed up',
    },
    loading: {
      title: 'Signing up...',
    },
    verifiedSwitchTab: {
      title: 'Successfully verified email',
      subtitle: 'Return to the newly opened tab to continue',
      subtitleNewTab: 'Return to previous tab to continue',
    },
  },
  emailCode: {
    title: 'Verify your email',
    subtitle: 'to continue to {{applicationName}}',
    formTitle: 'Verification code',
    formSubtitle: 'Enter the verification code sent to your email address',
    resendButton: "Didn't receive a code? Resend",
  },
  phoneCode: {
    title: 'Verify your phone',
    subtitle: 'to continue to {{applicationName}}',
    formTitle: 'Verification code',
    formSubtitle: 'Enter the verification code sent to your phone number',
    resendButton: "Didn't receive a code? Resend",
  },
  continue: {
    title: 'Fill in missing fields',
    subtitle: 'to continue to {{applicationName}}',
    actionText: 'Have an account?',
    actionLink: 'Sign in',
  },
},

If you want to customize multiple entries from the <SignUp /> component, the procedure would resemble the following:

const localization = {
  signUp: {
    start: {
      subtitle: 'to access {{applicationName}}',
    },
    emailCode: {
      subtitle: 'to access {{applicationName}}',
    },
  },
}

Feedback

What did you think of this content?

Last updated on