Skip to main content

Translations

Translation labels are loaded from the server during bootstrap and accessed through three functions exported from $lib/utils/translator.js. Labels match the user's current locale automatically — no locale argument is needed at the call site.


__(label, replacements?, ignoreMissing?)

The primary translation function. Looks up label in the loaded label set and returns the localised string.

import { __ } from '$lib/utils/translator.js';

__('conversation.title') // → 'Conversation'
__('errors.not_found') // → 'The requested item was not found.'

Dot notation resolves nested label keys:

__('composer.placeholder') // → resolves labels.composer.placeholder

When a key is not found, __() logs a console warning and returns "Missing translation: {label}" — making missing keys visible during development without throwing. Pass ignoreMissing: true to return an empty string silently instead:

__('optional.badge', undefined, true) // → '' when key is absent

String Replacements

Pass a replacements object to substitute :placeholder tokens in the label. Three case variants are substituted simultaneously, mirroring Laravel's Translator::makeReplacements():

Token in labelSubstituted value
:namevalue as-is
:Namevalue with first letter uppercased
:NAMEvalue fully uppercased
// Label: "Welcome, :Name! You have :count messages."
__('welcome', { name: 'alice', count: '3' })
// → 'Welcome, Alice! You have 3 messages.'

Function Replacements

When a replacement value is a function, every <key>content</key> occurrence in the label is replaced by calling the function with the inner content. Use this to wrap a portion of a translated string in an HTML element or Svelte component:

// Label: "Please read our <link>terms of service</link>."
__('terms_notice', {
link: (text) => `<a href="/terms">${text}</a>`
})
// → 'Please read our <a href="/terms">terms of service</a>.'

hasTranslation(label)

Returns true when a label key exists in the loaded label set. Use this to conditionally render optional UI elements without relying on an empty-string check:

import { hasTranslation } from '$lib/utils/translator.js';

if (hasTranslation('feature.beta_badge')) {
// render badge
}

getTranslations(label, replacements?, ignoreMissing?)

Like __() but allows returning non-string values. When the resolved label is an object (a nested section of the label tree), it is returned as-is. Replacement substitution only applies when the result is a string.

import { getTranslations } from '$lib/utils/translator.js';

// Returns the entire 'errors' sub-object if that key maps to a nested section
const allErrors = getTranslations('errors');

Prefer __() for string labels. Use getTranslations() only when you specifically need to iterate over a label section.


getTranslationsFlat(path)

Like getTranslations(), but flattens a nested label sub-tree into a single-level Record<string, string> with dot-notated keys. Requires path to resolve to an object — throws if it points to a string or any non-object value.

import { getTranslationsFlat } from '$lib/utils/translator.js';

// Given labels: { markdown: { markstream: { copy: 'Copy', copied: 'Copied!' } } }
getTranslationsFlat('markdown.markstream');
// → { 'copy': 'Copy', 'copied': 'Copied!' }

Returns {} with a console warning when labels are not yet loaded or the path is not found. Use this when a third-party library expects a flat key/value map of strings rather than a nested object — the Markdown component uses it to pass localised strings to markstream-svelte.


Label Files

Translation labels are served by the translation-labels API resource and loaded automatically during the main boot stage. The active locale comes from the connection object; if it fails to load, the system falls back to the configured default locale, and then to an empty label set. No manual setup is required — __() is available in any component or utility after bootstrap.

Labels live on the server side under resources/lang/. To add a new label, add the key to the appropriate language file there.