Skip to content

Commit

Permalink
Merge branch 'master' into test-header-menu
Browse files Browse the repository at this point in the history
  • Loading branch information
ulfgebhardt authored Mar 26, 2024
2 parents f5fdced + 182d930 commit a8b1c7b
Show file tree
Hide file tree
Showing 31 changed files with 175 additions and 45 deletions.
2 changes: 0 additions & 2 deletions presenter/.env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,3 @@ PUBLIC_ENV__ENDPOINTS__GRAPHQL_URI=http://localhost:4000/
# META
PUBLIC_ENV__META__BASE_URL="http://localhost:3000"
PUBLIC_ENV__META__DEFAULT_AUTHOR="DreamMall Verlag GbR"
PUBLIC_ENV__META__DEFAULT_DESCRIPTION="Deine Reichweite Erweitern Alle Möglichkeiten Miteinander Ausschöpfen Lebensqualität Leben"
PUBLIC_ENV__META__DEFAULT_TITLE="DreamMall"
2 changes: 1 addition & 1 deletion presenter/renderer/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
export default {
clientRouting: true,
prefetchStaticAssets: 'viewport',
passToClient: ['pageProps', /* 'urlPathname', */ 'routeParams'],
passToClient: ['pageProps', /* 'urlPathname', */ 'routeParams', 'locale'],
meta: {
title: {
// Make the value of `title` available on both the server- and client-side
Expand Down
16 changes: 16 additions & 0 deletions presenter/renderer/+onBeforeRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { PageContext } from 'vike/types'

import { extractLocale } from '#src/locales'

export function onBeforeRoute(pageContext: PageContext) {
const { urlWithoutLocale, locale } = extractLocale(pageContext.urlPathname)

return {
pageContext: {
// Make `locale` available as `pageContext.locale`
locale,
// Vike's router will use pageContext.urlLogical instead of pageContext.urlOriginal
urlLogical: urlWithoutLocale,
},
}
}
32 changes: 32 additions & 0 deletions presenter/renderer/+onPrerenderStart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { PageContextServer } from 'vike/types'

import { locales } from '#src/locales'

export { onPrerenderStart }

function onPrerenderStart(prerenderContext: { pageContexts: PageContextServer[] }): {
prerenderContext: {
pageContexts: PageContextServer[]
}
} {
const storePageContexts: PageContextServer[] = []
prerenderContext.pageContexts.forEach((pageContext) => {
// Duplicate pageContext for each locale
locales.forEach((locale) => {
// Localize URL
let { urlOriginal } = pageContext
urlOriginal = `/${locale}${urlOriginal}`
storePageContexts.push({
...pageContext,
urlOriginal,
// Set pageContext.locale
locale,
})
})
})
return {
prerenderContext: {
pageContexts: storePageContexts,
},
}
}
7 changes: 7 additions & 0 deletions presenter/renderer/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { createApolloClient } from '#plugins/apollo'
import i18n from '#plugins/i18n'
import pinia from '#plugins/pinia'
import CreateVuetify from '#plugins/vuetify'
import { locales } from '#src/locales'
import AuthService from '#src/services/AuthService'
import { useAuthStore } from '#stores/authStore'

Expand All @@ -25,6 +26,7 @@ function createApp(pageContext: PageContext, isClient = true) {
data: () => ({
Page: markRaw(pageContext.Page),
pageProps: markRaw(pageContext.pageProps || {}),
locale: markRaw(pageContext.locale || {}),
isClient,
}),
created() {
Expand Down Expand Up @@ -64,13 +66,18 @@ function createApp(pageContext: PageContext, isClient = true) {
Object.assign(pageContextReactive, pageContext)
rootComponent.Page = markRaw(pageContext.Page)
rootComponent.pageProps = markRaw(pageContext.pageProps || {})
rootComponent.locale = markRaw(pageContext.locale || {})
},
})

const pageContextReactive = reactive(pageContext)

setPageContext(app, pageContextReactive)

if (pageContext.locale && locales.includes(pageContext.locale)) {
i18n.global.locale.value = pageContext.locale
}

return { app, i18n }
}

Expand Down
5 changes: 3 additions & 2 deletions presenter/renderer/plugins/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { createI18n } from 'vue-i18n'
import { de as vuetifyDe, en as vuetifyEn } from 'vuetify/locale'

import { localeDefault, fallbackLocale } from '#src/locales'
import de from '#src/locales/de.json'
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',
locale: localeDefault,
fallbackLocale,
messages: {
de: {
$vuetify: vuetifyDe,
Expand Down
6 changes: 3 additions & 3 deletions presenter/renderer/utils.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { PageContext } from 'vike/types'

import { META } from '#src/env'
import i18n from '#plugins/i18n'

function getTitle(pageContext: PageContext) {
// The value exported by /pages/**/+title.js is available at pageContext.config.title
const val = pageContext.config.title
if (typeof val === 'string') return val
if (typeof val === 'function') return String(val(pageContext))
return META.DEFAULT_TITLE
return i18n.global.t('meta.defaultTitle')
}
function getDescription(pageContext: PageContext) {
const val = pageContext.config.description
if (typeof val === 'string') return val
if (typeof val === 'function') return val(pageContext)
return META.DEFAULT_DESCRIPTION
return i18n.global.t('meta.defaultDescription')
}

export { getTitle, getDescription }
1 change: 1 addition & 0 deletions presenter/scripts/tests/mock.vikePageContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ config.global.provide = {
routeParams: {
code: 'my-code',
},
locale: 'de',
},
}
14 changes: 14 additions & 0 deletions presenter/src/components/language/LanguageSelector.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { mount } from '@vue/test-utils'
import { describe, it, expect, beforeEach } from 'vitest'

import i18n from '#plugins/i18n'

import LanguageSelector from './LanguageSelector.vue'

describe('LanguageSelector', () => {
Expand All @@ -10,12 +12,24 @@ describe('LanguageSelector', () => {
})
}
let wrapper: ReturnType<typeof Wrapper>
let vSelect: ReturnType<typeof wrapper.findComponent>

beforeEach(() => {
wrapper = Wrapper()
vSelect = wrapper.findComponent({ name: 'v-select' })
})

it('renders', () => {
expect(wrapper.element).toMatchSnapshot()
})

describe('switch locale', () => {
beforeEach(async () => {
await vSelect.setValue('en')
})

it('to en', () => {
expect(i18n.global.locale.value).toBe('en')
})
})
})
8 changes: 3 additions & 5 deletions presenter/src/components/language/LanguageSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@
<script lang="ts" setup>
import { ref } from 'vue'
// TODO better place? maybe locales folder?
const languages = ref([
{ locale: 'de', title: 'Deutsch' },
{ locale: 'en', title: 'English' },
])
import { localizedLocale } from '#src/locales'
const languages = ref(localizedLocale)
</script>

<style lang="scss">
Expand Down
3 changes: 0 additions & 3 deletions presenter/src/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ describe('env', () => {
expect(META).toEqual({
BASE_URL: 'http://localhost:3000',
DEFAULT_AUTHOR: 'DreamMall Verlag GbR',
DEFAULT_DESCRIPTION:
'Deine Reichweite Erweitern Alle Möglichkeiten Miteinander Ausschöpfen Lebensqualität Leben',
DEFAULT_TITLE: 'DreamMall',
})
})
})
3 changes: 0 additions & 3 deletions presenter/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ const META = {
BASE_URL: (import.meta.env.PUBLIC_ENV__META__BASE_URL ?? 'http://localhost:3000') as string,
DEFAULT_AUTHOR: (import.meta.env.PUBLIC_ENV__META__DEFAULT_AUTHOR ??
'DreamMall Verlag GbR') as string,
DEFAULT_DESCRIPTION: (import.meta.env.PUBLIC_ENV__META__DEFAULT_DESCRIPTION ??
'Deine Reichweite Erweitern Alle Möglichkeiten Miteinander Ausschöpfen Lebensqualität Leben') as string,
DEFAULT_TITLE: (import.meta.env.PUBLIC_ENV__META__DEFAULT_TITLE ?? 'DreamMall') as string,
}

