--- url: /guide/migration/breaking10.md --- # Breaking Changes in v10 ## Default enable for JIT compilation **Reason**: CSP problems can be solved and dynamic resources can be supported JIT compilation was introduced in v9.3. It was not enabled by default. Nuxt I18n, which integrates vue-i18n, already has this feature enabled and stable by default. https://i18n.nuxtjs.org/docs/options/compilation#jit To use this feature in Vue I18n, we had to use bundler and `@intlify/unplugin-vue-i18n` to enable the `__INTLIFY_JIT_COMPILATION__` flag. By default in the JIT compilation, this flag is no longer needed starting with v10. If you would not still using the JIT compilation and would be moving up to v10 or later, **you will need to rebuild your application once**. About JIT compilation details, See "[Optimization](../advanced/optimization.md)". ## Change `$t` and `t` overloaded signature for Legacy API mode In Vue I18n v9, it has a different interface from the Composition API mode and Legacy API mode of `$t` and `t` overloaded signature. Especially, `$t` and `t` signature in Legacy API mode has fewer overloaded signatures than in Composition API mode, as shown below: | `$t` and `t` overloaded signatures | Legacy API v9 | Legacy API v10 | Composition API v9 & v10 | | --------------------------------------------------------------------------------------- | ------------- | -------------- | ------------------------ | | `$t(key: Key): TranslateResult;` | ✅ | ✅ | ✅ | | `$t(key: Key, locale: Locale): TranslateResult;` | ✅ | - | - | | `$t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` | ✅ | - | - | | `$t(key: Key, locale: Locale, named: NamedValue): TranslateResult;` | ✅ | - | - | | `$t(key: Key, plural: number): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, plural: number, options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, defaultMsg: string, options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, list: unknown[]): TranslateResult;` | ✅ | ✅ | ✅ | | `$t(key: Key, list: unknown[], plural: number): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, list: unknown[], defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, named: Record): TranslateResult;` | ✅ | ✅ | ✅ | | `$t(key: Key, named: NamedValue, plural: number): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, named: NamedValue, defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `$t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key): TranslateResult;` | ✅ | ✅ | ✅ | | `t(key: Key, locale: Locale): TranslateResult;` | ✅ | - | - | | `t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` | ✅ | - | - | | `t(key: Key, locale: Locale, named: Record): TranslateResult;` | ✅ | - | - | | `t(key: Key, plural: number): TranslateResult; ` | - | ✅ | ✅ | | `t(key: Key, plural: number, options: TranslateOptions): TranslateResult; ` | - | ✅ | ✅ | | `t(key: Key, defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, defaultMsg: string, options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, list: unknown[]): TranslateResult;` | ✅ | ✅ | ✅ | | `t(key: Key, list: unknown[], plural: number): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, list: unknown[], defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, named: Record): TranslateResult;` | ✅ | ✅ | ✅ | | `t(key: Key, named: NamedValue, plural: number): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, named: NamedValue, defaultMsg: string): TranslateResult;` | - | ✅ | ✅ | | `t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` | - | ✅ | ✅ | Starting from v10, Legacy API mode can use the same `$t` and `t` overload signature as Composition API mode. **Reason**: After that migration, when migrating to Composition API mode, we sometimes fall into a pitfall due to the different signature. If you are using the following APIs in Legacy API mode, you must change to another signature because of the breaking changes: * `$t(key: Key, locale: Locale): TranslateResult;` * `$t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` * `$t(key: Key, locale: Locale, named: NamedValue): TranslateResult;` * `t(key: Key, locale: Locale): TranslateResult;` * `t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` * `t(key: Key, locale: Locale, named: NamedValue): TranslateResult;` ### `$t(key: Key, locale: Locale): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` or `$t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` ```vue ``` ### `$t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` ```vue ``` ### `$t(key: Key, locale: Locale, named: NamedValue): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` ```vue ``` ### `t(key: Key, locale: Locale): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', 'ja')) ``` Vue I18n v10 or later: use `t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` or `t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', {}, { locale: 'ja' }) ``` ### `t(key: Key, locale: Locale, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', 'ja', ['dio'])) ``` Vue I18n v10 or later: use `t(key: Key, list: unknown[], options: TranslateOptions): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', ['dio'], { locale: 'ja' })) ``` ### `t(key: Key, locale: Locale, named: NamedValue): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', 'ja', { name: 'dio' })) ``` Vue I18n v10 or later: use `t(key: Key, named: NamedValue, options: TranslateOptions): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('message.hello', { name: 'dio' }, { locale: 'ja' })) ``` ## Deprecate `tc` and `$tc` for Legacy API mode The following APIs are deprecated in v10: * `tc(key: Key | ResourceKeys): TranslateResult;` * `tc(key: Key | ResourceKeys, locale: Locales | Locale): TranslateResult;` * `tc(key: Key | ResourceKeys, list: unknown[]): TranslateResult;` * `tc(key: Key | ResourceKeys, named: Record): TranslateResult;` * `tc(key: Key | ResourceKeys, choice: number): TranslateResult;` * `tc(key: Key | ResourceKeys, choice: number, locale: Locales | Locale): TranslateResult;` * `tc(key: Key | ResourceKeys, choice: number, list: unknown[]): TranslateResult;` * `tc(key: Key | ResourceKeys, choice: number, named: Record): TranslateResult;` * `$tc(key: Key): TranslateResult;` * `$tc(key: Key, locale: Locale): TranslateResult;` * `$tc(key: Key, list: unknown[]): TranslateResult;` * `$tc(key: Key, named: Record): TranslateResult;` * `$tc(key: Key, choice: number): TranslateResult;` * `$tc(key: Key, choice: number, locale: Locale): TranslateResult;` * `$tc(key: Key, choice: number, list: unknown[]): TranslateResult;` * `$tc(key: Key, choice: number, named: Record): TranslateResult;` **Reason**: Legacy API mode has `t` and `$t` support plural interfaces, so they can be replaced. In v10, `tc` and `$tc` still exist to give benefit migration. These will be dropped completely in v11. If you will use them, Vue I18n will output the console warning in your application. ### `tc(key: Key | ResourceKeys): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana')) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', 1)) ``` ### `tc(key: Key | ResourceKeys, locale: Locales | Locale): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', 'ja')) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, plural: number, options: TranslateOptions): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', 1, { locale: 'ja' })) ``` ### `tc(key: Key | ResourceKeys, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', ['dio'])) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, list: unknown[], plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', ['dio'], 1)) ``` ### `tc(key: Key | ResourceKeys, named: Record): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', { name: 'dio' })) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, named: NamedValue, plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', { name: 'dio' }, 1)) ``` ### `tc(key: Key | ResourceKeys, choice: number): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', 2)) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', 2)) ``` ### `tc(key: Key | ResourceKeys, choice: number, locale: Locales | Locale): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', 2, 'ja')) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, plural: number, options: TranslateOptions): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', 2, { locale: 'ja' })) ``` ### `tc(key: Key | ResourceKeys, choice: number, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', 2, ['dio'])) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, list: unknown[], plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', ['dio'], 2)) ``` ### `tc(key: Key | ResourceKeys, choice: number, named: Record): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.tc('banana', 2, { name: 'dio' })) ``` Vue I18n v10 or later: use `t(key: Key | ResourceKeys, named: NamedValue, plural: number): TranslateResult;` ```ts const i18n = createI18n({ legacy: true, // something options ... }) console.log(i18n.global.t('banana', { name: 'dio' }, 2)) ``` ### `$tc(key: Key): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, plural: number): TranslateResult;` ```vue ``` ### `$tc(key: Key, locale: Locale): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, plural: number, options: TranslateOptions): TranslateResult;` ```vue ``` ### `$tc(key: Key, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, list: unknown[], plural: number): TranslateResult;` ```vue ``` ### `$tc(key: Key, named: Record): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, named: NamedValue, plural: number): TranslateResult;` ```vue ``` ### `$tc(key: Key, choice: number): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, plural: number): TranslateResult;` ```vue ``` ### `$tc(key: Key, choice: number, locale: Locale): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, plural: number, options: TranslateOptions): TranslateResult;` ```vue ``` ### `$tc(key: Key, choice: number, list: unknown[]): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, list: unknown[], plural: number): TranslateResult;` ```vue ``` ### `$tc(key: Key, choice: number, named: Record): TranslateResult;` Vue I18n v9.x: ```vue ``` Vue I18n v10 or later: use `$t(key: Key, named: NamedValue, plural: number): TranslateResult;` ```vue ``` ## Drop modulo `%` syntax Named interpolation using modulo `%` is no longer supported in v10. **Reason**: module syntax has already deprecated in v9 with a warning. ### for migration You can use `eslint-plugin-vue-i18n`. `eslint-plugin-vue-i18n` has `@intlify/vue-i18n/no-deprecated-modulo-syntax` rule. https://eslint-plugin-vue-i18n.intlify.dev/rules/no-deprecated-modulo-syntax.html You can fixed with using `eslint --fix` You must have migrated with eslint before upgrading to vue-i18n v10 ## Drop `vue-i18n-bridge` **Reason**: vue-i18n-bridge is a bridge library for migrating vue-i18n from Vue 2 to Vue 3, and Vue 2 is no longer past EOL. ## Drop `allowComposition` option **Reason**: This option already deprecated in warning about being dropped in v10. docs says, https://vue-i18n.intlify.dev/guide/migration/vue3.html#about-supporting This option was added to support the migration from the Legacy API to the composition API on v9. ## Drop `formatter` option on Legacy API **Reason**: This option was deprecated in warning on v9. ## Drop `preserveDirectiveContent` option on Legacy API **Reason**: This option was deprecated in warning on v9. ## Drop `preserve` modifier codes on `v-t` directive **Reason**: This option was deprecated in warning on v9. ## Drop `getChoiceIndex` on Legacy API **Reason**: This option was deprecated in warning on v9. ## Drop translation component `` v8.x compatibility **Reason**: This option was deprecated in warning on v9. ## Drop `te` behavior v8.x compatibility **Reason**: This option was deprecated in warning on v9. This option was introduced in this issue for supporting te behavior v8.x compatibility on v9 --- --- url: /guide/migration/breaking11.md --- # Breaking Changes in v11 ## Deprecate Legacy API mode ### Reason The Legacy API mode was the API mode compatible with v8 for Vue 2. When v9 was released, the Legacy API was provided to smooth the migration from v8 to v9. Legacy API mode will be deprecated in v11, as previous vue-i18n releases have already provided the following to support migration to Composition API mode * Migration from Legacy API mode to Composition API mode: https://vue-i18n.intlify.dev/guide/migration/vue3.html * Composition API usage: https://vue-i18n.intlify.dev/guide/advanced/composition.html For compatibility, Legacy API mode still works in v11, but will be removed entirely in v12, so Legacy API mode will not work after that version. ## Deprecate Custom Directive `v-t` ### Reason The advantage of `v-t` was that it could optimize performance using the vue compiler transform and the pre-translation of `vue-i18n-extension`. This feature was supported from Vue 2. About details see the blog article: https://medium.com/@kazu\_pon/performance-optimization-of-vue-i18n-83099eb45c2d In Vue 3, due to the Composition API, the pre-translation of `vue-i18n-extension` is now limited only for global scope. In addition, Vue 3 Virtual DOM optimization has been introduced, and the optimization provided by `vue-i18n-extension` is no longer very effective. We need to require settings for SSR, the benefits of using `v-t` have disappeared. And DX of templates using `v-t` is not good. Custom directives do not work with key completion in editors (e.g. vscode). For compatibility, `v-t` mode still works in v11, but will be removed entirely in v12, so `v-t` will not work after that version. ### for migration You can use `eslint-plugin-vue-i18n`. `eslint-plugin-vue-i18n` has `@intlify/vue-i18n/no-deprecated-v-t` rule. https://eslint-plugin-vue-i18n.intlify.dev/rules/no-deprecated-v-t.html You must have migrated with eslint before upgrading to vue-i18n v11 ## Drop `tc` and `$tc` for Legacy API mode **Reason**: These APIs had already deprecated in warning about being dropped in v11. docs says, https://vue-i18n.intlify.dev/guide/migration/breaking10.html#deprecate-tc-and-tc-for-legacy-api-mode --- --- url: /guide/migration/breaking.md --- # Breaking Changes in v9 Most of the APIs offered in Vue I18n v9 (for Vue 3) strive to maintain compatibility, to ease the pain of migration from v8 (for Vue 2). But there are still a few breaking changes that you might encounter while migrating your application. This guide is how to adapt your application to make it work with Vue I18n v9. ## APIs ### `new VueI18n` becomes `createI18n` Vue I18n is no longer a class but a set of functions. Instead of writing `new VueI18n()`, you now have to call `createI18n`: Vue I18n v8.x: ```js{2,4,6-8,11} import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) const i18n = new VueI18n({ // ... }) new Vue({ i18n, // ... }) ``` Vue I18n v9 or later: ```js{2,4-6,11} import { createApp } from 'vue' import { createI18n } from 'vue-i18n' const i18n = createI18n({ // ... }) const app = createApp({ // ... }) app.use(i18n) ``` **Reason**: Vue 3 [Global API changes](https://v3-migration.vuejs.org/breaking-changes/global-api.html), and Vue 3 API architecture changes related for component instances. ### Rename to `datetimeFormats` from `dateTimeFormats` Vue I18n v8.x: ```js{3-5} const i18n = new VueI18n({ // ... dateTimeFormats: { // ... } }) ``` Vue I18n v9 or later: ```js{3-5} const i18n = createI18n({ // ... datetimeFormats: { // ... } }) ``` ### Translation API return value The translation API like `$t` and `t` function that return **string** only. Object and array values are no longer returned. Vue I18n v8.x: ```js{24} // e.g. Array structure locale messages const i18n = new VueI18n({ messages: { en: { errors: [ 'invalid argument', // ... 'unexpected errors' ] } } }) // e.g. Error Component const ErrorMessage = { props: { code: { type: Number, required: true } }, template: `

