mwg API
    Preparing search index...

    Function createCatalogFormatter

    • The reference MessageFormatter: looks up ${type}.${channel} in the active catalog (setBase/setActive, src/i18n/index.ts), falling back to ${type} alone for a message that reads the same on every channel, then formats through t() - the same interpolation, pluralisation and RTL handling every other message in the game already gets. A catalog missing both keys fails the same observable way t() already does for any key: returning the lookup key itself, rather than throwing or going silent.

      Returns MessageFormatter

      import { setBase, createCatalogFormatter, type SemanticMessage } from '@datamoc/mw_games/i18n';

      setBase({
      locale: 'en',
      direction: 'ltr',
      messages: {
      'combat.damage.log': 'The {target} takes {amount} damage.',
      'combat.damage.compact': '-{amount} HP',
      },
      });

      const formatter = createCatalogFormatter();
      const message: SemanticMessage = { type: 'combat.damage', params: { target: 'gnoll', amount: 7 } };

      console.log(formatter.format(message, 'log')); // 'The gnoll takes 7 damage.'
      console.log(formatter.format(message, 'compact')); // '-7 HP'
      console.log(formatter.format(message, 'debug')); // falls back to the bare type: the key itself, if undeclared
      console.log(formatter.format(message, 'audio')); // 'sounds/sword-hit.wav', or '' when no '<type>.audio' entry exists

      The audio channel is deliberately narrower than the text channels: it resolves only <type>.audio, never falling back to the bare type the way text does. A bare type holding a sentence ('combat.damage': 'combat.damage generic') is not a playable path, so falling back to it would hand the game garbage to load. Sounds that need no per-channel variation are still shared - every text channel already falls back to the same bare type, while audio stays a separate entry a translator never touches and the base language usually owns alone (runtime lookup falls back to the base catalog, so a translated catalog needs no copy of it).