Search docs
Search modules and symbols
Translations

Translations

Phrase files are the only copy of a plugin’s user-facing strings. Operators reword or recolour a message by editing JSON — no rebuild, no fork. Keys are checked at build against the files that plugin actually loads.

Load, then reply

Nothing is loaded automatically, including the shared common set. s2s build reads translations.load(...) to work out which keys cmd.replyT and Translations.translate accept; a key from a file you did not load is a compile error.

import { command, ADMFLAG, Chat, Translations, translations, HookResult } from '@s2script/sdk';

export function OnPluginStart(): void {
  translations.load('basecomm', 'common');

  command.admin('sm_gag', ADMFLAG.CHAT, (cmd) => {
    cmd.replyT('Usage Gag');
    Chat.toSlot(cmd.callerSlot, Translations.translate(cmd.callerSlot, 'Gagged Player', 1));
    return HookResult.Handled;
  });
}

translations.load is load-window only — it throws after settle. Order is significant: translate takes the first hit within each of its two passes (the client’s language, then English). List your own set before any shared one if you want to override a shared phrase.

A plugin that loads nothing widens PhraseKey to string and compiles unchecked.

Phrase files

One file per set, at translations/<set>.phrases.json in the addon (for example addons/s2script/translations/basecomm.phrases.json). Flat key → English template. {1}, {2}, … are positional slots; {green}, {default}, … are colour tags expanded on output.

{
  "Usage Gag": "Usage: sm_gag <target>",
  "Gagged Player": "{green}[SM]{default} Gagged {1} player."
}

Keys are human-readable English on purpose: an unresolved key renders as the key itself.

A translator adds translations/<code>/<set>.phrases.json — no code change, no rebuild. English (the root file) is the fallback when a language file omits a key.

A missing phrase file renders raw keys. Translations.load warns, naming the set, when a seedless load finds no file.

Colour tags

On CS2, tags match ChatColors names in lowercase ({green}, {default}, {lightred}, …). Expansion happens at output: chat keeps the control byte; console expands then strips, so tags never leak as literal {green}. Unknown tags are deleted (players never see stray braces) and warned once each to the server console.

{1} arguments cannot inject tags — braces are stripped from substituted values.

Chat.toAll is not per-client localized; it uses the operator-settable server default (Translations.setDefaultLanguage). cmd.replyT and Translations.translate(slot, …) resolve for that caller’s language.

Lower-level load

Prefer translations.load(...) — that is what the build reads. Translations.load(name, seed?) is the lower-level form, for a name computed at runtime or a set with an in-code default. A seed is starting content; the file overrides it.

See the translations module and commands.

s2script — Source 2 plugin framework

GitHub