Customization
Copy and translations
Configure shared messages
Use provider i18n for wording that should stay consistent across components.
For React, this fragment belongs in ConsentProvider options:
Supply the same message keys in each supported locale. A one-off component prop
such as dismissButtonText is useful for one banner; use translations for a
site-wide change. Astro's serializable integration options have their own
types, so verify that shape before copying a React object. The Vue plugin and
Nuxt module have no i18n option; their copy comes from the backend.
Load only the languages you use
c15t bundles English. Every other language it ships is a separate entry point
in @c15t/translations, named by its language code. Importing one registers
c15t's built-in copy for that language. Offline mode can then switch to it,
and your messages that repeat its wording don't hide backend edits. Import
them in the file that configures the provider, so they load in the browser:
Each entry also exports that copy as translations, if you want to read a
string or build your messages from it:
The entries are bg, cs, cy, da, de, el, es, et, fi, fr,
ga, gu, he, hi, hr, hu, id, is, it, lb, lt, lv, mt,
nb, nl, nn, pl, pt, rm, ro, sk, sl, sv and zh.
@c15t/translations/all still loads every language at once. The c15t
package doesn't re-export these entries, so add @c15t/translations to your
dependencies.
Combine messages with backend copy
With a backend or a manifest, the copy it sends for the visitor's language is
the base. Your i18n.messages for that language replace it key by key, and
keys you leave out keep the backend's wording, including copy edited in your
Inth project. c15t looks up messages for the exact language first, then for
its primary language, so de-AT uses your de messages when there is no
de-AT entry. 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 a stock bundle to enable a language
keeps backend edits visible, while a key you actually reworded stays pinned
in code. c15t only recognizes the built-in wording of English and of the
languages you import, such as
@c15t/translations/de or @c15t/translations/all.
Write labels that describe the action
Accept and Reject record a choice. Customize opens preferences. Acknowledge dismisses a notice and does not record a grant. Do not label a notice dismissal "Accept all" or make a preferences link sound like it submits an opt-out.
The notice acknowledgement uses common.acknowledge, with common.dismiss as
a fallback for older translation bundles. Keep the displayed label and the
command's effect aligned.
Translate the ConsentGate placeholder
The ConsentGate placeholder reads the consentGate section:
| Key | Where it shows |
|---|---|
consentGate.title | The placeholder text. {category} is replaced by the category's translated title. |
consentGate.actionButton | The button that opens preferences, with the same {category} replacement. |
consentGate.policyBlocked | React and Vue show it in place of the title, with no button, when a strict policy leaves the category out of scope. |
Earlier versions called this section frame. Copy under frame in
i18n.messages or custom translations still applies. c15t reads it as consentGate, a key set under consentGate
wins over the same key under frame, and c15t logs a warning once outside
production. Rename the section to consentGate to remove the warning.
Show right-to-left languages
c15t sets dir="rtl" on its surfaces when the resolved language is Arabic,
Hebrew, Persian, Urdu, Pashto, Sindhi, Kurdish or Dhivehi. It matches the
primary language, so ar-EG counts as Arabic. Hebrew is the only
right-to-left translation c15t ships. For the others, supply your own
messages or the copy from your Inth project.
What follows the direction:
- Text, headings and the button row in the banner, the preference dialog and the preference widget flow right to left.
- A floating or widget banner in its default corner moves to the mirrored
corner, so
bottom-leftbecomesbottom-right. Apositionyou set yourself stays where you put it. - The HTML script tag,
@c15t/browserand Astro's banner also setlangon their surfaces. React, Vue and Svelte setdironly, so setlangon<html>yourself.
What does not follow yet:
- The IAB TCF dialog aligns several labels, indents and borders to the left.
- The floating
ConsentDialogTriggerkeeps the corner you give it.
Test right-to-left pages with a real translation before you ship them.
Test more than English
Try the longest labels you support at a narrow width, with browser zoom and right-to-left text where relevant. Check banner actions, category descriptions, legal links and the preferences save action. Translate explanations as well as buttons so a visitor can make an informed choice.