Translation
LO-TEK has almost no text. Whoever renders the markup writes the text in it, in their own language and with the translation tool the app already uses. The few texts built into the package are defaults, and each of them can be replaced. They are listed in the table at the bottom.
The text is in your markup
Section titled “The text is in your markup”A button, a label and a dialog are markup you write yourself, and the text in them is yours. In React with i18next, the session timeout looks like this:
import { useId } from "react"import { useTranslation } from "react-i18next"import { lt } from "@lo-tek/interfaces/react"
export function SessionWarning() { const { t } = useTranslation() const session = lt.sessionTimeout({ titleId: useId() })
return ( <lt-session-timeout {...session.host}> <dialog {...session.dialog}> <h2 {...session.title}>{t("session.title")}</h2> <p {...session.text}> {t("session.beforeCount")} <span {...session.count} /> {t("session.afterCount")} </p> <span {...session.live} /> <form {...session.actions}> <button {...session.extend}>{t("session.continue")}</button> <button {...session.logout}>{t("session.logOut")}</button> </form> </dialog> </lt-session-timeout> )}On a server it is the same markup, with the text coming from the server’s own setup. In a Go template it can be a function the app has registered itself:
<h2 class="lt-session-timeout__title" id="session-title">{{ T "session.title" }}</h2>LO-TEK does not care which tool you use, as long as it produces text. Some common choices:
| Where the markup is made | Common tools |
|---|---|
| React | i18next with react-i18next, FormatJS (react-intl), Lingui |
| Other JavaScript | i18next, Paraglide, FormatJS |
| Server | gettext, go-i18n in Go, resource files in .NET, ResourceBundle in Kotlin and Java |
Why LO-TEK has no integration
Section titled “Why LO-TEK has no integration”- The package has no dependencies, and is not getting any. An integration with i18next would make i18next part of every app that uses LO-TEK.
- Most of the tools have a separate package per framework, such as react-i18next. An integration would tie LO-TEK to one framework again, which is what the whole system is built to avoid.
- A server in Go or Kotlin cannot use a JavaScript library. Its text has to come from the server anyway.
- The text belongs to the markup, and the markup comes from whoever renders it. See Markup and behaviour.
Numbers and durations
Section titled “Numbers and durations”The components format numbers and durations with the browser’s own Intl, following lang on the page. The announcement in Session Timeout says “1 minute and 30 seconds” on an English page and “1 minutt og 30 sekunder” on a Norwegian one, without anyone having translated it. Suggestion picks the plural form with Intl.PluralRules, so Polish gets all four of its forms.
Set lang on <html>, therefore, and on any element in a different language from the rest of the page. Without lang, the browser’s own language is used.
The texts in the package
Section titled “The texts in the package”These are all the texts LO-TEK writes into the page itself. A guard in the build fails on a new text that is not listed here, on a text in CSS that is not read from a variable, and on a text written directly in a component.
| Component | Default text | How to replace it |
|---|---|---|
| Toast, the region | Notifications | label on <lt-toast>, or label in lt.toast() |
| Toast, the close button | Close message | close-label on <lt-toast>, closeLabel in lt.toast(), or closeLabel in show() for a single message |
| Connection Status, no connection | No connection. What you type is not being saved. | offline-text |
| Connection Status, back | Connection restored. | online-text |
| Suggestion, no matches | No matches | count-none |
| Suggestion, one match | One match | count-one |
| Suggestion, several matches | {n} matches | count-other, and count-zero, count-two, count-few and count-many for languages that have them |
| Label and Fieldset, required with a symbol | * | --lt-label-required-symbol |
| Label and Fieldset, required with text | (required) | --lt-label-required-text |
| Label and Fieldset, optional | (optional) | --lt-label-optional-text |
Session Timeout is not in the table. It has no text: you write the dialog yourself.
The texts in the stylesheets are replaced with a variable, for example by the language of the page. This example translates them into Norwegian on purpose, to show a language other than the defaults:
:root:lang(nb) { --lt-label-required-text: " (påkrevd)"; --lt-label-optional-text: " (valgfri)";}In the suggestion field, {n} stands for the count. Write it in every form except count-none, including count-one: in French that form also covers 0 matches, and in Russian also 21. The Norwegian example is on purpose too:
<lt-suggestion lang="nb" count-none="Ingen treff" count-one="{n} treff" count-other="{n} treff">If you use i18next, you can pass the translation straight in, as count-other={t("matches.other")}. i18next leaves {n} with single braces alone, so it can stay in the translation file.