import { lang as Lang } from "/helpers/lang.js"
// or if running into errors due to cells running before the import:
// const lang = await import("/helpers/lang.js");
// or if only needing the main lg function:
// import { lg } from "/helpers/lang.js"
languages = [
{ key: "en", label: "English", locale: "en-US" },
{ key: "fr", label: "Français", locale: "fr-FR" }
];Lang Module Guide
Author: Zach Bogart, Brayden Youngberg
Version: 2.0.1
Overview
The Lang module provides a set of helper functions to manage translations, template insertions, and string formatting in JavaScript notebooks and apps. It is especially useful for multi-language support and dynamic text replacement.
Installation & Defining Languages
Define available languages with keys, labels, and locales:
Setting Up Translation JSON
Structure your translations as a nested object or external JSON, with language keys for each field:
nbText = new Object({
"hello": {
"en": "hello",
"fr": "Bonjour"
},
"error": {
"en": "Whoops"
},
"insert": {
"small": {
"en": "This is an insertion example: :::field:::",
"fr": "Ceci est un exemple d'insertion: :::field:::"
},
"big": {
"en": "This is an insertion example: :::field::: :::name:::",
"fr": "Ceci est un exemple d'insertion: :::field::: :::name:::"
}
}
})Language Toggle UI (Observable Example)
Create a master toggle to pick the language key (Observable Inputs):
viewof language = Inputs.radio(languages, {
label: "Main language toggle",
format: (d) => d.key,
value: languages.find((x) => x.key === defaultLangKey),
})A “pretty” toggle with label that changes based on the language:
- NOTE: it is required to do this in a new Input, as there would be a circular definition otherwise
viewof prettyLanguageView = {
return Inputs.bind(
Inputs.radio(languages, {
label: Lang.getText({en: "Language", fr: "Langue"}, { key: language.key }),
format: (d) => d.label
}),
viewof language
);
}Retrieving Translations
Get a translation for the current language:
Lang.getText(nbText.hello, { key: language.key });Shorthand Helper
To avoid repeating the language key, use lg:
_lang = Lang.lg(language.key);
_lang(nbText.hello);Template Insertion
Replace placeholders in template strings with dynamic values.
Example: Single Insertion
{
const template = Lang.getText(nbText.insert.small, { key: language.key });
const items = [{ name: "field", value: "hello world!" }];
return Lang.reduceReplaceTemplateItems(template, items);
}Example: Multiple Insertions
{
const template = Lang.getText(nbText.insert.big, { key: language.key });
const greeting = Lang.getText(nbText.hello, { key: language.key });
const items = [
{ name: "field", value: greeting },
{ name: "name", value: "Alice" }
];
return Lang.reduceReplaceTemplateItems(template, items);
}Custom Placeholder Delimiters
{
const customTemplate = "This is a test: >field<";
const result = Lang.reduceReplaceTemplateItems(
customTemplate,
[{ name: "field", value: "hello world!" }],
{ start: ">", end: "<" }
);
return result
}Checking for Missing Translations
Find missing language keys in your text object:
Lang.listLeavesMissingObjectKeys(nbText, ["en", "fr"]);
// Returns an array of paths to missing translationsString Formatting Helpers
Lang.toTitleCase("welcome to my home");Lang.toSentenceCase("welcome to my home");Advanced: Default Language from URL
Set the default language using a URL parameter (?lang=fr):
queryLanguage = await Lang.getParamFromList({
name: "lang",
list: languages.map((d) => d.key)
});
defaultLangKey = queryLanguage ?? "en";API Reference
| Function | Description |
|---|---|
lg(defaultKey) | Returns a function to fetch text for a default language key. |
getText(textObj, { key }) | Gets text for the specified language key. |
getRegexForNamedInsertion(item, opts) | Returns regex to match placeholders (default: :::item:::). |
reduceReplaceTemplateItems(...) | Replaces all placeholders in a template with provided values. |
listLeavesMissingObjectKeys(obj, keys) | Lists object leaves missing specified keys. |
getParamFromList({ name, list, ... }) | Returns query parameter value if it exists in a provided list. |
toTitleCase(str) | Converts a string to title case. |
toSentenceCase(str) | Converts a string to sentence case. |
Links: Observable Notebook Example
Happy translating!