mirror of
https://github.com/IT4Change/boilerplate-frontend.git
synced 2025-12-13 07:35:53 +00:00
properly use i18n and enforce it
This commit is contained in:
parent
5ab01326dc
commit
5985cd1fad
@ -13,6 +13,7 @@
|
||||
"plugin:promise/recommended",
|
||||
"plugin:security/recommended",
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:@intlify/vue-i18n/recommended",
|
||||
"plugin:storybook/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
@ -32,6 +33,9 @@
|
||||
"import/resolver": {
|
||||
"typescript": true,
|
||||
"node": true
|
||||
},
|
||||
"vue-i18n": {
|
||||
"localeDir": "./src/locales/*.json"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
|
||||
218
package-lock.json
generated
218
package-lock.json
generated
@ -35,6 +35,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.1.0",
|
||||
"@intlify/eslint-plugin-vue-i18n": "^2.0.0",
|
||||
"@storybook/addon-essentials": "^7.5.3",
|
||||
"@storybook/addon-interactions": "^7.5.3",
|
||||
"@storybook/addon-links": "^7.5.3",
|
||||
@ -3123,6 +3124,212 @@
|
||||
"url": "https://github.com/sponsors/kazupon"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/eslint-plugin-vue-i18n/-/eslint-plugin-vue-i18n-2.0.0.tgz",
|
||||
"integrity": "sha512-ECBD0TvQNa56XKyuM6FPIGAAl7MP6ODcgjBQJrzucNxcTb8fYTWmZ+xgBuvmvAtA0iE0D4Wp18UMild2N0bGyw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint/eslintrc": "^1.2.0",
|
||||
"@intlify/core-base": "^9.1.9",
|
||||
"@intlify/message-compiler": "^9.1.9",
|
||||
"debug": "^4.3.1",
|
||||
"glob": "^8.0.0",
|
||||
"ignore": "^5.0.5",
|
||||
"is-language-code": "^3.1.0",
|
||||
"js-yaml": "^4.0.0",
|
||||
"json5": "^2.1.3",
|
||||
"jsonc-eslint-parser": "^2.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"parse5": "^7.0.0",
|
||||
"semver": "^7.3.4",
|
||||
"vue-eslint-parser": "^9.0.0",
|
||||
"yaml-eslint-parser": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/@eslint/eslintrc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
|
||||
"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.4.0",
|
||||
"globals": "^13.19.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"minimatch": "^3.1.2",
|
||||
"strip-json-comments": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/glob/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/globals": {
|
||||
"version": "13.23.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
|
||||
"integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.20.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/minimatch/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/eslint-plugin-vue-i18n/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@intlify/message-compiler": {
|
||||
"version": "9.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.7.1.tgz",
|
||||
@ -16323,6 +16530,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-language-code": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-language-code/-/is-language-code-3.1.0.tgz",
|
||||
"integrity": "sha512-zJdQ3QTeLye+iphMeK3wks+vXSRFKh68/Pnlw7aOfApFSEIOhYa8P9vwwa6QrImNNBMJTiL1PpYF0f4BxDuEgA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-map": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
|
||||
@ -21872,8 +22088,6 @@
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
||||
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
|
||||
@ -84,6 +84,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "^4.1.0",
|
||||
"@intlify/eslint-plugin-vue-i18n": "^2.0.0",
|
||||
"@storybook/addon-essentials": "^7.5.3",
|
||||
"@storybook/addon-interactions": "^7.5.3",
|
||||
"@storybook/addon-links": "^7.5.3",
|
||||
|
||||
@ -5,7 +5,7 @@ import type { PageContext, VikePageContext } from '#types/PageContext'
|
||||
let app: ReturnType<typeof createApp>
|
||||
async function render(pageContext: VikePageContext & PageContext) {
|
||||
if (!app) {
|
||||
app = createApp(pageContext)
|
||||
app = createApp(pageContext).app
|
||||
app.mount('#app')
|
||||
} else {
|
||||
app.changePage(pageContext)
|
||||
@ -17,9 +17,11 @@ function onHydrationEnd() {
|
||||
}
|
||||
function onPageTransitionStart() {
|
||||
// console.log('Page transition start')
|
||||
// document.body.classList.add('page-transition')
|
||||
}
|
||||
function onPageTransitionEnd() {
|
||||
// console.log('Page transition end')
|
||||
// document.body.classList.remove('page-transition')
|
||||
}
|
||||
|
||||
export const clientRouting = true
|
||||
|
||||
@ -13,7 +13,9 @@ import type { App } from 'vue'
|
||||
export const passToClient = ['pageProps', /* 'urlPathname', */ 'routeParams']
|
||||
|
||||
async function render(pageContext: PageContextServer & PageContext) {
|
||||
const app = createApp(pageContext, false)
|
||||
const { app, i18n } = createApp(pageContext, false)
|
||||
|
||||
const locale = i18n.global.locale.value
|
||||
|
||||
const appHtml = await renderToString(app)
|
||||
|
||||
@ -23,7 +25,7 @@ async function render(pageContext: PageContextServer & PageContext) {
|
||||
const desc = (documentProps && documentProps.description) || META.DEFAULT_DESCRIPTION
|
||||
|
||||
const documentHtml = escapeInject`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="${locale}">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="${logoUrl}" />
|
||||
|
||||
@ -61,7 +61,7 @@ function createApp(pageContext: VikePageContext & PageContext, isClient = true)
|
||||
// Make pageContext available from any Vue component
|
||||
setPageContext(app, pageContextReactive)
|
||||
|
||||
return app
|
||||
return { app, i18n }
|
||||
}
|
||||
|
||||
// Same as `Object.assign()` but with type inference
|
||||
|
||||
@ -7,6 +7,7 @@ import en from '#src/locales/en.json'
|
||||
|
||||
export default createI18n({
|
||||
legacy: false, // Vuetify does not support the legacy mode of vue-i18n
|
||||
globalInjection: true,
|
||||
locale: 'de',
|
||||
fallbackLocale: 'en',
|
||||
messages: { de, en },
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<v-btn elevation="2" @click="state.count++">{{ $t('counter') }} {{ state.count }}</v-btn>
|
||||
<v-btn elevation="2" @click="state.count++">{{
|
||||
$t('app.inc.text', { count: state.count })
|
||||
}}</v-btn>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -1,16 +1,38 @@
|
||||
<template>
|
||||
<v-app-bar flat>
|
||||
<LogoAvatar />
|
||||
<v-container class="mx-auto d-flex align-center justify-center">
|
||||
<VikeBtn href="/">Home</VikeBtn>
|
||||
<VikeBtn href="/app">App</VikeBtn>
|
||||
<VikeBtn href="/about">About</VikeBtn>
|
||||
</v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<LogoAvatar />
|
||||
</v-col>
|
||||
<v-col class="d-flex align-center justify-center grow">
|
||||
<VikeBtn href="/">{{ $t('menu.home') }}</VikeBtn>
|
||||
<VikeBtn href="/app">{{ $t('menu.app') }}</VikeBtn>
|
||||
<VikeBtn href="/about">{{ $t('menu.about') }}</VikeBtn>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch
|
||||
v-model="isEnabled"
|
||||
class="d-flex justify-end mr-5"
|
||||
:label="$t('language.german')"
|
||||
color="success"
|
||||
@update:model-value="onChange"
|
||||
></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useLocale } from 'vuetify'
|
||||
|
||||
import VikeBtn from '#components/VikeBtn.vue'
|
||||
|
||||
import LogoAvatar from './LogoAvatar.vue'
|
||||
|
||||
const { current: locale } = useLocale()
|
||||
const isEnabled = ref(locale.value === 'de')
|
||||
const onChange = () => {
|
||||
locale.value = isEnabled.value ? 'de' : 'en'
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,3 +1,53 @@
|
||||
{
|
||||
"counter": "Zähler"
|
||||
"about": {
|
||||
"h1": "Über",
|
||||
"link1": "github.com",
|
||||
"link2": "Webseite",
|
||||
"text1": "Um mehr über diese Kochplatte zu erfahren kannst du dir den Quellcode auf {link} anschauen.",
|
||||
"text2": "Du willst mehr erfahren? Besuche uns auf {link}."
|
||||
},
|
||||
"app": {
|
||||
"inc": {
|
||||
"h1": "Erhöhe den Zähler",
|
||||
"menu": "Erhöhe",
|
||||
"text": "Erhöhe: {count}"
|
||||
},
|
||||
"reset": {
|
||||
"h1": "Den Zähler zurücksetzen",
|
||||
"menu": "Zurücksetzen",
|
||||
"text": "Zurücksetzent: {count}"
|
||||
},
|
||||
"value": {
|
||||
"h1": "Der Zähler",
|
||||
"menu": "Wert",
|
||||
"text": "Der aktuelle Wert des Zählers lautet: {count}"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"404": {
|
||||
"h1": "404 Seite nicht gefunden",
|
||||
"text": "Diese Seite konnte nicht gefunden werden."
|
||||
},
|
||||
"500": {
|
||||
"h1": "500 Interner Fehler",
|
||||
"text": "Irgendetwas ist schief gegangen."
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"greet1": "Hochachtungsvoll",
|
||||
"greet2": "Dein IT Team For Change",
|
||||
"h1": "IT4C Frontend Kochplatte",
|
||||
"text1": "Willkommen zu diesem minimalen Frontendstarter.",
|
||||
"text2": "Es handelt sich um ein einfaches Beispiel um zu zeigen was so geht - nichts besonderes.",
|
||||
"text3": "In dem Anwendungsbereich wirst du ein Zählerbeispiel finden, welches den Browserspeicher verwendet.",
|
||||
"text4": "Fröhliches Programmieren"
|
||||
},
|
||||
"language": {
|
||||
"german": "Deutsch"
|
||||
},
|
||||
"menu": {
|
||||
"about": "Über",
|
||||
"app": "Anwendung",
|
||||
"home": "Daheim"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,53 @@
|
||||
{
|
||||
"counter": "Counter"
|
||||
"about": {
|
||||
"h1": "About",
|
||||
"link1": "github.com",
|
||||
"link2": "website",
|
||||
"text1": "To find out more about this boilerplate you can look at the sources on {link}.",
|
||||
"text2": "Want to get in touch? Find out how on our {link}."
|
||||
},
|
||||
"app": {
|
||||
"inc": {
|
||||
"h1": "Increase the Counter",
|
||||
"menu": "Increase",
|
||||
"text": "Increase: {count}"
|
||||
},
|
||||
"reset": {
|
||||
"h1": "Reset the Counter",
|
||||
"menu": "Reset",
|
||||
"text": "Reset: {count}"
|
||||
},
|
||||
"value": {
|
||||
"h1": "The Counter",
|
||||
"menu": "Value",
|
||||
"text": "The current value of the counter is: {count}"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"404": {
|
||||
"h1": "404 Page Not Found",
|
||||
"text": "This page could not be found."
|
||||
},
|
||||
"500": {
|
||||
"h1": "500 Internal Error",
|
||||
"text": "Something went wrong."
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"greet1": "Sincerly",
|
||||
"greet2": "Your IT Team For Change",
|
||||
"h1": "IT4C Frontend Boilerplate",
|
||||
"text1": "Welcome to this minimal starter for frontends.",
|
||||
"text2": "This is just a basic example to demonstrate things - nothing fancy.",
|
||||
"text3": "In the App Section you will find a counter example utilizing the local storage.",
|
||||
"text4": "Happy Coding"
|
||||
},
|
||||
"language": {
|
||||
"german": "German"
|
||||
},
|
||||
"menu": {
|
||||
"about": "About",
|
||||
"app": "App",
|
||||
"home": "Home"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div v-if="is404">
|
||||
<h1>404 Page Not Found</h1>
|
||||
<p>This page could not be found.</p>
|
||||
<h1>{{ $t('error.404.h1') }}</h1>
|
||||
<p>{{ $t('error.404.text') }}</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h1>500 Internal Error</h1>
|
||||
<p>Something went wrong.</p>
|
||||
<h1>{{ $t('error.500.h1') }}</h1>
|
||||
<p>{{ $t('error.500.text') }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<h1>About</h1>
|
||||
<p>
|
||||
To find out more about this boilerplate you can look at the sources:
|
||||
<a href="https://github.com/IT4Change/boilerplate-frontend/" target="_blank"
|
||||
>github.com/IT4Change/boilerplate-frontend</a
|
||||
>.
|
||||
</p>
|
||||
<h1>{{ $t('about.h1') }}</h1>
|
||||
<i18n-t scope="global" keypath="about.text1" tag="p">
|
||||
<template #link>
|
||||
<a href="https://github.com/IT4Change/boilerplate-frontend/" target="_blank">
|
||||
{{ $t('about.link1') }}
|
||||
</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<br />
|
||||
<p>
|
||||
Want to get in touch? Find out how on our
|
||||
<a href="https://it4c.dev" target="_blank">website</a>
|
||||
</p>
|
||||
<i18n-t scope="global" keypath="about.text2" tag="p">
|
||||
<template #link>
|
||||
<a href="https://it4c.dev" target="_blank">{{ $t('about.link2') }}</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@ -3,11 +3,9 @@ import type { PageContextBuiltInServer } from 'vike/types'
|
||||
export { onBeforeRender }
|
||||
|
||||
async function onBeforeRender(pageContext: PageContextBuiltInServer) {
|
||||
const { page } = pageContext.routeParams
|
||||
const pageProps = { page }
|
||||
return {
|
||||
pageContext: {
|
||||
pageProps,
|
||||
pageProps: pageContext.routeParams,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,34 +2,54 @@
|
||||
<DefaultLayout>
|
||||
<template #sidemenu>
|
||||
<v-list rounded>
|
||||
<v-list-item link title="Value" :active="page === null" href="/app"></v-list-item>
|
||||
<v-list-item link title="Increase" :active="page === 'inc'" href="/app/inc"></v-list-item>
|
||||
<v-list-item
|
||||
link
|
||||
:title="$t('app.value.menu')"
|
||||
:active="page === null"
|
||||
href="/app"
|
||||
></v-list-item>
|
||||
<v-list-item
|
||||
link
|
||||
:title="$t('app.inc.menu')"
|
||||
:active="page === 'inc'"
|
||||
href="/app/inc"
|
||||
></v-list-item>
|
||||
|
||||
<v-divider class="my-2"></v-divider>
|
||||
<v-list-item link title="Reset" :active="page === 'reset'" href="/app/reset"></v-list-item>
|
||||
<v-list-item
|
||||
link
|
||||
:title="$t('app.reset.menu')"
|
||||
:active="page === 'reset'"
|
||||
href="/app/reset"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<div v-if="page === null">
|
||||
<h1>The Counter</h1>
|
||||
<p>
|
||||
The current value of the counter is:
|
||||
<ClientOnly
|
||||
><b>{{ counter.count }}</b></ClientOnly
|
||||
>
|
||||
</p>
|
||||
<h1>{{ $t('app.value.h1') }}</h1>
|
||||
<i18n-t scope="global" keypath="app.value.text" tag="p">
|
||||
<template #count>
|
||||
<ClientOnly>
|
||||
<b>{{ counter.count }}</b>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div v-else-if="page === 'inc'">
|
||||
<h1>Increase the Counter</h1>
|
||||
<h1>{{ $t('app.inc.h1') }}</h1>
|
||||
<ClientOnly>
|
||||
<v-btn elevation="2" @click="counter.increment()">{{ counter.count }}</v-btn>
|
||||
<v-btn elevation="2" @click="counter.increment()">{{
|
||||
$t('app.inc.text', { count: counter.count })
|
||||
}}</v-btn>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
<div v-else-if="page === 'reset'">
|
||||
<h1>Reset the Counter</h1>
|
||||
<h1>{{ $t('app.reset.h1') }}</h1>
|
||||
<ClientOnly>
|
||||
<v-btn elevation="2" @click="counter.reset()">{{ counter.count }}</v-btn>
|
||||
<v-btn elevation="2" @click="counter.reset()">{{
|
||||
$t('app.reset.text', { count: counter.count })
|
||||
}}</v-btn>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<h1>IT4C Frontend Boilerplate</h1>
|
||||
<p>Welcome to this minimal starter for frontends.</p>
|
||||
<h1>{{ $t('home.h1') }}</h1>
|
||||
<p>{{ $t('home.text1') }}</p>
|
||||
<br />
|
||||
<p>This is just a basic example to demonstrate things - nothing fancy.</p>
|
||||
<p>{{ $t('home.text2') }}</p>
|
||||
<br />
|
||||
<p>In the App Section you will find a counter example utilizing the local storage.</p>
|
||||
<p>{{ $t('home.text3') }}</p>
|
||||
<br />
|
||||
<p>Happy Coding <v-icon icon="mdi-heart" color="red" /></p>
|
||||
<p>{{ $t('home.text4') }} <v-icon icon="mdi-heart" color="red" /></p>
|
||||
<br />
|
||||
<p>Sincerly</p>
|
||||
<p>Your IT Team For Change</p>
|
||||
<p>{{ $t('home.greet1') }}</p>
|
||||
<p>{{ $t('home.greet2') }}</p>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template>
|
||||
<header>
|
||||
<div class="storybook-header">
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
<template>
|
||||
<article>
|
||||
<example-header
|
||||
|
||||
@ -14,6 +14,7 @@ const config: UserConfig = {
|
||||
!isStorybook() && vike(), // SSR only when storybook is not running
|
||||
vueI18n({
|
||||
ssr: true,
|
||||
include: path.resolve(__dirname, './src/locales/**'),
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user