{{ getErrorMessage(code) }}

`, methods: { getErrorMessage(code) { return this.$t('errors')[code] } } } ``` In Vue I18n v9 and later, it changed to getting locale messages with `$tm` / `tm`, and to resolve locale messages with `$rt` or `rt`. The following Composition API example: ```js{24} // e.g. Array structure locale messages const i18n = createI18n({ messages: { en: { errors: [ 'invalid argument', // ... 'unexpected errors' ] } } }) // e.g. Error Component const ErrorMessage = { props: { code: { type: Number, required: true } }, template: `

{{ errors(code) }}

`, setup() { const { tm, rt } = useI18n() const errors = (code) => rt(tm('errors')[code]) return { errors } } } ``` **Reason**: To make **simple obligation** to return the translation results, and it’s also to support TypeScript types. ### Pluralization API return value Similar to *[Translation API return value](#translation-api-return-value)*, the pluralization API like `$tc` and `tc` function that return **string** only. Object and array values are no longer returned. **Reason**: To make **simple obligation** to return the translation results, and it’s also to support TypeScript types. ### Remove `getChoiceIndex` > \[!CAUTION] > `getChoiceIndex` option implementation code is be going to fully remove in v10. To customize the pluralization rules, Vue I18n v8.x extends `getChoiceIndex` of VueI18n class. Vue I18n v8.x: ```js VueI18n.prototype.getChoiceIndex = function (choice, choicesLength) { // this === VueI18n instance, so the locale property exists if (this.locale !== 'ru') { // proceed to the default implementation } if (choice === 0) { return 0; } const teen = choice > 10 && choice < 20; const endsWithOne = choice % 10 === 1; if (!teen && endsWithOne) { return 1; } if (!teen && choice % 10 >= 2 && choice % 10 <= 4) { return 2; } return (choicesLength < 4) ? 2 : 3; } ``` In Vue I18n v9 and later, you can customize it with the following options: Legacy API mode: ```js{21-24} import { createI18n } from 'vue-i18n' function customRule(choice, choicesLength, orgRule) { if (choice === 0) { return 0 } const teen = choice > 10 && choice < 20 const endsWithOne = choice % 10 === 1 if (!teen && endsWithOne) { return 1 } if (!teen && choice % 10 >= 2 && choice % 10 <= 4) { return 2 } return choicesLength < 4 ? 2 : 3 } const i18n = createI18n({ // ... pluralizationRules: { ru: customRule, // ... }, // ... }) ``` Composition API mode: ```js{23-26} import { useI18n } from 'vue-i18n' function customRule(choice, choicesLength, orgRule) { if (choice === 0) { return 0 } const teen = choice > 10 && choice < 20 const endsWithOne = choice % 10 === 1 if (!teen && endsWithOne) { return 1 } if (!teen && choice % 10 >= 2 && choice % 10 <= 4) { return 2 } return choicesLength < 4 ? 2 : 3 } const MyComp = { setup() { const { t } = useI18n({ // ... pluralRules: { ru: customRule, // ... }, // ... }) // ... } } ``` **Reason**: VueI18n class has been removed. ### Change `warnHtmlInMessage` option default value In Vue I18n v8.x, the value of `warnHtmlInMessage` was `"off"`. Therefore, by default, no warning is output to the console even if the message contains HTML. In Vue I18n v9 and later, change the default values as follows: * Legacy API mode: `warnHtmlInMessage` property: `"warn"` * Composition API mode: `warnHtmlMessage` boolean property, default `true` In development mode, unless you change this value, you will **receive the warning to the console by default**. In production mode, it does not detect if the message contains HTML to maximize performance. **Reason**: to make stronger security for locale messages ### Version info Version information is now accessible in import syntax instead of the VueI18n class static property. Vue I18n v8.x: ```js import VueI18n from 'vue-i18n' console.log(VueI18n.version) ``` Vue I18n v9 or later: ```js import { VERSION } from 'vue-i18n' console.log(VERSION) ``` **Reason**: Tree shaking optimization, and VueI18n class has been removed. ### Remove Intl availability Removed as major browsers now support the [ECMAScript Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). Vue I18n v8.x: ```js import VueI18n from 'vue-i18n' console.log(VueI18n.availability) ``` **Reason**: IE9 end of life, and VueI18n class has been removed. ### Remove Custom formatter > \[!CAUTION] > `formatter` option implementation code is be going to fully remove in v10. > As an alternative, vue-i18n has the [custome message format](../advanced/format.md) as an experimental feature. **Reason**: Due to hard to provide custom formats in the new compiler and runtime APIs. We are planning to support it in the next major version to support in these APIs. If you would like to use ICU message format, you can use the [@formatjs/vue-intl](https://formatjs.io/docs/vue-intl/) ### Remove `preserveDirectiveContent` option > \[!CAUTION] > `preserveDirectiveContent` option implementation code is be going to fully remove in v10. The `v-t` directive for Vue 3 now preserves the default content. Therefore, this option and its properties have been removed from the VueI18n instance. Vue I18n v8.x: ```js import VueI18n from 'vue-i18n' const i18n = new VueI18n({ // ... preserveDirectiveContent: true, // ... }) ``` **Reason**: Keep the content to element with `v-t` directive ## Message Format Syntax ### Remove array-like object for List interpolation In Vue I18n v8.x, List interpolation could use an array-like object as a parameter, such as the following: ```js import VueI18n from 'vue-i18n' const i18n = new VueI18n({ // ... messages: { en: { greeting: 'hello, {0}!' } }, // ... }) ``` ```html

