ICU Messages in Vue with vue-i18n
Implement ICU MessageFormat in Vue.js applications using vue-i18n. Covers plural, select, linked messages, and the Composition API integration.
Detailed Explanation
ICU MessageFormat in Vue.js
vue-i18n is the standard internationalization library for Vue.js applications. While vue-i18n has its own message syntax by default, it supports ICU MessageFormat through the messageCompiler option.
Enabling ICU in vue-i18n
To use ICU MessageFormat syntax with vue-i18n v9+, install the ICU message compiler:
npm install @intlify/message-compiler
Configure in your i18n setup:
import { createI18n } from 'vue-i18n';
const i18n = createI18n({
locale: 'en',
messages: {
en: {
greeting: 'Hello, {name}!',
items: '{count, plural, one {# item} other {# items}}',
pronoun: '{gender, select, male {He} female {She} other {They}}',
},
ja: {
greeting: 'こんにちは、{name}!',
items: '{count, plural, other {#個のアイテム}}',
pronoun: '{gender, select, male {彼は} female {彼女は} other {その人は}}',
},
},
});
Using in Templates
<template>
<p>{{ $t('greeting', { name: userName }) }}</p>
<p>{{ $t('items', { count: itemCount }) }}</p>
</template>
Composition API
import { useI18n } from 'vue-i18n';
export default {
setup() {
const { t } = useI18n();
const message = t('items', { count: 5 });
return { message };
},
};
Plural with Select
const messages = {
en: {
activity: '{gender, select, male {He} female {She} other {They}} posted {count, plural, one {# photo} other {# photos}}.',
},
};
<p>{{ $t('activity', { gender: 'female', count: 3 }) }}</p>
<!-- Output: "She posted 3 photos." -->
vue-i18n's Native Plural Syntax vs ICU
vue-i18n has its own plural syntax using pipe separators:
// vue-i18n native syntax
items: 'no items | one item | {count} items'
// ICU MessageFormat syntax
items: '{count, plural, =0 {no items} one {one item} other {# items}}'
ICU syntax is more powerful because it supports:
- Named plural categories beyond ordinal position
- Nested messages (select inside plural)
- Locale-aware category selection via CLDR rules
- Consistent syntax across all frameworks
Component Interpolation
For messages containing HTML or Vue components:
<i18n-t keypath="tos" tag="p">
<template #link>
<a href="/tos">{{ $t('tosLink') }}</a>
</template>
</i18n-t>
Message Files Organization
src/
locales/
en.json # English messages (ICU format)
ja.json # Japanese messages
de.json # German messages
i18n.ts # vue-i18n configuration
Best Practices
- Use JSON files for messages, not inline objects
- Provide context comments in your message keys for translators
- Test with RTL locales (Arabic, Hebrew) for layout verification
- Use the Vue DevTools i18n plugin for debugging message resolution
- Enable
fallbackWarn: falsein production to suppress console warnings
Use Case
Vue.js developers integrating ICU MessageFormat into their internationalization workflow, especially those migrating from vue-i18n's native plural syntax to the more powerful ICU syntax for better multi-language support.