Skip to content

Commit d7e2efb

Browse files
committed
docs: add layz-loading section
1 parent 37b7e50 commit d7e2efb

File tree

17 files changed

+785
-623
lines changed

17 files changed

+785
-623
lines changed

.textlintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
'MEMO',
2626
'YAML',
2727
'JSON5',
28+
'HTTP',
2829
'CLI'
2930
]
3031
},

docs/.vitepress/config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ const config = {
107107
text: 'Single File Components',
108108
link: '/advanced/sfc'
109109
},
110+
{
111+
text: 'Lazy Loading',
112+
link: '/advanced/lazy'
113+
},
110114
{
111115
text: 'Message Functions',
112116
link: '/advanced/function'

docs/advanced/lazy.md

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,102 @@
1-
# Lazy loading localization
1+
# Lazy loading
22

3-
TODO:
3+
Loading all of your localization files at once is overkill and unnecessary.
4+
5+
Lazy loading or asynchronously loading the localization files is really easy when using bundler.
6+
7+
Let´s assume we have a project directory similar to the one below:
8+
9+
```
10+
├── dist
11+
├── index.html
12+
├── package.json
13+
├── src
14+
│   ├── App.vue
15+
│   ├── components
16+
│   ├── i18n.js
17+
│   ├── index.css
18+
│   ├── locales
19+
│   │   ├── en.json
20+
│   │   └── ja.json
21+
│   ├── main.js
22+
│   ├── pages
23+
│   │   ├── About.vue
24+
│   │   └── Home.vue
25+
│   └── router.js
26+
```
27+
28+
The `pages` folder is where our arbitrary Vue component files like the `About.vue`, router inits, i18n inits and other reside. The `locales` folder is where all of our localization files reside, and In `i18n.js`, the functions for i18n-related process are defined as follows:
29+
30+
```js
31+
import { createI18n } from 'vue-i18n'
32+
33+
export function setupI18n(options = { locale: 'en' }) {
34+
const i18n = createI18n(options)
35+
setI18nLanguage(i18n, options.locale)
36+
return i18n
37+
}
38+
39+
export function setI18nLanguage(i18n, locale) {
40+
if (i18n.mode === 'legacy') {
41+
i18n.global.locale = locale
42+
} else {
43+
i18n.global.locale.value = locale
44+
}
45+
/**
46+
* NOTE:
47+
* If you need to specify the language setting for headers, such as the `fetch` API, set it here.
48+
* The following is an example for axios.
49+
*
50+
* axios.defaults.headers.common['Accept-Language'] = locale
51+
*/
52+
document.querySelector('html').setAttribute('lang', locale)
53+
}
54+
55+
export async function loadLocaleMessages(i18n, locale) {
56+
// load locale messages
57+
if (!i18n.global.availableLocales.includes(locale)) {
58+
const messages = await import(
59+
/* webpackChunkName: "locale-[request]" */ `./locales/${locale}.json`
60+
)
61+
i18n.global.setLocaleMessage(locale, messages.default)
62+
}
63+
}
64+
```
65+
66+
The following three functions are exported:
67+
68+
- `setupI18n`
69+
- `setI18nLanguage`
70+
- `loadLocaleMessages`
71+
72+
The `setupI18n` function takes the same options as `createI18n`, creates an instance of i18n with those options, executes the `setI18nLanguage` function, and returns the i18n instance.
73+
74+
The `setI18nLanguage` function sets the language by setting the locale of the parameter `i18n` to the value of the parameter `locale`. Besides, this function has the utility of setting the `lang` attribute of the HTML doocument to the value of the parameter `locale`. As noted in the comments, like the HTTP client, you can also set the language
75+
76+
The `loadLocaleMessages` function is what we will actually use to change the languages. Loading the new files is done via the `import` function, which is generously provided by webpack and it allows us to load files dynamically, and because it uses promises we can easily wait for the loading to finish.
77+
78+
You can learn more about the import function in the [Webpack documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports).
79+
80+
Using the `loadLocaleMessages` function is straightforward. A common use case is inside a vue-router beforeEach hook.
81+
82+
Here the code for the vue-router beforeEach hook part of `router.js`:
83+
84+
```js
85+
// navigation guards
86+
router.beforeEach((to, from, next) => {
87+
const locale = to.params.locale
88+
89+
// check locale
90+
if (!SUPPORT_LOCALES.includes(locale)) {
91+
return false
92+
}
93+
94+
// load locale messages
95+
loadLocaleMessages(i18n, locale)
96+
97+
// set i18n language
98+
setI18nLanguage(i18n, locale)
99+
100+
return next()
101+
})
102+
```

examples/composition/fallback/default-format.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
<p>{{ t("messages.hello", { name: 'kazupon' }, 'hello, {name}!') }}</p>
1313
<!-- `default` option (string) -->
1414
<p>
15-
{{ t("messages.hello", { name: 'kazupon' }, { default: 'hi, {name}!' }) }}
15+
{{ t("messages.hello", { name: 'kazupon' }, { default: 'hi, {name}!' })
16+
}}
1617
</p>
1718
<!-- `default` option (true) -->
1819
<p>

examples/lazy-loading/vite/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
"build": "vite build"
88
},
99
"dependencies": {
10-
"vue": "^3.0.0",
11-
"vue-i18n": "^9.0.0-beta.4",
12-
"vue-router": "^4.0.0-beta.13"
10+
"vue": "^3.0.2",
11+
"vue-i18n": "^9.0.0-beta.6",
12+
"vue-router": "^4.0.0-rc.2"
1313
},
1414
"devDependencies": {
15-
"@vue/compiler-sfc": "^3.0.0",
15+
"@vue/compiler-sfc": "^3.0.2",
1616
"vite": "^1.0.0-rc.4"
1717
}
1818
}