{{ $t('greeting', { '0': 'kazupon' }) }}

``` In Vue I18n v9 and later, you can’t use array-like objects for list interpolation, you have to use array: ```html

{{ $t('greeting', ['kazupon']) }}

``` **Reason**: provide a Translation API with a consistent argument I/F ### Special character handling The messages that can be translated by Vue I18n can be highly translated using message format syntax, such as the following: ``` @.caml:{'no apples'} | {0} apple | {n} apples ``` The message format syntax can be expressed using the following special characters that are used: * `{`, `}`, `@`, `$`, `|` Since Vue I18n v9 and later, message format syntax is now handled by the message format compiler, if you use these special characters as part of a message, the message will occur error at compile. If you want to use these special characters, you **have to use literal interpolation**. ``` // e.g. `@` use-case for mail address {emailIdentity}{'@'}{emailDomain} ``` **Reason**: In order for the message format compiler to correctly handle the special characters of the syntax used in the message format syntax, it is necessary to limit them. ### Remove brackets grouping for Linked messages In Vue I18n v8.x, the distinction was made between key references in Linked messages and messages using brackets `()` to distinguish between them. Vue I18n v8.x: ```js{5} const messages = { en: { message: { dio: 'DIO', linked: 'There\'s a reason, you lost, @:(message.dio).' } } } ``` In Vue I18n v9 and later, brackets are no longer needed as the message format compiler allows you to handle **named, list, and literal interpolations**. Vue I18n v9 or later: ```js const messages = { en: { message: { dio: 'DIO', linked: "There\'s a reason, you lost, @:{'message.dio'}." } } } ``` ## `v-t` directive ### Remove `preserve` modifier > \[!CAUTION] > `preserve` modifier implementation code is be going to fully remove in v10. Similar to *[Remove `preserveDirectiveContent` option](#remove-preservedirectivecontent-option)*, the `v-t` directive for Vue 3 now preserves the default content. Therefore, `preserve` modifier and it’s have been removed from `v-t` directive. Vue I18n v8.x: ```html

``` **Reason**: Keep the content to element with `v-t` directive ## Translation component ### Rename to `i18n-t`from `i18n` The tag name of the translation component (called *i18n functional component* in Vue I18n v8.x) has been changed. Vue I18n v8.x: ```html ``` Vue I18n v9 or later: ```html ``` **Reason**: tag name same i18n custom blocks ``, so it’s confusing with the block names and prone to mistakes in SFC. ### `tag` prop is optional In Vue I18n v8.x, `tag` prop could be used to render child elements without the root element by specifying a tag name and the `Boolean` value `false`. Vue I18n v8.x: ```html{1,3} hello! ``` Since Vue I18n v9 or later, you can do the same by omitting the `tag` prop. Vue I18n v9 or later: ```html{1,3} hello! ``` **Reason**: Since Vue 3 now supports Fragments ### Rename to `keypath` prop from `path` prop Vue I18n v8.x: ```html ``` Vue I18n v9 or later: ```html ``` ### Remove place syntax with `place` attr and `places` prop In Vue I18n v9 and later, the `place` attr and `places` prop have been removed from component interpolation. Vue I18n v8.x: ```html {{ refundLimit }} {{ $t('refund') }} ``` Vue I18n v9 or later: ```html