From 9770a6fec69c72e368870ee1cddabd2926b56108 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 16 Nov 2023 11:25:48 +0100 Subject: [PATCH] install vue-i18n --- .eslintrc.json | 4 -- README.md | 6 ++- package-lock.json | 61 ++++++++++++++++++++++++++++ package.json | 4 +- renderer/app.ts | 6 ++- renderer/i18n.ts | 10 +++++ renderer/vuetify.ts | 17 ++++++-- src/locales/de.ts | 6 +++ src/locales/en.ts | 6 +++ src/pages/index/ClickCounter.spec.ts | 2 +- src/pages/index/ClickCounter.vue | 2 +- tests/unit.setup.ts | 6 +++ vitest.config.ts | 1 + 13 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 renderer/i18n.ts create mode 100644 src/locales/de.ts create mode 100644 src/locales/en.ts create mode 100644 tests/unit.setup.ts diff --git a/.eslintrc.json b/.eslintrc.json index f620c98..c58c1d5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -50,10 +50,6 @@ "error", "unix" ], - "quotes": [ - "error", - "single" - ], "semi": [ "error", "never" diff --git a/README.md b/README.md index 12bb0c1..767b5c5 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![vike][badge-vike-img]][badge-vike-href] [![vuetify][badge-vuetify-img]][badge-vuetify-href] [![pinia][badge-pinia-img]][badge-pinia-href] +[![vue-i18n][badge-vue-i18n-img]][badge-vue-i18n-href] [![eslint][badge-eslint-img]][badge-eslint-href] [![vitest][badge-vitest-img]][badge-vitest-href] [![storybook][badge-storybook-img]][badge-storybook-href] @@ -48,9 +49,9 @@ The following commands are available: - [x] storybook - [x] eslint - [x] vitest +- [x] vue-i18n - [ ] figma - [ ] chromatic -- [ ] localization? - [ ] documentation? - [ ] docker - [ ] github actions @@ -87,6 +88,9 @@ See [vite-plugin-ssr-vuetify](https://github.com/brillout/vite-plugin-ssr-vuetif [badge-pinia-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.pinia&label=pinia&color=green [badge-pinia-href]: https://pinia.vuejs.org/ +[badge-vue-i18n-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.vue-i18n&label=vue-i18n&color=green +[badge-vue-i18n-href]: https://vue-i18n.intlify.dev/ + [badge-eslint-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.eslint&label=eslint&color=yellow [badge-eslint-href]: https://eslint.org/ diff --git a/package-lock.json b/package-lock.json index 097618a..7332889 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "vike": "^0.4.145", "vite": "^4.4.9", "vue": "^3.3.4", + "vue-i18n": "^9.7.0", "vuetify": "^3.4.0" }, "devDependencies": { @@ -2946,6 +2947,47 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@intlify/core-base": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.7.0.tgz", + "integrity": "sha512-1tBnfnCI23jXqGW15cagCjn2GgD487VST1dMG8P5LRzrSfx+kUzqFyTrjMNIwgq1tVaF4HnDpFMUuyrzTLKphw==", + "dependencies": { + "@intlify/message-compiler": "9.7.0", + "@intlify/shared": "9.7.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.7.0.tgz", + "integrity": "sha512-/YdZCio2L2tCM5bZ2eMHbSEIQNPh1QqvZIOLI/yCVKXLscis7O0SsR2nmuU/DfCJ3iSeI8juw82C2wLvfsAeww==", + "dependencies": { + "@intlify/shared": "9.7.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.7.0.tgz", + "integrity": "sha512-PUkEuk//YKu4CHS5ah3mNa3XL/+TZj6rAY/6yYN+GCNFd2u+uWUkeuwE4Q6t8dydRWlErOePHHS0KyNoof/oBw==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -18177,6 +18219,25 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/vue-i18n": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.7.0.tgz", + "integrity": "sha512-8Z8kSz9U2juzuAf+6mjW1HTd5pIlYuFJZkC+HvYOglFdpzwc2rTUGjxKwN8xGdtGur1MFnyJ44TSr+TksJtY8A==", + "dependencies": { + "@intlify/core-base": "9.7.0", + "@intlify/shared": "9.7.0", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vue-inbrowser-compiler-independent-utils": { "version": "4.71.1", "resolved": "https://registry.npmjs.org/vue-inbrowser-compiler-independent-utils/-/vue-inbrowser-compiler-independent-utils-4.71.1.tgz", diff --git a/package.json b/package.json index 954ffa9..1050820 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "pinia", "storybook", "eslint", - "vitest" + "vitest", + "vue-i18n" ], "author": "Ulf Gebhardt", "license": "Apache-2.0", @@ -60,6 +61,7 @@ "vike": "^0.4.145", "vite": "^4.4.9", "vue": "^3.3.4", + "vue-i18n": "^9.7.0", "vuetify": "^3.4.0" }, "devDependencies": { diff --git a/renderer/app.ts b/renderer/app.ts index cb5eb43..70385e3 100644 --- a/renderer/app.ts +++ b/renderer/app.ts @@ -2,7 +2,8 @@ import { createSSRApp, defineComponent, h } from 'vue' import PageShell from './PageShell.vue' import { setPageContext } from './usePageContext' import type { Component, PageContext, PageProps } from './types' -import vuetify from './vuetify' +import i18n from './i18n' +import CreateVuetify from './vuetify' import { createPinia } from 'pinia' export { createApp } @@ -25,7 +26,8 @@ function createApp(Page: Component, pageProps: PageProps | undefined, pageContex const pinia = createPinia() const app = createSSRApp(PageWithLayout) app.use(pinia) - app.use(vuetify) + app.use(i18n) + app.use(CreateVuetify(i18n)) // Make pageContext available from any Vue component setPageContext(app, pageContext) diff --git a/renderer/i18n.ts b/renderer/i18n.ts new file mode 100644 index 0000000..6093b29 --- /dev/null +++ b/renderer/i18n.ts @@ -0,0 +1,10 @@ +import { createI18n } from 'vue-i18n' +import de from '../src/locales/de' +import en from '../src/locales/en' + +export default createI18n({ + legacy: false, // Vuetify does not support the legacy mode of vue-i18n + locale: 'de', + fallbackLocale: 'en', + messages: { de, en }, +}) diff --git a/renderer/vuetify.ts b/renderer/vuetify.ts index 2640009..ddb4b0b 100644 --- a/renderer/vuetify.ts +++ b/renderer/vuetify.ts @@ -4,7 +4,16 @@ import { createVuetify } from 'vuetify' import * as components from 'vuetify/lib/components/index.mjs' import * as directives from 'vuetify/lib/directives/index.mjs' -export default createVuetify({ - components, - directives, -}) +import { createVueI18nAdapter } from 'vuetify/locale/adapters/vue-i18n' + +import { useI18n } from 'vue-i18n' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default (i18n: any) => + createVuetify({ + locale: { + adapter: createVueI18nAdapter({ i18n, useI18n }), + }, + components, + directives, + }) diff --git a/src/locales/de.ts b/src/locales/de.ts new file mode 100644 index 0000000..46135f0 --- /dev/null +++ b/src/locales/de.ts @@ -0,0 +1,6 @@ +import { de as $vuetify } from 'vuetify/locale' + +export default { + counter: 'Zähler', + $vuetify, +} diff --git a/src/locales/en.ts b/src/locales/en.ts new file mode 100644 index 0000000..69dab4c --- /dev/null +++ b/src/locales/en.ts @@ -0,0 +1,6 @@ +import { en as $vuetify } from 'vuetify/locale' + +export default { + counter: 'Counter', + $vuetify, +} diff --git a/src/pages/index/ClickCounter.spec.ts b/src/pages/index/ClickCounter.spec.ts index 8eaa13a..648bb9c 100644 --- a/src/pages/index/ClickCounter.spec.ts +++ b/src/pages/index/ClickCounter.spec.ts @@ -7,6 +7,6 @@ describe('ClickCounter', () => { it('renders Button with a Counter of 0', () => { expect(wrapper.find('v-btn').exists()).toBe(true) - expect(wrapper.text()).toBe('Counter 0') + expect(wrapper.text()).toBe("$t('counter') 0") }) }) diff --git a/src/pages/index/ClickCounter.vue b/src/pages/index/ClickCounter.vue index 458a3f9..63a3ac2 100644 --- a/src/pages/index/ClickCounter.vue +++ b/src/pages/index/ClickCounter.vue @@ -1,5 +1,5 @@