examples/lazy-loading/vite/src/App.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,33 @@
22
<nav>
33
<div class="navigation">
44
<router-link :to="{ name: 'home', params: { locale } }">
5-
{{ $t('navigations.home') }}
5+
{{ t('navigations.home') }}
66
</router-link>
77
|
88
<router-link :to="{ name: 'about', params: { locale } }">
9-
{{ $t('navigations.about') }}
9+
{{ t('navigations.about') }}
1010
</router-link>
1111
</div>
1212
<form class="language">
13-
<label>{{ $t('labels.language') }}</label>
13+
<label>{{ t('labels.language') }}</label>
1414
<select v-model="locale">
1515
<option value="en">en</option>
1616
<option value="ja">ja</option>
1717
</select>
1818
</form>
1919
</nav>
20-
<router-view></router-view>
20+
<router-view />
2121
</template>
2222

2323
<script>
2424
import { ref, watch, defineComponent } from 'vue'
2525
import { useRoute, useRouter } from 'vue-router'
26+
import { useI18n } from 'vue-i18n'
2627
2728
export default defineComponent({
2829
name: 'App',
2930
setup() {
30-
const locale = ref('en')
31+
const { t, locale } = useI18n()
3132
const router = useRouter()
3233
const route = useRoute()
3334
@@ -39,7 +40,7 @@ export default defineComponent({
3940
})
4041
})
4142
42-
return { locale }
43+
return { t, locale }
4344
}
4445
})
4546
</script>
Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
import { createI18n } from 'vue-i18n'
2-
import type { I18n, Locale } from 'vue-i18n'
2+
import type { I18n, Locale, I18nOptions, Composer } from 'vue-i18n'
33

