|
| 1 | +# Nuxt 3 integration |
| 2 | + |
| 3 | +We will introduce Vue I18n integration for Nuxt 3. |
| 4 | + |
| 5 | +The following is a tutorial on setting up a Nuxt 3 application from the initial configuration. |
| 6 | + |
| 7 | +If you go through this tutorial, you can learn how to integrate Vue I18n with Nuxt plugin. |
| 8 | + |
| 9 | +## Requirements |
| 10 | + |
| 11 | +The Node.js requirement for this tutorial is the same environment as Nuxt 3. |
| 12 | + |
| 13 | +Please check [here](https://v3.nuxtjs.org/getting-started/quick-start#prerequisites) for Node.js version of Nuxt 3. |
| 14 | + |
| 15 | +## Example codes |
| 16 | + |
| 17 | +You can get the code for the tutorial below on [examples/frameworks/nuxt3](https://github.com/intlify/vue-i18n-next/tree/master/examples/framework/nuxt3). |
| 18 | + |
| 19 | +## Setup vue-i18n on Nuxt 3 Application |
| 20 | + |
| 21 | +We will now set up the initial environment for using Vue I18n with Nuxt 3. |
| 22 | + |
| 23 | +### Create Nuxt 3 application |
| 24 | + |
| 25 | +Run the following command to create a Nuxt 3 application: |
| 26 | + |
| 27 | +```sh |
| 28 | +npx nuxi init nuxt3-app-vue-i18n |
| 29 | +``` |
| 30 | + |
| 31 | +We will have run the above command, it will be created Nuxt 3 initial project with the following directory structure: |
| 32 | + |
| 33 | +``` |
| 34 | +cd nuxt3-app-vue-i18n |
| 35 | +tree -L 1 |
| 36 | +. |
| 37 | +├── README.md |
| 38 | +├── app.vue |
| 39 | +├── node_modules |
| 40 | +├── nuxt.config.ts |
| 41 | +├── package-lock.json |
| 42 | +├── package.json |
| 43 | +└── tsconfig.json |
| 44 | +``` |
| 45 | + |
| 46 | +### Install Vue I18n |
| 47 | + |
| 48 | +Install Vue I18n with the following command: |
| 49 | + |
| 50 | +```sh |
| 51 | +npm install --save-dev vue-i18n |
| 52 | +``` |
| 53 | + |
| 54 | +### Setup Nuxt plugin |
| 55 | + |
| 56 | +We will set up the Nuxt plugin. |
| 57 | + |
| 58 | +Create a `plugins` directory as follows: |
| 59 | + |
| 60 | +```sh |
| 61 | +mkdir plugins |
| 62 | +``` |
| 63 | + |
| 64 | +Next, create a Nuxt plugin file to implement for setting up Vue I18n. |
| 65 | + |
| 66 | +```sh |
| 67 | +touch plugins/i18n.ts |
| 68 | +``` |
| 69 | + |
| 70 | +When we have created it, edit it with the below codes: |
| 71 | + |
| 72 | +```ts |
| 73 | +import { createI18n } from 'vue-i18n' |
| 74 | + |
| 75 | +export default defineNuxtPlugin(({ vueApp }) => { |
| 76 | + const i18n = createI18n({ |
| 77 | + legacy: false, |
| 78 | + globalInjection: true, |
| 79 | + locale: 'en', |
| 80 | + messages: { |
| 81 | + en: { |
| 82 | + hello: 'Hello, {name}!' |
| 83 | + } |
| 84 | + } |
| 85 | + }) |
| 86 | + |
| 87 | + vueApp.use(i18n) |
| 88 | +}) |
| 89 | +``` |
| 90 | + |
| 91 | +We aim to set up Vue I18n in the implementation here. |
| 92 | + |
| 93 | +Configure up locale resources to localize a Nuxt 3 application is described in the next section. |
| 94 | + |
| 95 | +### Run the Nuxt 3 application |
| 96 | + |
| 97 | +Let's see if Vue I18n works with Nuxt 3. |
| 98 | + |
| 99 | +We will edit `app.vue` of the setup Nuxt 3 application as follows: |
| 100 | + |
| 101 | +```diff |
| 102 | + <template> |
| 103 | + <div> |
| 104 | +- <NuxtWelcome /> |
| 105 | ++ <h1>{{ $t('hello', { name: 'vue-i18n' }) }}</h1> |
| 106 | + </div> |
| 107 | + </template> |
| 108 | +``` |
| 109 | + |
| 110 | +We have edited and saved, run the following command to run the Nuxt 3 application at local: |
| 111 | + |
| 112 | +```sh |
| 113 | +npm run dev |
| 114 | +``` |
| 115 | + |
| 116 | +After we will run the command and access to `http://localhost:3000`, you can see the display similar to the following: |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | +## Localize your Nuxt 3 application |
| 121 | + |
| 122 | +So far we have been able to integrate Vue I18n into our Nuxt 3 application. |
| 123 | +Next, we will implement language switching and import locale resources from outside. |
| 124 | + |
| 125 | +By implementing language switching, we can i18n our Nuxt 3 application. Also, when we will be separating locale resources from the source code and externalizing them, we can be localized in a separate workflow using the Localization service. |
| 126 | + |
| 127 | +In the following sections, we will work on Nuxt 3 applications that support English, French, and Japanese. |
| 128 | + |
| 129 | +### Add language switching |
| 130 | + |
| 131 | +We will add language switching feature to `app.vue` as follows: |
| 132 | + |
| 133 | +```diff |
| 134 | + <template> |
| 135 | + <div> |
| 136 | + <h1>{{ $t('hello', { name: 'vue-i18n' }) }}</h1> |
| 137 | ++ <form> |
| 138 | ++ <label for="locale-select">{{ $t('language') }}: </label> |
| 139 | ++ <select id="locale-select" v-model="$i18n.locale"> |
| 140 | ++ <option value="en">en</option> |
| 141 | ++ <option value="fr">fr</option> |
| 142 | ++ <option value="ja">ja</option> |
| 143 | ++ </select> |
| 144 | ++ </form> |
| 145 | + </div> |
| 146 | + </template> |
| 147 | +``` |
| 148 | + |
| 149 | +Language switching is implemented using the `select` element on `form`. |
| 150 | +The value of each option is defined as the value of the locale code, which will be explained later in the externalization of locale resources. |
| 151 | + |
| 152 | +The value of each option defines the value of the locale code, which will be explained later in the externalization of locale resources. |
| 153 | + |
| 154 | +### Externalize locale resources |
| 155 | + |
| 156 | +We will define the locale resources as externalizing. |
| 157 | + |
| 158 | +There are several file formats for resources supported by Vue I18n, so we will use the json format in here. |
| 159 | + |
| 160 | +These are managed separately from the directories managed by Nuxt 3 by creating `locales` directories as follows: |
| 161 | + |
| 162 | +```sh |
| 163 | +mkdir locales |
| 164 | +``` |
| 165 | + |
| 166 | +Then, We will have created a file defining locale resources for English, French, and Japanese as follows: |
| 167 | + |
| 168 | +```sh |
| 169 | +touch locales/en.json # for english |
| 170 | +touch locales/fr.json # for french |
| 171 | +touch locales/ja.json # for japanese |
| 172 | +``` |
| 173 | + |
| 174 | +And more then, We will have saved each created locale resource file for each language as follows: |
| 175 | + |
| 176 | +For english at `locales/en.json`: |
| 177 | +```json |
| 178 | +{ |
| 179 | + "hello": "Hello, {name}!", |
| 180 | + "language": "Language" |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +For french at `locales/fr.json`: |
| 185 | +```json |
| 186 | +{ |
| 187 | + "hello": "Bonjour, {name}!", |
| 188 | + "language": "Langue" |
| 189 | +} |
| 190 | +``` |
| 191 | + |
| 192 | +For japanese at `locales/ja.json`: |
| 193 | +```json |
| 194 | +{ |
| 195 | + "hello": "こんにちは、{name}!", |
| 196 | + "language": "言語" |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +### Import locale resources |
| 201 | + |
| 202 | +We will import locale resources that is defined in the `locales` directory for use with Vue I18n. |
| 203 | + |
| 204 | +And then, change `plugins/i18n.ts` as follows: |
| 205 | + |
| 206 | +```diff |
| 207 | + import { createI18n } from 'vue-i18n' |
| 208 | ++import en from '../locales/en.json' |
| 209 | ++import fr from '../locales/fr.json' |
| 210 | ++import ja from '../locales/ja.json' |
| 211 | + |
| 212 | + export default defineNuxtPlugin(({ vueApp }) => { |
| 213 | + const i18n = createI18n({ |
| 214 | + legacy: false, |
| 215 | + globalInjection: true, |
| 216 | + locale: 'en', |
| 217 | + messages: { |
| 218 | +- en: { |
| 219 | +- hello: "Hello, {name}!" |
| 220 | +- } |
| 221 | ++ en, |
| 222 | ++ fr, |
| 223 | ++ ja |
| 224 | + } |
| 225 | + }) |
| 226 | + |
| 227 | + vueApp.use(i18n) |
| 228 | + }) |
| 229 | +``` |
| 230 | + |
| 231 | +It’s set locale resources for each imported language to `messages` option, so you can manage locale resources with separating from code in the `locales` directory. It also facilitates integration with the localization service. |
| 232 | + |
| 233 | +Let's run `npm run dev` to see if the fixes so far work. When we will have run the command and have be access to `http://localhost:3000`, you can see the display similar to the following: |
| 234 | + |
| 235 | + |
| 236 | + |
| 237 | +Your Nuxt 3 application is now ready for basic internationalization! |
| 238 | + |
| 239 | +## Optimize with `@intlify/unplugin-vue-i18n` |
| 240 | + |
| 241 | +So far, you have been able to use Vue I18n to support language switching for your Nuxt 3 application. Also, by externalizing the locale resources, you have separated them from the code, making it easier to manage locale resources and integrate with the localization service. |
| 242 | + |
| 243 | +However, as described in the [Optimization](../advanced/optimization), your Nuxt 3 application prepared so far is not optimized for bundle size. |
| 244 | + |
| 245 | +Since Vue I18n v9, the message compiler allows pre-compiling of locale resources for improved performance, but has not yet been optimized for that performance. |
| 246 | + |
| 247 | +Finally, we would to introduce with you [@intlify/unplugin-vue-i18n](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n) a Vue I18n to optimize performance. |
| 248 | + |
| 249 | +### Install `@intlify/unplugin-vue-i18n` |
| 250 | + |
| 251 | +```sh |
| 252 | +npm install --save-dev @intlify/unplugin-vue-i18n |
| 253 | +``` |
| 254 | + |
| 255 | +### Configure Nuxt config |
| 256 | + |
| 257 | +Configure `nuxt.config.ts` like the below: |
| 258 | + |
| 259 | +```diff |
| 260 | + import { defineNuxtConfig } from 'nuxt' |
| 261 | ++import { resolve, dirname } from 'node:path' |
| 262 | ++import { fileURLToPath } from 'url' |
| 263 | ++import VueI18nVitePlugin from '@intlify/unplugin-vue-i18n/vite' |
| 264 | + |
| 265 | + // https://v3.nuxtjs.org/api/configuration/nuxt.config |
| 266 | + export default defineNuxtConfig({ |
| 267 | ++ vite: { |
| 268 | ++ plugins: [ |
| 269 | ++ VueI18nVitePlugin({ |
| 270 | ++ include: [ |
| 271 | ++ resolve(dirname(fileURLToPath(import.meta.url)), './locales/*.json') |
| 272 | ++ ] |
| 273 | ++ }) |
| 274 | ++ ] |
| 275 | ++ } |
| 276 | + }) |
| 277 | +``` |
| 278 | + |
| 279 | +The bundler for Nuxt 3 is vite by default. So we will use the `vite` option here for optimization. |
| 280 | + |
| 281 | +In `vite.plugins`, the plugin for `@intlify/unplugin-vue-i18n` is configured. As an option for this plugin, the `include` option specifies locale resources in json format placed in the `locales` directory. This allows `@intlify/unplugin-vue-i18n` to pre-compile locale resources at bundle time using Vue I18n message compiler internally. This improves the translation performance of Vue I18n and consequently the rendering performance of Nuxt 3 applications. |
| 282 | + |
| 283 | +### Inside of bundling with optimization |
| 284 | + |
| 285 | +When you have finished the setup, let’s run `npm run dev` to check it out! |
| 286 | + |
| 287 | +When you will access to `http://localhost:3000`, the behavior of the Nuxt 3 application remains the same, but there is a change in the bandwidth of the Nuxt 3 application. |
| 288 | + |
| 289 | +The following is a comparison of bundle sizes measured in the network tab of devtools with and without `@intlify/unplugin-vue-i18n`: |
| 290 | + |
| 291 | + |
| 292 | + |
| 293 | +The area highlighted in blue is the code bundled by vite. |
| 294 | + |
| 295 | +By setting up this plugin, the plugin will internally set up a Vue I18n module that is runtime-only. Specifically, vite config `resolve.alias`, set the `vue-i18n` alias to use only the Vue I18n runtime (`vue-i18n/dist/vue-i18n.runtime.esm-bundler.js`). This setting reduces the bundle size since the message compiler used by Vue I18n is not included. |
| 296 | + |
| 297 | +About details, see `@intlify/unplugin-vue-i18n` [docs](https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#runtimeonly) |
| 298 | + |
| 299 | +Also, you can see the changing in the bandling of locale resources. |
| 300 | + |
| 301 | +Code for locale resources, depending on whether or not the `@intlify/unplugin-vue-i18n` plugin to `vite.plugins` is set. Below: |
| 302 | + |
| 303 | + |
| 304 | + |
| 305 | +Without the `@intlify/unplugin-vue-i18n` plugin to `vite.plugins`, locale resources are bundled as **json**, but with this plugin set, locale resources are **converted from json to JavaScript code** for bandwidth. |
| 306 | + |
| 307 | +Vue I18n just call the functions! if the locale resource is a function, since it has already been compiled. |
| 308 | + |
| 309 | +In this tutorial, the Nuxt 3 application is small, so we can not enough experience the performance of this optimization, but as the application gets larger, it will benefit from it. |
0 commit comments