or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdindex.mdmessage-processing.md
tile.json

message-processing.mddocs/

Message Processing

Message descriptor types and processing patterns supported by babel-plugin-formatjs for React Intl message extraction and transformation.

Capabilities

Message Descriptor Types

Core interfaces for representing message descriptors and extraction results (available as TypeScript types).

/**
 * Basic message descriptor interface - represents a single translatable message
 */
interface MessageDescriptor {
  /** Unique identifier for the message */
  id: string;
  /** Default message text with ICU MessageFormat syntax support */
  defaultMessage?: string;
  /** Human-readable description for translators (removed during processing) */
  description?: string;
}

/**
 * Extended message descriptor with source location information
 */
interface ExtractedMessageDescriptor extends MessageDescriptor {
  /** Source file path where message was found */
  file?: string;
  /** Start position in source file */
  start?: number;
  /** End position in source file */
  end?: number;
  /** Line number in source file */
  line?: number;
  /** Column number in source file */
  column?: number;
}

/**
 * Result of message extraction process (exported from main module)
 */
interface ExtractionResult<M = Record<string, string>> {
  /** Array of extracted message descriptors */
  messages: ExtractedMessageDescriptor[];
  /** Additional metadata extracted from pragma comments */
  meta: M;
}

Supported Source Patterns

The plugin recognizes and processes these React Intl patterns during Babel transformation:

defineMessages Pattern

Extracts multiple message descriptors from object properties.

import { defineMessages } from 'react-intl';

const messages = defineMessages({
  greeting: {
    id: 'app.greeting',
    defaultMessage: 'Hello {name}!',
    description: 'Greeting with name placeholder'
  },
  farewell: {
    // ID will be auto-generated if not provided
    defaultMessage: 'Goodbye!',
    description: 'Simple farewell message'
  }
});

// After processing (descriptions removed, IDs generated):
const messages = defineMessages({
  greeting: {
    id: 'app.greeting',
    defaultMessage: 'Hello {name}!'
  },
  farewell: {
    id: '[generated-hash]', // Auto-generated based on content
    defaultMessage: 'Goodbye!'
  }
});

defineMessage Pattern

Extracts a single message descriptor from object expression.

import { defineMessage } from 'react-intl';

const message = defineMessage({
  id: 'app.single',
  defaultMessage: 'Single message',
  description: 'Example single message'
});

// After processing:
const message = defineMessage({
  id: 'app.single',
  defaultMessage: 'Single message'
});

formatMessage Calls

Extracts messages from intl.formatMessage() and similar function calls.

// Direct call
intl.formatMessage({
  id: 'app.dynamic',
  defaultMessage: 'Dynamic message',
  description: 'Runtime message'
});

// Function name variants (configurable)
formatMessage({
  defaultMessage: 'Function call message'
});

$t({
  defaultMessage: 'Short-hand function'
});

$formatMessage({
  defaultMessage: 'Vue-style function'
});

JSX FormattedMessage Components

Extracts messages from JSX component attributes.

<FormattedMessage
  id="app.jsx"
  defaultMessage="JSX message with {placeholder}"
  description="Message in JSX component"
  values={{ placeholder: 'value' }}
/>

// After processing (description removed):
<FormattedMessage
  id="app.jsx"
  defaultMessage="JSX message with {placeholder}"
  values={{ placeholder: 'value' }}
/>

Custom Component Names

Process additional component names when configured with additionalComponentNames.

// When additionalComponentNames: ['CustomMessage', 'TransText']
<CustomMessage
  id="app.custom"
  defaultMessage="Custom component message"
  description="From custom component"
/>

<TransText
  defaultMessage="Another custom component"
/>

Custom Function Names

Process additional function names when configured with additionalFunctionNames.

// When additionalFunctionNames: ['translate', '__', 'i18n']
translate({
  id: 'app.translate',
  defaultMessage: 'Translate function message'
});

__({
  defaultMessage: 'Underscore function message'
});

i18n({
  defaultMessage: 'I18n function message'
});

ICU MessageFormat Support

The plugin validates and processes ICU MessageFormat syntax in message strings.

Basic Placeholders

defineMessage({
  defaultMessage: 'Hello {name}!'
});

defineMessage({
  defaultMessage: 'You have {count} items'
});

Plural Messages

defineMessage({
  defaultMessage: 'You have {count, plural, one {# item} other {# items}}'
});

defineMessage({
  defaultMessage: '{itemCount, plural, =0 {no items} =1 {one item} other {# items}}'
});

Select Messages

defineMessage({
  defaultMessage: '{gender, select, male {He} female {She} other {They}} will respond'
});

Date and Number Formatting

defineMessage({
  defaultMessage: 'Today is {today, date, full}'
});

defineMessage({
  defaultMessage: 'Price: {price, number, currency}'
});

Message Transformation

The plugin performs these transformations during processing:

ID Generation

When no id is provided, the plugin generates one based on configuration:

// Input
defineMessage({
  defaultMessage: 'Hello world!'
});

// Output (with default pattern [sha512:contenthash:base64:6])
defineMessage({
  id: 'a1b2c3',
  defaultMessage: 'Hello world!'
});

Description Removal

Descriptions are always removed from the transformed code to reduce bundle size:

// Input
defineMessage({
  id: 'app.greeting',
  defaultMessage: 'Hello!',
  description: 'Greeting message'
});

// Output
defineMessage({
  id: 'app.greeting',
  defaultMessage: 'Hello!'
});

Optional Default Message Removal

When removeDefaultMessage: true, default messages are removed in production:

// Input
defineMessage({
  id: 'app.greeting',
  defaultMessage: 'Hello!'
});

// Output (removeDefaultMessage: true)
defineMessage({
  id: 'app.greeting'
});

AST Pre-parsing

When ast: true, messages are pre-parsed for runtime efficiency:

// Input
defineMessage({
  id: 'app.greeting',
  defaultMessage: 'Hello {name}!'
});

// Output (ast: true)
defineMessage({
  id: 'app.greeting',
  defaultMessage: [
    { type: 'literal', value: 'Hello ' },
    { type: 'argument', value: 'name' },
    { type: 'literal', value: '!' }
  ]
});

Error Handling

The plugin throws compilation errors for:

Invalid ICU Syntax

// This will cause a build error
defineMessage({
  defaultMessage: 'Hello {name!' // Missing closing brace
});

Non-static Values

// This will cause a build error
const dynamicId = 'computed-id';
defineMessage({
  id: dynamicId, // Must be statically evaluable
  defaultMessage: 'Dynamic message'
});

Missing Required Properties

// This will cause a build error
defineMessage({
  description: 'Only description provided' // Need id or defaultMessage
});

Extraction Callbacks

Configure callbacks to receive extracted messages and metadata:

// babel.config.js
{
  plugins: [
    ["babel-plugin-formatjs", {
      onMsgExtracted: (filename, messages) => {
        // Process extracted messages
        console.log(`Found ${messages.length} messages in ${filename}`);
        messages.forEach(msg => {
          console.log(`  ${msg.id}: ${msg.defaultMessage}`);
        });
      },
      onMetaExtracted: (filename, meta) => {
        // Process extracted metadata from pragma comments
        console.log(`Meta from ${filename}:`, meta);
      }
    }]
  ]
}

Pragma Metadata Extraction

Extract metadata from pragma comments in source files:

// @react-intl namespace:user-profile locale:en-US region:america
import { defineMessages } from 'react-intl';

const messages = defineMessages({
  greeting: {
    defaultMessage: 'Hello!'
  }
});

// Extracted metadata: { namespace: 'user-profile', locale: 'en-US', region: 'america' }