4-
import en from './locales/en'
5-
6-
export function setupI18n(locale: Locale = 'en'): I18n {
7-
const i18n = createI18n({
8-
locale,
9-
fallbackLocale: 'en',
10-
messages: {
11-
en
12-
}
13-
}) as I18n
14-
setI18nLanguage(i18n, locale)
4+
export function setupI18n(options: I18nOptions = { locale: 'en' }): I18n {
5+
const i18n = createI18n(options) as I18n
6+
setI18nLanguage(i18n, options.locale!)
157
return i18n
168
}
179

1810
export function setI18nLanguage(i18n: I18n, locale: Locale): void {
19-
i18n.global.locale.value = locale
11+
if (i18n.mode === 'legacy') {
12+
i18n.global.locale = locale
13+
} else {
14+
;((i18n.global as unknown) as Composer).locale.value = locale
15+
}
2016
/**
2117
* NOTE:
2218
* If you need to specify the language setting for headers, such as the `fetch` API, set it here.
@@ -26,3 +22,11 @@ export function setI18nLanguage(i18n: I18n, locale: Locale): void {
2622
*/
2723
document.querySelector('html').setAttribute('lang', locale)
2824
}
25+
26+
export async function loadLocaleMessages(i18n: I18n, locale: Locale) {
27+
// load locale messages
28+
if (!i18n.global.availableLocales.includes(locale)) {
29+
const messages = await import(`./locales/${locale}.js`)
30+
i18n.global.setLocaleMessage(locale, messages.default)
31+
}
32+
}

examples/lazy-loading/vite/src/main.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ import App from './App.vue'
33
import './index.css'
44
import { setupRouter } from './router'
55
import { setupI18n } from './i18n'
6+
import en from './locales/en'
67

7-
const i18n = setupI18n()
8+
const i18n = setupI18n({
9+
legacy: false,
10+
locale: 'en',
11+
fallbackLocale: 'en',
12+
messages: {
13+
en
14+
}
15+
})
816
const router = setupRouter(i18n)
917

1018
const app = createApp(App)

examples/lazy-loading/vite/src/router.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { createRouter, createWebHistory } from 'vue-router'
2-
import { setI18nLanguage } from './i18n'
2+
import { setI18nLanguage, loadLocaleMessages } from './i18n'
33
import type { Router, RouteRecordRaw } from 'vue-router'
4-
import type { I18n, Locale } from 'vue-i18n'
4+
import type { I18n, Locale, Composer } from 'vue-i18n'
55

66
import Home from './pages/Home.vue'
77
import About from './pages/About.vue'
88

99
export function setupRouter(i18n: I18n): Router {
1010
const SUPPORT_LOCALES = ['en', 'ja']
11-
const { global: composer } = i18n
11+
const locale: Locale =
12+
i18n.mode === 'legacy'
13+
? i18n.global.locale
14+
: ((i18n.global as unknown) as Composer).locale.value
1215

1316
// setup routes
1417
const routes: RouteRecordRaw[] = [
@@ -24,7 +27,7 @@ export function setupRouter(i18n: I18n): Router {
2427
},
2528
{
2629
path: '/:pathMatch(.*)*',
27-
redirect: () => `/${composer.locale.value}`
30+
redirect: () => `/${locale}`
2831
}
2932
]
3033

@@ -35,7 +38,7 @@ export function setupRouter(i18n: I18n): Router {
3538
})
3639

3740
// navigation guards
38-
router.beforeEach(async (to, from, next) => {
41+
router.beforeEach((to, from, next) => {
3942
const locale = (to.params as any).locale as Locale
4043

4144
// check locale
@@ -44,10 +47,7 @@ export function setupRouter(i18n: I18n): Router {
4447
}
4548

4649
// load locale messages
47-
if (!composer.availableLocales.includes(locale)) {
48-
const messages = await import(`./locales/${locale}`)
49-
composer.setLocaleMessage(locale, messages.default)
50-
}
50+
loadLocaleMessages(i18n, locale)
5151

5252
// set i18n language
5353
setI18nLanguage(i18n, locale)

0 commit comments

Comments
 (0)