Presets

The built-in presets, how x18n detects them, and the placeholders and extraction templates they add.

A preset is a group of plugins for one i18n library. It tells x18n which calls are translate calls, how namespaces work, which placeholder syntax the messages use, and which code replaces a hard string.

PresetLibraryDetected from
nuxt-i18n@nuxtjs/i18n@nuxtjs/i18n, nuxt-i18n
vue-i18nvue-i18nvue-i18n, vuex-i18n, petite-vue-i18n, vue-i18n-bridge, @intlify/*
fluent-vuefluent-vuefluent-vue, fluent-vue-loader, rollup-plugin-fluent-vue, unplugin-fluent-vue
i18next-shopifyi18next-shopify@shopify/i18next-shopify
react-i18nextreact-i18nextreact-i18next, next-i18next
next-translatenext-translatenext-translate
next-internationalnext-internationalnext-international
i18nexti18nexti18next
next-intlnext-intlnext-intl, use-intl
react-intlreact-intl (FormatJS)react-intl, @formatjs/*
svelte-i18nsvelte-i18n, sveltekit-i18nsvelte-i18n, sveltekit-i18n, @sveltekit-i18n/base
solid-primitives-i18n@solid-primitives/i18n@solid-primitives/i18n
paraglideParaglide JS@inlang/paraglide-js, @inlang/paraglide-sveltekit, @inlang/paraglide-next, @inlang/paraglide-astro, @inlang/paraglide-vite
ngx-translatengx-translate@ngx-translate/core
translocoTransloco@jsverse/transloco, @ngneat/transloco
linguiLingui@lingui/core, @lingui/react, @lingui/macro
ember-intlember-intlember-intl
polyglotPolyglot.jsnode-polyglot
globalizeGlobalizeglobalize
i18n-tages2015-i18n-tages2015-i18n-tag
i18n-jsi18n-jsi18n-js
ui5SAPUI5, OpenUI5@ui5/cli
chrome-extensionChrome and WebExtension i18ndefault_locale in manifest.json, src/manifest.json or public/manifest.json
vscode-extensionVS Code extension APIvscode, @types/vscode
laravelLaravellaravel/framework in composer.json
php-joomlaJoomlajoomla/application, joomla/cms in composer.json
php-gettextgettext in PHPnever: list it in presets
ruby-railsRuby on Railsrails, rails-i18n, railties in Gemfile
jekylljekyll-multiple-languages-pluginjekyll-multiple-languages-plugin in Gemfile
flutterflutter_i18nflutter_i18n in pubspec.yaml
generalnonealways

Detection

With the default presets: 'auto', x18n tests each preset in the order of the table. Most presets apply when the project depends on one of the listed packages. x18n reads the dependencies, dev dependencies and peer dependencies in package.json, and the dependencies in composer.json, pubspec.yaml and Gemfile. The manifests in the parent directories, up to the git root, count too.

More than one preset can apply. Some presets include the plugins of another preset: react-i18next includes everything of i18next, and i18next-shopify includes everything of react-i18next. When two applied presets share a plugin, x18n adds that plugin one time.

A preset can be exclusive. When an exclusive preset applies, x18n tests no preset after it. laravel and php-gettext are exclusive. php-gettext has no detection, so it applies only when you list it.

Run x18n doctor to see the result. Each preset shows as detected, not-detected, listed, or after-exclusive.

List presets

To pick the presets yourself, list them. x18n then applies exactly the listed presets and detects none:

import { general, vueI18n } from '@x18n/cli/presets'
import { defineConfig } from '@x18n/core'

export default defineConfig({
  presets: [vueI18n(), general()],
})

In TS, the presets are functions from @x18n/cli/presets: nuxtI18n, vueI18n, fluentVue, i18nextShopify, reactI18next, nextTranslate, nextInternational, i18next, nextIntl, reactIntl, svelteI18n, solidPrimitivesI18n, paraglide, ngxTranslate, transloco, lingui, emberIntl, polyglot, globalize, i18nTag, i18nJs, ui5, chromeExtension, vscodeExtension, laravel, phpJoomla, phpGettext, rubyRails, jekyll, flutter and general. In YAML and JSON, use the names in the first column of the table. presets: [] turns every preset off.

What a preset adds

Each preset page lists what the preset adds:

  • Translate calls: the callee names that count as translate calls, and where the key, the namespace and the key prefix come from. These become usage.calls.
  • Defaults: namespace rules, derived keys and resource patterns.
  • Placeholders: the syntax of the placeholders in messages.
  • Extraction templates: the code that replaces a hard string.

Your config adds to these defaults. For example, usage.calls in the config adds callees to the ones of the preset. See How x18n merges the config.

Resource defaults

The resource patterns of all applied presets add up. For example, a project with next-intl and ngx-translate uses the patterns of both presets.

  • If your config has resources, x18n uses only your patterns. They replace the patterns of every preset.
  • If the patterns of the presets match no file, x18n guesses the locale directories, as it does without presets. See Locale files.
  • A pattern without {locale}, such as webapp/i18n/i18n.properties, holds the source locale. To give it another locale, set locale on the resource.

Placeholders

A placeholder syntax tells x18n how placeholders look in messages. The placeholder-mismatch check and x18n apply compare the placeholders of each translation with the source value. Translate prompts list them.

SyntaxExampleUsed by
braces{name}, {0}vue-i18n, nuxt-i18n, i18next-shopify, next-international, ui5, vscode-extension, flutter
linked@:key, @.lower:keyvue-i18n, nuxt-i18n
double braces{{name}}, {{name, format}}, {{- raw}}i18next, react-i18next, i18next-shopify, next-translate, ngx-translate, transloco
nesting$t(key)i18next, react-i18next, i18next-shopify
ICU{name}, {count, plural, one {# item} other {# items}}next-intl, react-intl, svelte-i18n, lingui, ember-intl, globalize
fluent{ $name }fluent-vue
percent braces%{name}polyglot, i18n-js, ruby-rails
printf%s, %d, %1$sphp-joomla, php-gettext
colon:namelaravel
dollars$name$chrome-extension

A linked message (@:key) and a nesting placeholder ($t(key)) name another key. That key then counts as used. The invalid-syntax check reports a linked message whose key does not exist, and ICU messages that do not parse or that lack an other case.

Plugins can use all of these syntaxes from @x18n/builtins/placeholders. A YAML plugin can declare a shape such as %{name}.

Extraction templates

x18n extract replaces a hard string with code from a template. A template has these tokens:

TokenBecomes
{key}The new key.
{attr}The attribute name, for attribute kinds.
{args}The arguments of a template string: , { name: user.name }. Empty when there are none.

Each hard string has a kind, which tells where it is:

KindExample
jsx-text<p>Hello</p> in JSX
jsx-attribute<input placeholder="Search" /> in JSX
vue-template-textText in a Vue template
vue-attributeAn attribute in a Vue template
svelte-textText in a Svelte component
svelte-attributeAn attribute in a Svelte component
js-stringA string literal in JS or TS
js-templateA template string in JS or TS

x18n picks the first template that matches the kind (kinds) and the file (files). It tries the templates of extract.templates first, then those of the presets, then these defaults:

KindsTemplate
jsx-text{t('{key}'{args})}
jsx-attribute{attr}={t('{key}'{args})}
vue-template-text{{ $t('{key}'{args}) }}
vue-attribute:{attr}="$t('{key}'{args})"
svelte-text{$t('{key}'{args})}
svelte-attribute{attr}={$t('{key}'{args})}
anyt('{key}'{args})

A template can add imports: lines that x18n adds once to the file when they are missing, such as import { useI18n } from 'vue-i18n'.

x18n.config.ts
import { defineConfig } from '@x18n/core'

export default defineConfig({
  extract: {
    keyPrefix: '{component}',
    templates: [
      {
        template: 'i18n.t(\'{key}\'{args})',
        kinds: ['js-string', 'js-template'],
        files: ['src/server/**'],
        imports: ['import { i18n } from \'~/i18n\''],
      },
    ],
  },
})