export { AUTH, ENDPOINTS, META }
19 changes: 14 additions & 5 deletions presenter/src/locales/de.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"about": {},
"auth": {
"content": "Logge ein..."
"content": "Logge ein...",
"title": "DreamMall {'|'} Authentifizierung"
},
"dataProtection": {
"euDispute": {
Expand All @@ -26,7 +27,8 @@
"revocation": {
"content": "Nur mit Ihrer ausdrücklichen Einwilligung sind einige Vorgänge der Datenverarbeitung möglich. Ein Widerruf Ihrer bereits erteilten Einwilligung ist jederzeit möglich. Für den Widerruf genügt eine formlose Mitteilung per E-Mail. Die Rechtmäßigkeit der bis zum Widerruf erfolgten Datenverarbeitung bleibt vom Widerruf unberührt.",
"headline": "Widerruf Ihrer Einwilligung zur Datenverarbeitung"
}
},
"title": "DreamMall {'|'} Datenschutz"
},
"error": {
"404": {
Expand All @@ -36,7 +38,8 @@
"500": {
"h1": "500 Interner Fehler",
"text": "Etwas ist schief gegangen."
}
},
"title": "DreamMall {'|'} Fehler"
},
"home": {
"aboutSection": {
Expand Down Expand Up @@ -161,7 +164,8 @@
"content": "Umsatzsteuer-Identifikationsnummer gemäß § 27 a Umsatzsteuergesetz:",
"headline": "Umsatzsteuer-ID",
"id": "DE356946303"
}
},
"title": "DreamMall {'|'} Impressum"
},
"menu": {
"eMail": "E-Mail",
Expand Down Expand Up @@ -202,14 +206,19 @@
"sitemap": "Sitemap"
}
},
"meta": {
"defaultDescription": "Deine Reichweite Erweitern Alle Möglichkeiten Miteinander Ausschöpfen Lebensqualität Leben",
"defaultTitle": "DreamMall"
},
"optin": {
"error": {
"link": "Erneut eintragen",
"text": "Bei der Bestätigung ist ein Fehler aufgetreten. Bitte tragen Sie sich erneut in den Newsletter ein."
},
"success": {
"text": "Sie haben Ihr Newsletterabbonoment erfolgreich bestätigt. Sie werden in Kürze auf die Startseite weitergeleitet."
}
},
"title": "DreamMall {'|'} Newsletter"
},
"validation": {
"fieldNoEmail": "Dieses Feld muss eine Email-Adresse sein.",
Expand Down
19 changes: 14 additions & 5 deletions presenter/src/locales/en.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"about": {},
"auth": {
"content": "Logging in..."
"content": "Logging in...",
"title": "DreamMall {'|'} Authentication"
},
"dataProtection": {
"euDispute": {
Expand All @@ -26,7 +27,8 @@
"revocation": {
"content": "Some data processing operations are only possible with your express consent. You can withdraw your consent at any time. An informal notification by e-mail is sufficient for the revocation. The legality of the data processing carried out until the revocation remains unaffected by the revocation.",
"headline": "Withdrawal of your consent to data processing"
}
},
"title": "DreamMall {'|'} Privacy Policy"
},
"error": {
"404": {
Expand All @@ -36,7 +38,8 @@
"500": {
"h1": "500 Internal error",
"text": "Something went wrong."
}
},
"title": "DreamMall {'|'} Error"
},
"home": {
"aboutSection": {
Expand Down Expand Up @@ -161,7 +164,8 @@
"content": "Sales tax identification number according to § 27 a sales tax law:",
"headline": "Sales tax ID",
"id": "DE356946303"
}
},
"title": "DreamMall {'|'} Imprint"
},
"menu": {
"eMail": "E-Mail",
Expand Down Expand Up @@ -202,14 +206,19 @@
"sitemap": "Sitemap"
}
},
"meta": {
"defaultDescription": "Expanding your reach making the most of opportunities enhance quality of life together",
"defaultTitle": "DreamMall"
},
"optin": {
"error": {
"link": "Register again",
"text": "An error occurred during confirmation. Please subscribe to the newsletter again."
},
"success": {
"text": "You have successfully confirmed your newsletter subscription. You will be redirected to the start page shortly."
}
},
"title": "DreamMall {'|'} Newsletter"
},
"validation": {
"fieldNoEmail": "This field must be an email address",
Expand Down
25 changes: 25 additions & 0 deletions presenter/src/locales/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type LocaleCode = 'de' | 'en'
export const locales: LocaleCode[] = ['de', 'en']
export const localeDefault = 'de'
export const fallbackLocale = 'en'
export const localizedLocale = [
{ locale: 'de', title: 'Deutsch' },
{ locale: 'en', title: 'English' },
]

export function extractLocale(url: string) {
const urlPaths = url.split('/')
let locale: LocaleCode
let urlWithoutLocale
// We remove the URL locale, for example `/de/about` => `/about`
const firstPath = urlPaths[1] as LocaleCode
if (locales.includes(firstPath)) {
locale = firstPath
urlWithoutLocale = '/' + urlPaths.slice(2).join('/')
} else {
locale = localeDefault
urlWithoutLocale = url
}

return { locale, urlWithoutLocale }
}
4 changes: 3 additions & 1 deletion presenter/src/pages/_error/+title.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const title = 'DreamMall | Fehler'
import i18n from '#plugins/i18n'

export const title = () => i18n.global.t('error.title')
4 changes: 3 additions & 1 deletion presenter/src/pages/_error/Page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { describe, it, expect, beforeEach } from 'vitest'
import { Component, h } from 'vue'
import { VApp } from 'vuetify/components'

import i18n from '#plugins/i18n'

import ErrorPage from './+Page.vue'
import { title } from './+title'

describe('ErrorPage', () => {
it('title returns correct title', () => {
expect(title).toBe('DreamMall | Fehler')
expect(title()).toBe(i18n.global.t('error.title'))
})
describe('500 Error', () => {
const WrapperUndefined = () => {
Expand Down
4 changes: 3 additions & 1 deletion presenter/src/pages/auth/+title.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const title = 'DreamMall | Authentifizierung'
import i18n from '#plugins/i18n'

export const title = () => i18n.global.t('auth.title')
Loading

0 comments on commit a8b1c7b

Please sign in to comment.