Ink language
Example apps / ink-language / v0.1.0
Node modneeds codeware
A HUD panel in the player's language: the game's own text by key, and the package's own text from locales files with a parameter, plurals and V's gender. It follows a language change in the game.
The simulated game speaks English, so the preview shows the English file; the game's keys show their English words.
// Ink language: the test of phase I2d (docs/ink.md). A HUD panel in the player's language:
// the game's own text by key (the game translates it itself), and this package's own text from
// locales/<language>.json through t(), with a parameter, plurals, V's gender, a key French
// lacks and one no file has. Switch the game's language in its settings and watch it follow.
import { game, ink, t, ui } from 'rednode';
const status = ui.text('Reading the game language...', { tone: 'dim' });
const log = ui.list({ keep: 200 });
function say(text) {
log.push(`${new Date().toLocaleTimeString()} ${text}`);
console.log(text);
}
// The language line is a plain text this mod sets itself; everything else follows by itself.
const language = ink.text('', { style: 'small', tone: 'dim' });
ink.mount(
'hud',
{ anchor: 'left', x: 80, y: -200 },
ink.column(
{ gap: 6 },
ink.text(t('title'), { style: 'label' }),
language,
ink.row({ gap: 12 }, ink.text(t('gameKey'), { style: 'small' }), ink.text('LocKey#15396', { style: 'value' })),
ink.text('', { key: 'UI-ResourceExports-Inventory', style: 'body', tone: 'accent' }),
ink.text(t('reward', { amount: 500 }), { style: 'body' }),
ink.text(t('found', { count: 1 }), { style: 'body' }),
ink.text(t('found', { count: 2 }), { style: 'body' }),
ink.text(t('found', { count: 5 }), { style: 'body' }),
ink.text(t('thanks'), { style: 'body', tone: 'highlight' }),
ink.text(t('onlyEnglish'), { style: 'small', tone: 'dim' }),
ink.text(t('nowhere'), { style: 'small', tone: 'dim' }),
),
);
async function showLanguage(why) {
const { language: name, tag } = await game.language();
const number = new Intl.NumberFormat(tag).format(1234567.89);
language.set({ text: `${name} (${tag}) ${number}` });
status.set({ text: `Game language: ${name} (${tag}). A number in it: ${number}`, tone: 'normal' });
say(`${why}: ${name} (${tag}); ${t('reward', { amount: 500 })}; ${t('thanks')}`);
}
game.on('language', (e) => showLanguage(`The language changed to ${e.language}`));
ui.window({
title: 'Ink language',
anchor: 'right',
x: -40,
y: 0,
width: 520,
height: 420,
closable: true,
children: [
status,
ui.text('The panel is on the HUD at the left. Change the language in the game: Settings, Language, On-screen.', { tone: 'dim' }),
ui.button('Read the language', () => showLanguage('Read')),
log,
],
});
await t.ready;
await showLanguage('Ready');
REDnode runs JavaScript. The rednode package also has TypeScript types, so an editor checks these calls; compile TypeScript to .mjs first.
{
"id": "ink-language",
"name": "Ink language",
"version": "0.1.0",
"author": "Edgemodders",
"description": "The test of the ink API's phase I2d: text in the player's language. A HUD panel with the game's own text by key, the package's own text from locales/en-us.json and locales/fr-fr.json with a parameter, plurals and V's gender, a key French lacks and one no file has. Switch the game's language and watch it follow. Needs Codeware.",
"main": "mod.mjs",
"open": false,
"requires": {
"codeware": ">=1.16"
}
}
The manifest names the package and says how REDnode runs it. Its fields are in Overlay apps.
How it works
An ink text set to "LocKey#15396", or with key: "UI-ResourceExports-Inventory", shows the game's own word in the player's language: the game translates it, and follows a change by itself.
t("reward", { amount: 500 }) takes the text from locales/<language>.json. count picks a plural form and m and f forms follow V's gender. A key French lacks shows in English, and a key no file has shows as itself; each is logged once.
An ink text showing t()'s text is sent again in the new language when the game's language changes. game.language() gives the game's name and the standard tag, for Intl.
What it uses
t() locales/<language>.json LocKey# key game.language game.on("language") Intl
Try this
- Add
locales/de-de.jsonwith your own German words. - Format money with
new Intl.NumberFormat(tag, { maximumFractionDigits: 0 }).
Use it
Copy the files into red4ext/plugins/REDnode/apps/ink-language/ in the game folder, or start your own package from them: change id and name in the manifest first. The whole folder is on GitHub.