Skip to main content
Light Dark System

Translation Group

<zn-translation-group> | ZnTranslationGroup
Since 1.0 experimental

Puts several zn-translations fields behind one language select, so a whole form’s worth of copy is translated a language at a time.

The Translation Group component wraps multiple zn-translations components in a panel-styled container with a shared language select. The fields sit in a form group, so the caption, help text and the select share its label column and the fields line up with every other form group around them. Closed, the select carries how many languages are done as a 1/5 chip; open, each language is marked translated, partial or falling back to English. Type to filter the list — by name or by language code, so de finds German. Choosing a language switches every child at once.

<zn-translation-group
  label="Product Content"
  help-text="Every field is translated one language at a time"
  languages='{"en":"English","fr":"French","de":"German"}'>
  <zn-translations
    label="Name"
    name="name"
    values='{"en":"Wireless Headphones","fr":"Écouteurs sans fil","de":"Kabellose Kopfhörer"}'
  ></zn-translations>
  <zn-translations
    label="Description"
    name="description"
    values='{"en":"Premium noise-cancelling headphones","fr":"Écouteurs antibruit premium","de":"Premium-Kopfhörer mit Geräuschunterdrückung"}'
  ></zn-translations>
</zn-translation-group>

Examples

Basic Usage

A translation group with two translation inputs sharing one language select.

<zn-translation-group languages='{"en":"English","fr":"French"}'>
  <zn-translations label="Title" name="title"></zn-translations>
  <zn-translations label="Subtitle" name="subtitle"></zn-translations>
</zn-translation-group>

Label and Help Text

label names the section in the form group’s label column, and help-text sits under it — the pair behave as they do on any other form group. The language select follows them, in the group’s chip position. language-label sets the select’s accessible name — it is not shown, since the caption names the section on screen.

<zn-translation-group
  label="Page Translations"
  help-text="Pick a language to edit every field in it"
  languages='{"en":"English","fr":"French","es":"Spanish"}'>
  <zn-translations label="Heading" name="heading"></zn-translations>
  <zn-translations label="Body" name="body"></zn-translations>
</zn-translation-group>

Pre-filled Values

Set initial translations on each child. A language every child has a value for is marked Translated; one only some children have is Partial; one no child has falls back to English. English itself is marked Empty rather than falling back, having nothing to fall back to, and counts towards the total like any other language.

<zn-translation-group
  label="Notification Templates"
  languages='{"en":"English","fr":"French","de":"German","es":"Spanish"}'>
  <zn-translations
    label="Subject"
    name="subject"
    values='{"en":"Welcome aboard!","fr":"Bienvenue !","de":"Willkommen!","es":"Bienvenido!"}'
  ></zn-translations>
  <zn-translations
    label="Preview Text"
    name="preview"
    values='{"en":"Get started with your account","fr":"Commencez avec votre compte","de":"Starten Sie mit Ihrem Konto","es":"Comience con su cuenta"}'
  ></zn-translations>
</zn-translation-group>

Many Languages

Every configured language is offered whether or not it has been translated yet, so there is no separate step to add one — pick it and start typing. The chip on the closed select tracks how many are done.

<zn-translation-group
  label="Release Notes"
  languages='{"en":"English","ar":"Arabic","de":"German","es":"Spanish","fr":"French","it":"Italian","ja":"Japanese","ko":"Korean","pt":"Portuguese","ru":"Russian","tr":"Turkish","zh-hans":"Simplified Chinese"}'>
  <zn-translations
    label="Headline"
    name="headline"
    values='{"en":"Now shipping","ar":"متاح الآن","de":"Jetzt verfügbar","es":"Ya disponible","fr":"Disponible dès maintenant","it":"Disponibile ora","ja":"発売開始","ko":"출시됨","pt":"Disponível agora","ru":"Уже в продаже","tr":"Şimdi mevcut","zh-hans":"现已发布"}'
  ></zn-translations>
  <zn-translations
    label="Summary"
    name="summary"
    values='{"en":"Tap through the release highlights.","ar":"تصفح أبرز ميزات الإصدار.","de":"Highlights der Version ansehen.","es":"Consulta lo más destacado.","fr":"Découvrez les nouveautés.","it":"Scopri le novità.","ja":"リリースのハイライトをご覧ください。","ko":"업데이트 주요 내용 보기.","pt":"Veja os destaques.","ru":"Ознакомьтесь с обновлениями.","tr":"Sürüm önemli noktaları.","zh-hans":"浏览版本亮点。"}'
  ></zn-translations>
</zn-translation-group>

Custom Accessible Name

language-label is read out by a screen reader in place of a visible label.

<zn-translation-group
  language-label="Language"
  languages='{"en":"English","fr":"French","de":"German"}'>
  <zn-translations label="Heading" name="heading" values='{"en":"Now shipping","de":"Jetzt verfügbar"}'></zn-translations>
  <zn-translations label="Body" name="body" values='{"en":"Tap through the highlights."}'></zn-translations>
</zn-translation-group>

Inline (No Panel)

Nested inside another panel, the group’s own border and padding indent its fields out of line with everything around them. inline drops the chrome so the group reads as a section of the form instead.

<zn-panel caption="Product Details" icon="inventory_2">
  <div style="display: flex; flex-direction: column; gap: 1rem;">
    <zn-input label="Product SKU" value="PROD-12345" readonly></zn-input>

    <zn-translation-group
      inline
      label="Translatable Content"
      languages='{"en":"English","fr":"French","de":"German"}'>
      <zn-translations
        name="name"
        label="Product Name"
        values='{"en":"Premium Wireless Headphones","fr":"Écouteurs sans fil premium","de":"Premium kabellose Kopfhörer"}'
      ></zn-translations>
      <zn-translations
        name="short-description"
        label="Short Description"
        values='{"en":"High-quality wireless audio","fr":"Audio sans fil haute qualité","de":"Hochwertiges kabelloses Audio"}'
      ></zn-translations>
    </zn-translation-group>

    <zn-input label="Price" type="currency" value="299.99"></zn-input>
  </div>
