Skip to main content

HTML Customization

Translations

Where the copy comes from

The script tag bundles English only. Other languages come from outside the bundle, and which source wins depends on the mode:

ModeWhere the copy comes from
Hosted, with data-backend-urlYour Inth project. The backend picks the language from the visitor's browser, or from data-language, and sends its copy with the policy.
Manifest, including a tag loaded from your backend's /c15t.jsThe manifest's translations for the visitor's language.
OfflineEnglish, or the language and messages you set in i18n.

In every mode, your i18n.messages for the language in use override that copy key by key. Text you set in ui.banner, such as title or acceptButtonText, replaces the translated text for all languages.

Pick the language

In hosted and manifest mode, c15t follows the visitor's browser language. To force one, add data-language to the tag:

<script
  src="https://your-project.inth.app/c15t.js"
  data-language="de"
  defer
></script>

A multilingual site can print each page's language into the tag, for example from the lang attribute your CMS already writes on <html>.

To switch after load, call c15t.setLanguage('fr'). With a backend, c15t asks the backend for French copy and re-renders the banner and dialog. In offline mode, data-language and c15t.setLanguage() switch to a language that has copy in the bundle or in i18n.messages. A language with no copy shows the default copy. See add a language in offline mode.

Change the wording

Set i18n.messages in a queued config call. You only list the keys you change; the rest keep their default text:

<script>
  window.c15t = window.c15t || [];
  c15t.push(['config', {
    i18n: {
      locale: 'en',
      messages: {
        en: {
          common: { acceptAll: 'Accept', rejectAll: 'Reject optional' },
          cookieBanner: { title: 'Cookies on this site' },
        },
      },
    },
  }]);
</script>

With a backend, the /init response or the manifest carries your Inth project's copy for the visitor's language. Your i18n.messages for that language override it key by key, and keys you leave out keep the project's copy. c15t looks for the exact language first, then the primary language, so a visitor on de-AT gets your de messages. Messages for other languages are not applied.

A key only overrides the backend when your text differs from c15t's built-in wording for that language. So passing the stock bundles from @c15t/translations/all to enable languages keeps edits made in your Inth project visible, while a key you actually reworded stays pinned in code. Core bundles only English; for other languages, import @c15t/translations/all so c15t can recognize its stock wording.

Add a language in offline mode

Load c15t.offline.js without data-backend-url. Queue your i18n configuration before that tag. Offline mode shows the language named in i18n.locale, built from your messages over the English defaults:

<script>
  window.c15t = window.c15t || [];
  c15t.push(['config', {
    i18n: {
      locale: 'de',
      messages: {
        de: {
          common: {
            acceptAll: 'Alle akzeptieren',
            rejectAll: 'Alle ablehnen',
            customize: 'Anpassen',
            save: 'Einstellungen speichern',
            acknowledge: 'OK',
          },
          cookieBanner: {
            title: 'Wir respektieren Ihre Privatsphäre',
            description: 'Diese Website verwendet Cookies, um Ihr Erlebnis zu verbessern.',
          },
        },
      },
    },
  }]);
</script>

Keys you leave out stay in English, so translate every key your banner and dialog show. The messages follow the same structure every c15t package uses.

The script tag bundles English only, so in offline mode every other language needs an entry in i18n.messages. With one entry per language, data-language and c15t.setLanguage() switch between them. A regional code such as de-AT uses the de entry when there is no de-AT entry. A language with no entry shows the default copy.

Message keys the stock UI reads

KeyWhere it shows
cookieBanner.title, cookieBanner.descriptionBanner heading and text under a choice policy.
cookieBanner.noticeTitle, cookieBanner.noticeDescriptionBanner heading and text under a notice policy.
common.acceptAll, common.rejectAll, common.customizeBanner and dialog buttons.
common.acknowledgeThe notice's dismiss button.
common.saveThe dialog's save button.
common.securedByThe "Secured by" tag.
consentManagerDialog.title, consentManagerDialog.descriptionDialog heading and text.
consentTypes.measurement.title, consentTypes.measurement.description and the other categoriesEach category row in the dialog.
legalLinks.privacyPolicy, legalLinks.cookiePolicy, legalLinks.termsOfServiceLegal link labels, when a link has no label of its own.
rights.optOut, rights.preferencesThe extra button an opt-out policy adds to the banner.

The trigger's accessible name is not a message. Set ui.trigger.ariaLabel per page instead.

Right-to-left languages

For a right-to-left language such as Hebrew, the banner and dialog set dir="rtl" and a banner at a default left or right position moves to the other side. Check wrapping and button order after you switch.

Copy and translations covers labelling actions honestly and testing long strings.

Check it works

  1. Set your browser's preferred language to German and open the page in a private window. With a backend, the banner shows your project's German copy.
  2. Add data-language="fr" to the tag and reload. The banner switches to French.
  3. Open the preference dialog. Its title, category names and buttons use the same language as the banner.