Lattice Grid Buy a licence

developer guide

Data Grid Localisation (i18n) and Translation

Every string the grid writes can be replaced, and a locale tag resolves to the closest catalogue you have supplied rather than dropping back to English at the first miss. An Arabic, Hebrew or Farsi locale also mirrors the layout, and a catalogue can be audited for what it is missing.

Developer guideTheming and density › Data Grid Localisation (i18n) and Translation

Translating the grid

Every string the grid renders or announces comes from a message catalogue. British English is the default; supply messages to replace some or all of it.

import { createGrid, FR_FR } from '@toclocoinc/lattice-grid';

createGrid(element, { locale: 'fr-FR', messages: FR_FR });

Where locale is not set, the grid takes the language the page declares in its lang attribute. Overrides merge over the default, so translating part of the interface leaves the remainder in English rather than showing raw keys, and a key that is not in the catalogue is ignored with a warning.

Catalogues ship for twenty-one locales: British and American English, French (France and Canada), Italian, Spanish, Brazilian Portuguese, German, Dutch, Swedish, Danish, Norwegian, Finnish, Polish, Czech, Hungarian, Romanian, Ukrainian, Greek, Japanese and Arabic. Each is an export of the package, so importing one does not reduce what is bundled. EN_US is a partial overlay carrying only what differs from British English and merging over it. AR_SA is an alias for AR rather than a separate catalogue: Arabic ships pan-Arabic, and a region appears in a name only where two variants exist. For anything else, resolveCatalogue(tag) resolves a tag to a catalogue and falls back to the base language, so ar-EG and es-MX both find one. FR_CA is a complete catalogue that follows Quebec usage where it differs, a column there is figée rather than épinglée.

None of the translations has been reviewed by a native speaker. They are structurally complete and checked for placeholder integrity and plural coverage, but they are a starting point for review rather than finished copy.

Writing your own

A message is a string, or an object keyed by plural category when it counts something:

{
  'menu.sortAscending': 'Sortera stigande',
  'count.rows': { one: '{count} rad', other: '{count} rader' },
}

Placeholders are named, so word order is yours to choose. The parameter called count selects the plural form, using the categories the language actually has: English needs two, French treats zero as singular, Arabic has six. Numbers are formatted for the locale automatically; do not format them yourself.

MESSAGE_KEYS lists every key. auditCatalogue(yours) returns what is missing and what is not a real key, which is the quickest way to check a translation before shipping it.

Keys seeded in English, awaiting translation

A key added after a catalogue was written ships in British English only until a translator supplies it; Messages merges every catalogue over the default, so the grid says it in English rather than showing the key. The shipped catalogues do not carry an English copy under the guise of a translation, and the build's completeness test lists exactly which keys are in this state. As of 1.55 the most recent additions are the strings that had shipped as template literals, untranslated in every locale: the presence live region and roster note, a11y.presence.refused, presence.someoneElse and presence.hidden; the comment panel's changed-since note, comments.valueMoved; the facet band's accessible name, facets.filter; the heading tooltip that names a reduction, header.totalOf; the audit-mode tooltip, diff.before and diff.empty; the kanban list names, kanban.columnCards and kanban.laneCards, both plural objects selected by count; and the gantt lag label, gantt.lag and gantt.lead. Supply any of them in messages to translate it today.

The rest of that text followed in 1.69: the gantt's pointer tooltip, gantt.tip.range, gantt.tip.duration and gantt.tip.slack - plain strings rather than plural objects, because the day unit is an abbreviation that does not inflect; the comment panel's own labels, comments.resolve, comments.reopen, comments.loading, comments.empty, comments.unknownAuthor, comments.edited (which takes the already-rendered time as {time}, so the marker need not come last) and comments.cellTitle; the accessible name of each entry in the presence roster, presence.peer, presence.peerIdle and presence.peerHidden; and the reduction named in a column heading, which now reads the same total.* keys the tool panel does, with total.custom for a reduction supplied as a function and total.passRate and total.failureCount for the two capability reductions that had no key at all.

The kanban board and the gantt view are modules and do not import the catalogue. A board bound to a grid, or a plan created with one, borrows that grid's messages; otherwise pass messages - a grid's own, or any object with t(key, params) - to createKanban or to gantt.mount. With neither they render the English.

The grid is checked in the other direction too. auditCatalogue tells you a catalogue is complete: that a translator covered every key. It cannot tell you the grid only ever renders text that came from a catalogue in the first place, and a string written into the source passes every test, because the tests assert on the English the grid happens to produce.

So the build refuses one. Any literal reaching an element's text, or an announced attribute such as aria-label, title or placeholder, has to come from the catalogue. That is what stops a localised grid drifting back into English one plausible change at a time.

Right-to-left

The grid lays out right to left. Set direction: 'rtl' outright, or leave it unset and it follows the element's computed dir first and the locale second, so locale: 'ar' renders right to left with no further configuration, and a grid inside a page that has already declared dir="rtl" agrees with it.

createGrid(element, { locale: 'ar' });        // direction follows the locale
createGrid(element, { direction: 'rtl' });    // or say so outright

The element comes before the locale because a page that has set dir has already made a decision about layout, and a grid inside it should not disagree on the strength of a language tag.

Pinned columns swap sides, the header and pinned rows follow the scroll the other way, and column resize and reorder, the fill handle, annotations, the facet band, the comment marker and menu placement all follow the writing direction rather than the physical one.

Not yet exercised with bidirectional text. The layout is verified, but only with Latin text in a right-to-left grid. Cells, headings and editors holding actual Arabic or Hebrew (particularly mixed with Latin text or numbers) have not been tested.