</zn-panel>

Actions

Buttons for the bottom of the group go in the actions slot. They sit on the white body rather than the grey footer, and follow zinc’s form action rows in sitting on the right. align="start" moves one to the left; any number can sit on either side. Write them in the order they should be read — the sides are set by CSS ordering, so markup order is what a keyboard follows.

Auto-translate Cancel Save
<zn-translation-group
  label="Product Content"
  languages='{"en":"English","fr":"French","de":"German"}'>
  <zn-translations label="Name" name="name" values='{"en":"Wireless Headphones","de":"Kabellose Kopfhörer"}'></zn-translations>
  <zn-translations label="Description" name="description" values='{"en":"Premium noise-cancelling headphones"}'></zn-translations>

  <zn-button slot="actions" align="start" color="transparent" icon="translate">Auto-translate</zn-button>
  <zn-button slot="actions" color="secondary">Cancel</zn-button>
  <zn-button slot="actions" color="success">Save</zn-button>
</zn-translation-group>

Flush Layout

Remove body padding for a more compact appearance using the flush attribute.

<zn-translation-group
  flush
  label="Compact Translations"
  languages='{"en":"English","fr":"French"}'>
  <zn-translations label="Label" name="label"></zn-translations>
  <zn-translations label="Placeholder" name="placeholder"></zn-translations>
</zn-translation-group>

Listening to Language Changes

The group emits a zn-language-change event when the active language changes.

Active Language: en
<zn-translation-group
  id="group-events"
  label="Event Demo"
  languages='{"en":"English","fr":"French","de":"German"}'>
  <zn-translations label="Title" name="title"></zn-translations>
  <zn-translations label="Description" name="description"></zn-translations>
</zn-translation-group>

<div style="margin-top: 1rem; padding: 1rem; background: var(--zn-color-neutral-50); border-radius: 4px;">
  <strong>Active Language:</strong>
  <span id="active-lang" style="font-family: monospace;">en</span>
</div>

<script type="module">
  const group = document.getElementById('group-events');
  const display = document.getElementById('active-lang');

  group.addEventListener('zn-language-change', (event) => {
    display.textContent = event.detail.language;
  });
</script>

Properties

Property Type Default Description
label string '' Names the section, in the form group’s label column
help-text string '' Sits under the label, above the language select
language-label string 'Edit Languages' The select’s accessible name; not shown on screen
inline boolean false Drops the panel border, background and padding
languages Record<string, string> {en: "EN"} Object mapping language codes to display names
flush boolean false Removes body padding for compact layout

Events

Event Description Event Detail
zn-language-change Emitted when the active language changes { language: string }

Slots

Slot Description
(default) Place <zn-translations> elements here
actions Buttons for the bottom of the body; align="start" on a child moves it to the left
footer Content displayed in the grey panel footer

CSS Parts

Part Description
base The outer panel wrapper
form-group The form group holding the caption, the language select and the fields
language-field The container holding the language select, in the group’s chip slot
language-select The select itself
actions The row of buttons at the bottom of the body

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.160/dist/components/translation-group/translation-group.js"></script>

To import this component from the CDN using a JavaScript import:

import 'https://cdn.jsdelivr.net/npm/@kubex/zinc@1.1.160/dist/components/translation-group/translation-group.js';

To import this component using a bundler:

import '@kubex/zinc/dist/components/translation-group/translation-group.js';

Slots

Name Description
(default) The zn-translations fields the select drives.
actions Buttons for the bottom of the panel, on the white body rather than the grey footer. They sit on the right, as zinc’s form action rows do; align="start" moves one to the left. Write them in the order they should be read — the sides are set by CSS ordering, so markup order is what a keyboard follows.
footer Content displayed in the grey panel footer.

Learn more about using slots.

Properties

Name Description Reflects Type Default
label The form group’s label. An alias for the inherited caption, which wins where both are set. string ''
helpText
help-text
Sits under the label, above the language select, as help text does in any other form group. string ''
inline Drops the panel chrome — border, background and padding — so the group reads as a section of the surrounding form rather than a panel of its own. For groups nested inside another panel, where the fields would otherwise sit indented behind a second border. boolean false
languageLabel
language-label
The select’s accessible name. Not shown — the caption is what names the section on screen — but read out by a screen reader, which has nothing else to go on once the visible label is gone. string 'Edit Languages'
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. Set on every child, so they do not need their own copy. Record { 'en': '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-language-change Emitted when the active language changes. Detail: { language: string }. -

Learn more about events.

Custom Properties

Name Description Default
--zn-panel-basis The flex-basis of the panel. Can be set using the basis-px attribute.
--zn-panel-header-padding Padding around the header row. Defaults to --zn-base-gap.
--zn-panel-footer-padding Padding around the footer row.

Learn more about customizing CSS custom properties.

Parts

Name Description
base The component’s base wrapper.
form-group The form group holding the caption, the language select and the fields.
actions The row of buttons at the bottom of the body.
language-field The select that chooses the language every child is editing, in the group’s chip slot.
language-select The select itself.
header The header region, when a caption or actions are given.
header-content The padded row inside the header, forwarded from zn-header.
footer The footer region, when the footer slot is filled.

Learn more about customizing CSS parts.

Dependencies

This component automatically imports the following dependencies.

  • <zn-chip>
  • <zn-example>
  • <zn-form-group>
  • <zn-icon>
  • <zn-opt-group>
  • <zn-option>
  • <zn-popup>
  • <zn-select>
  • <zn-tag>