This library provides FormatJS internationalization bindings for Svelte 5.

Installation

npm i -S @formatjs/svelte-intl

Usage

Create an intl instance and provide it to the component tree using Svelte's Context API.

Provider setup

In your root component (e.g. App.svelte):

<script>
  import {createIntl, provideIntl} from '@formatjs/svelte-intl'

  const intl = createIntl({
    locale: 'en',
    defaultLocale: 'en',
    messages: {
      greeting: 'Hello, {name}!',
    },
  })

  provideIntl(intl)
</script>

<slot />

Consuming intl

In any descendant component, use useIntl() to access the intl object:

<script>
  import {useIntl} from '@formatjs/svelte-intl'

  const intl = useIntl()
</script>

<p>
  {intl.formatMessage({id: 'greeting'}, {name: 'World'})}
</p>
<p>
  {intl.formatNumber(1000, {style: 'currency', currency: 'USD'})}
</p>
<p>
  {intl.formatDate(new Date(), {dateStyle: 'full'})}
</p>

See @formatjs/intl for the full list of IntlShape methods.

Standalone usage (without context)

You can also use createIntl directly without Svelte context, useful for utility files or server-side code:

import {createIntl, createIntlCache} from '@formatjs/svelte-intl'

const cache = createIntlCache()
const intl = createIntl(
  {
    locale: 'en',
    defaultLocale: 'en',
    messages: {greeting: 'Hello, {name}!'},
  },
  cache
)

intl.formatMessage({id: 'greeting'}, {name: 'World'})

Rich Text / HTML Formatting

Unlike react-intl which uses React elements for rich text, Svelte does not have a VNode-like type. There are two approaches:

Using {@html} (simple)

Use {@html} to render HTML returned by formatMessage:

<script>
  import {useIntl} from '@formatjs/svelte-intl'

  const intl = useIntl()
  // Message: "Welcome, <b>{name}</b>!"
</script>

<p>
  {@html intl.formatMessage(
    {id: 'welcome', defaultMessage: 'Welcome, <b>{name}</b>!'},
    {name: userName}
  )}
</p>

Using rich text callbacks (safe)

For XSS-safe rich text, use formatMessage's tag callbacks to split the message into parts, then render each part with Svelte markup:

<script>
  import {useIntl} from '@formatjs/svelte-intl'

  const intl = useIntl()
  // Message: "Read the <link>docs</link> for more info."

  const parts = intl.formatMessage(
    {
      id: 'info',
      defaultMessage: 'Read the <link>docs</link> for more info.',
    },
    {
      link: (chunks) => `<a href="/docs">${chunks}</a>`,
    }
  )
</script>

<p>{@html parts}</p>

Since T = string in @formatjs/svelte-intl, rich text tag callbacks receive and return strings. You still need {@html} to render the result, but the message structure is preserved for translators.

Message Declaration

Use defineMessages and defineMessage for static analysis and extraction:

<script>
  import {defineMessages, useIntl} from '@formatjs/svelte-intl'

  const messages = defineMessages({
    greeting: {
      id: 'app.greeting',
      defaultMessage: 'Hello, {name}!',
      description: 'Greeting shown on homepage',
    },
    farewell: {
      id: 'app.farewell',
      defaultMessage: 'Goodbye!',
    },
  })

  const intl = useIntl()
</script>

<h1>{intl.formatMessage(messages.greeting, {name: 'World'})}</h1>
<p>{intl.formatMessage(messages.farewell)}</p>

API Reference

ExportDescription
provideIntlSet intl context via Svelte's setContext. Call in a parent component.
useIntlGet intl context via Svelte's getContext. Call in a descendant component.
intlKeyThe Symbol used as the context key.
createIntlCreate an IntlShape instance. Re-exported from @formatjs/intl.
createIntlCacheCreate a cache for createIntl. Re-exported from @formatjs/intl.
defineMessagesIdentity function for message extraction tooling.
defineMessageIdentity function for single message extraction.

All types and error classes from @formatjs/intl are also re-exported.

Tooling

formatjs toolchain supports .svelte files:

Extracting messages

formatjs extract "src/**/*.{ts,svelte}" --out-file lang.json

The CLI extracts messages from:

  • <script> and <script module> blocks
  • Template expressions: {intl.formatMessage(...)}, attribute bindings, {#if}, {#each}, {@const}, etc.