This library contains our plugin for Vue.
Installation#
npm i -S vue-intl
Usage#
Initialize VueIntl plugin with the same IntlConfig documented in @formatjs/intl.
const app = createApp(App)
app.use(
createIntl({
locale: 'en',
defaultLocale: 'en',
messages: {
foo: 'bar',
},
})
)
From there you can use our APIs in 2 ways:
inject#
By specifying inject: {intl: intlKey}, you can use the full IntlFormatters API documented in @formatjs/intl.
Note: intlKey needs to be imported from vue-intl.
Composition API#
We also support Vue's Composition API with provideIntl & useIntl.
const Ancestor = {
setup() {
provideIntl(
createIntl({
locale: 'en',
defaultLocale: 'en',
messages: {
foo: 'Composed',
},
})
)
},
render() {
return h(Descendant)
},
}
const Descendant = {
setup() {
const intl = useIntl()
return () =>
h(
'p',
{},
intl.formatMessage({
id: 'foo',
defaultMessage: 'Hello',
})
)
},
}
Methods#
You can also use our formatters in Vue template by prepending $ like below:
<template>
<p>{{ $formatNumber(3, {style: 'currency', currency: 'USD'}) }}</p>
</template>
We currently support:
$formatMessage$formatDate$formatTime$formatRelativeTime$formatTimeRange$formatDisplayName$formatList
See @formatjs/intl for the full list of API signatures.
Tooling#
formatjs toolchain fully supports vue:
- eslint-plugin-formatjs: This fully supports
.vueand JS/TS. - @formatjs/cli: We now support extracting messages from
.vueSFC files. - babel-plugin-formatjs: Compile messages during bundling for
babel. - @formatjs/ts-transformer: Compile messages during bundling for
TypeScript.
Caveats#
Using ICU in Vue SFC#
Since }} & {{ are special tokens in .vue <template>, this can cause potential conflict with ICU MessageFormat syntax, e.g:
<template>
<p>
{{ $formatMessage({ defaultMessage: '{count, selectordinal, offset:1 one {#}
other {# more}}', }) }}
</p>
</template>
Notice the {# more}} where it ends with }}. This will cause parsing issue in your vue template. In order to work around this issue, we recommend using space to turn }} into } }.
<template>
<p>
{{
$formatMessage({
defaultMessage:
'{count, selectordinal, offset:1 one {#} other {# more} }',
})
}}
</p>
</template>
Typed messages and migration#
Version 8 requires TypeScript 5.4 or newer. Message helpers now share the
@formatjs/intl contracts. Returned descriptors and catalog entries are readonly;
construct a new descriptor instead of mutating one.
import {defineMessage} from 'vue-intl'
const message = defineMessage<{readonly count: number}>(
{id: 'items', defaultMessage: '{count, number} items'},
{typed: true}
)
// intl.formatMessage(message, {count: 3})
defineMessages<Contracts>(catalog, {typed: true}) attaches a separate values
contract to each catalog entry. Helpers return the original objects at runtime.
The generic declares the contract; it does not parse ICU literals.
For formatMessage and $t, the first generic is the values contract and the
second is the rich output type. Move an existing output generic to the second
position. Without generics, typed descriptors retain their checks; ordinary
unregistered descriptors remain permissive. Vue uses its configured VNode output;
Svelte uses strings.