- Translations
- Examples
- Basic Usage
- With Label
- Label Slot
- Setting Values
- Disabled State
- Flush Layout
- Textarea
- Inline Editing
- Many Languages
- Blank Languages Fall Back to English
- RTL Language Support
- Listening to Changes
- Form Integration
- Programmatic Control
- Help Text
- Slash Menu Quick Insertions
- Properties
- Events
- Slots
- Methods
- CSS Parts
- Accessibility
- Importing
- Slots
- Properties
- Events
- Methods
- Parts
- Dependencies
Translations
<zn-translations> | ZnTranslations
Collects one piece of text in several languages, one language at a time.
The Translations component provides a user-friendly interface for managing multi-language text input. A
select above the field chooses the language being edited, and each language it offers carries a chip saying
whether it has a translation of its own or falls back to English; closed, it carries how many languages are
done as a 1/5 chip. The field itself is a plain input, or a textarea with
input-type="textarea".
Several fields that should share one language picker belong in a
zn-translation-group instead.
<zn-translations languages='{"en":"English","fr":"French","de":"German"}' values='{"en":"Welcome","fr":"Bienvenue","de":"Willkommen"}' ></zn-translations>
Examples
Basic Usage
A simple translations component with default English language.
<zn-translations></zn-translations>
With Label
Use the label attribute to add a descriptive label above the translations.
<zn-translations label="Product Description" languages='{"en":"English","fr":"French"}' ></zn-translations>
Label Slot
Use the label slot for rich HTML content in the label.
<zn-translations languages='{"en":"English","fr":"French"}'> <span slot="label"> <strong>Description</strong> <zn-icon src="translate" size="16" style="margin-inline-start: 4px;"></zn-icon> </span> </zn-translations>
Setting Values
values takes an object keyed by language code. value is the same thing as a JSON
string, for setting it from markup or from a server-rendered template — set one or the other, not both.
<zn-translations label="Set with values" languages='{"en":"English","fr":"French","es":"Spanish"}' values='{"en":"Hello World","fr":"Bonjour le monde","es":"Hola Mundo"}' ></zn-translations> <br /> <zn-translations label="Set with value" languages='{"en":"English","fr":"French"}' value='{"en":"This is a product description","fr":"Ceci est une description de produit"}' ></zn-translations>
Disabled State
Disable editing of translations.
<zn-translations label="System Message (Read-only)" disabled languages='{"en":"English","fr":"French"}' values='{"en":"This cannot be edited","fr":"Cela ne peut pas être modifié"}' ></zn-translations>
Flush Layout
Remove padding for a more compact appearance.
<zn-translations flush languages='{"en":"English","fr":"French","de":"German"}' values='{"en":"Compact layout","fr":"Mise en page compacte","de":"Kompaktes Layout"}' ></zn-translations>
Textarea
Use input-type="textarea" for longer copy, and textarea-rows to set its height.
<zn-translations label="Confirmation Message" input-type="textarea" textarea-rows="3" languages='{"en":"English","de":"German"}' values='{"en":"Thanks — your order is on its way.","de":"Danke — Ihre Bestellung ist unterwegs."}' ></zn-translations>
Inline Editing
Add inline-edit to read the translation as text until it is clicked, through
zn-inline-edit, rather than showing an input outright.
<zn-translations inline-edit label="Welcome Message" languages='{"en":"English","fr":"French"}' values='{"en":"Hello World","fr":"Bonjour le monde"}' ></zn-translations>
Many Languages
Each language becomes an option labelled Name (CODE) — or the code alone where the configured
name already is the code. The select takes any number of them, and its listbox scrolls once the list is
longer than the space below it.
<zn-translations label="International Content" languages='{"en":"English","fr":"French","de":"German","es":"Spanish","it":"Italian","pt":"Portuguese","ru":"Russian","zh":"Chinese","ja":"Japanese","ar":"Arabic","hi":"Hindi","ko":"Korean"}' values='{"en":"Hello","fr":"Bonjour","de":"Hallo","es":"Hola","it":"Ciao","pt":"Olá","ru":"Привет","zh":"你好","ja":"こんにちは","ar":"مرحبا","hi":"नमस्ते","ko":"안녕하세요"}' ></zn-translations>
Blank Languages Fall Back to English
A language you have not translated yet is marked English in the select rather than hidden, and
its field shows the English text as a placeholder. Leave it blank and the English text is what gets used.
<zn-translations label="Product Name" languages='{"en":"English","fr":"French","de":"German","pl":"Polish"}' values='{"en":"Premium Wireless Headphones","de":"Premium kabellose Kopfhörer"}' ></zn-translations>
RTL Language Support
The component automatically detects and applies right-to-left text direction for Arabic and Hebrew languages.
<zn-translations label="RTL Languages" languages='{"en":"English","ar":"Arabic","he":"Hebrew"}' values='{"en":"Hello World","ar":"مرحبا بالعالم","he":"שלום עולם"}' ></zn-translations>
Listening to Changes
The component emits zn-change events when translation values change.
<zn-translations id="trans-events" label="Translation Input" languages='{"en":"English","fr":"French"}' ></zn-translations> <div style="margin-top: 1rem; padding: 1rem; background: var(--zn-color-neutral-50); border-radius: 4px;"> <strong>Event Log:</strong> <div id="event-log-trans" style="margin-top: 0.5rem; font-family: monospace; font-size: 0.875rem;"></div> </div> <script type="module"> const translations = document.getElementById('trans-events'); const eventLog = document.getElementById('event-log-trans'); translations.addEventListener('zn-change', (event) => { const timestamp = new Date().toLocaleTimeString(); const value = JSON.parse(event.target.value); eventLog.innerHTML = `[${timestamp}] Translation changed: ${JSON.stringify(value, null, 2)}`; }); </script>
Form Integration
The component submits its translations as a JSON object under name. required marks
the label, though validity is not enforced per language.
<form class="translations-form"> <zn-translations name="content" label="Article Content" required languages='{"en":"English","fr":"French","de":"German"}' ></zn-translations> <br /> <zn-button type="submit" color="success">Submit Translations</zn-button> </form> <script type="module"> const form = document.querySelector('.translations-form'); await customElements.whenDefined('zn-translations'); form.addEventListener('submit', (e) => { e.preventDefault(); const formData = new FormData(form); const data = Object.fromEntries(formData); alert('Form submitted!\n\n' + JSON.stringify(data, null, 2)); }); </script>
Programmatic Control
Access and modify translation values via JavaScript.
<zn-translations id="prog-trans" label="Programmatic Translations" languages='{"en":"English","fr":"French","es":"Spanish"}' ></zn-translations> <div style="margin-top: 1rem;"> <zn-button id="set-values-btn">Set Sample Values</zn-button> <zn-button id="get-values-btn" color="info">Get Values</zn-button> <zn-button id="clear-values-btn" color="secondary">Clear All</zn-button> </div> <script type="module"> const trans = document.getElementById('prog-trans'); document.getElementById('set-values-btn').addEventListener('click', () => { trans.values = { en: 'Sample English text', fr: 'Exemple de texte français', es: 'Texto de muestra en español' }; }); document.getElementById('get-values-btn').addEventListener('click', () => { alert('Current values:\n\n' + JSON.stringify(trans.values, null, 2)); }); document.getElementById('clear-values-btn').addEventListener('click', () => { trans.values = { en: '', fr: '', es: '' }; }); </script>
Help Text
Use the help-text attribute to describe how the field should be filled in. It sits below the
field and applies to every language, so it is the place to explain a convention the translator needs to
follow. For help text containing HTML, use the help-text slot instead.
<zn-translations label="Confirmation headline" help-text="Keep this under 60 characters so it does not wrap on mobile."></zn-translations> <br /> <zn-translations label="Footer"> <div slot="help-text">Shown on <strong>every</strong> page of the checkout.</div> </zn-translations>
Slash Menu Quick Insertions
Copy that carries replacement strings — {{BRAND_NAME}} and the like — needs the same tokens in
every language. Set slash-items and typing / offers them at the caret, in
whichever language is being edited. This works on both the single-line default and
input-type="textarea". The attribute takes the same shorthand and JSON that
zn-textarea accepts, and
slash-preset, slash-trigger and slash-heading are forwarded too.
<zn-translations label="Confirmation message" input-type="textarea" textarea-rows="4" languages='{"en": "EN", "fr": "FR", "de": "DE"}' values='{"en": "Look for /"}' slash-heading="Replacement strings" slash-items='[ {"label": "Brand name", "value": "{{BRAND_NAME}}", "description": "The product / company name", "icon": "sell"}, {"label": "Customer email", "value": "{{CUSTOMER_EMAIL}}", "description": "The customer's email address", "icon": "mail"}, {"label": "Renewal price", "value": "{{RENEWAL_PRICE}}", "description": "The renewal price amount", "icon": "payments"} ]'></zn-translations>
The menu claims ↑, ↓, Enter, Tab and
Escape while it is open, so choosing an item never submits the form the way
Enter otherwise would.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
name |
string |
'' |
Form field name for submission |
value |
string |
'{"en":""}' |
JSON string of translations |
label |
string |
'' |
Label displayed above the component |
help-text |
string |
'' |
Text shown below the field, describing how to fill it in |
disabled |
boolean |
false |
Disables editing of all translations |
required |
boolean |
false |
Makes the field required for form validation |
flush |
boolean |
false |
Removes padding for compact layout |
languages |
Record<string, string> |
{en: "EN"} |
Object mapping language codes to display names |
values |
Record<string, string> |
{} |
Object mapping language codes to translation text |
grouped |
boolean |
false |
Hides the language select; a parent zn-translation-group drives it |
input-type |
'text' | 'number' | 'textarea' |
'text' |
The control each translation is edited through |
textarea-rows |
number |
— | Rows of the textarea, when input-type is textarea |
inline-edit |
boolean |
false |
Edits through zn-inline-edit instead of a plain input or textarea |
slash-items |
SlashMenuItem[] |
[] |
Quick insertions offered by the slash menu |
slash-preset |
string |
'' |
Registered item sets to offer, comma separated |
slash-trigger |
string |
'/' |
The characters that open the slash menu |
slash-heading |
string |
'Insert' |
Heading shown above the slash menu’s items |
Events
| Event | Description | Event Detail |
|---|---|---|
zn-change |
Emitted when any translation value changes | {value: string} |
zn-input |
Emitted when translation input changes | None |
Slots
| Slot | Description |
|---|---|
label |
Alternative to the label attribute for rich HTML content |
help-text |
Alternative to the help-text attribute for rich HTML content |
Methods
| Method | Description |
|---|---|
checkValidity() |
Checks form validity |
reportValidity() |
Checks validity and shows message |
setCustomValidity(message) |
Sets custom validation message |
getForm() |
Returns the parent form element |
CSS Parts
| Part | Description |
|---|---|
form-control |
The component’s base wrapper |
form-control-label |
The label’s wrapper |
form-control-input |
The wrapper around the field being edited |
language-select |
The select that chooses the language being edited |
The component uses zn-select for the language and zn-input,
zn-textarea or zn-inline-edit for the field, each of which exposes its own CSS
parts for advanced styling.
Accessibility
- The component automatically detects RTL languages (Arabic, Hebrew) and applies proper text direction
-
The language select is a standard combobox: it opens on
EnterorSpaceand moves through the languages with the arrow keys Entersubmits the form from a single-line field, and inserts a newline in a textarea
Importing
If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.
To import this component from the CDN using a script tag:
<script type="module" src="https://cdn.jsdelivr.net/npm/@kubex/zinc@1.1.116/dist/components/translations/translations.js"></script>
To import this component from the CDN using a JavaScript import:
import 'https://cdn.jsdelivr.net/npm/@kubex/zinc@1.1.116/dist/components/translations/translations.js';
To import this component using a bundler:
import '@kubex/zinc/dist/components/translations/translations.js';
Slots
| Name | Description |
|---|---|
label
|
The field’s label. Alternatively, use the label attribute. |
help-text
|
Text describing how to fill the field in, shown below it and shared by every language.
Alternatively, use the help-text attribute.
|
Learn more about using slots.
Properties
| Name | Description | Reflects | Type | Default |
|---|---|---|---|---|
name
|
The name submitted with the form. |
string
|
''
|
|
value
|
The translations as a JSON object keyed by language code. The mirror of values in
attribute form.
|
string
|
'{"en":""}'
|
|
label
|
The label shown above the field. If you need HTML, use the label slot instead. |
string
|
''
|
|
helpText
help-text
|
Text shown below the field, describing how to fill it in. Applies to every language. If you need
HTML, use the
help-text slot instead.
|
string
|
''
|
|
disabled
|
Disables editing in every language. |
|
boolean
|
false
|
required
|
Marks the label required. Validity is not enforced per language. |
|
boolean
|
false
|
flush
|
Removes the component’s own padding. |
|
boolean
|
false
|
inputType
input-type
|
The control each translation is edited through. |
'text' | 'number' | 'textarea'
|
'text'
|
|
textareaRows
textarea-rows
|
Rows of the textarea, when input-type is textarea. |
number | undefined
|
- | |
inlineEdit
inline-edit
|
Edits the translation through a zn-inline-edit — the value reads as text until it is
clicked — rather than a plain input or textarea.
|
|
boolean
|
false
|
slashItems
slash-items
|
Quick insertions offered by the slash menu on text and textarea inputs.
Accepts a JSON array of items, or the shorthand
Brand name={{BRAND_NAME}}, Support email={{SUPPORT_EMAIL}}. Every language shares the
list.
|
SlashMenuItem[]
|
[]
|
|
slashPreset
slash-preset
|
Names of item sets registered with registerSlashMenuPreset, comma separated. |
string
|
''
|
|
slashTrigger
slash-trigger
|
The characters that open the slash menu. |
string
|
'/'
|
|
slashHeading
slash-heading
|
The name the slash menu’s list is announced by. |
string
|
'Insert'
|
|
slashHideKeys
slash-hide-keys
|
Hides the insertion keys normally shown against the slash menu’s items. |
boolean
|
false
|
|
slashRecentKey
slash-recent-key
|
Lists the slash menu items most recently chosen here above the rest, remembered under this key. |
string
|
''
|
|
slashItemsProvider
|
Resolves additional slash menu items each time the menu opens. JavaScript only. |
(query: string) => SlashMenuItem[] | Promise
|
- | |
grouped
|
Hides this component’s own language select and defers the choice to a parent zn-translation-group. The group sets this on its children itself. |
|
boolean
|
false
|
languages
|
The languages on offer, as language code to display name —
{"en": "English", "fr": "French"}. Writing the code as the name ({"en": "EN"}) is also accepted. en is the language every other one falls back to.
|
Record
|
{ 'en': 'EN' }
|
|
values
|
The translations as an object keyed by language code. The mirror of value in property
form.
|
Record
|
{}
|
|
defaultValue
|
The serialized translations a form reset restores. Taken from the value attribute where
there is one.
|
string
|
'{"en":""}'
|
|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Events
| Name | React Event | Description | Event Detail |
|---|---|---|---|
zn-change |
|
Emitted when a translation’s value changes. | - |
zn-input |
|
Emitted when a translation receives input. | - |
Learn more about events.
Methods
| Name | Description | Arguments |
|---|---|---|
setActiveLanguage() |
Sets the active language externally. Used by zn-translation-group. Browsing to a language does not
create a key for it — an untouched language stays absent from values so it is not
submitted as an empty translation.
|
language: string
|
getActiveLanguage() |
Returns the currently active language. | - |
addLanguageKey() |
Adds a language key to this component’s values if not already present. Used by zn-translation-group. |
languageCode: string
|
getValueLanguages() |
Returns all language codes that have values. | - |
hasTranslation() |
Whether the language carries a translation of its own, rather than falling back to English. |
language: string
|
Learn more about methods.
Parts
| Name | Description |
|---|---|
form-control |
The form control that wraps the label, the language select, the field and the help text. |
form-control-label |
The label’s wrapper. |
form-control-input |
The wrapper around the field being edited. |
form-control-help-text |
The help text’s wrapper. |
language-select |
The select that chooses the language being edited. |
Learn more about customizing CSS parts.
Dependencies
This component automatically imports the following dependencies.
<zn-chip><zn-example><zn-icon><zn-inline-edit><zn-input><zn-opt-group><zn-option><zn-popup><zn-select><zn-slash-item><zn-slash-menu><zn-tag><zn-textarea><zn-tooltip>