mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender-pwa.git
synced 2025-08-05 19:29:16 +02:00
feat:#60 added switch button (not working)
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MenuBar from "./components/MenuBar.vue";
|
import MenuBar from "./components/MenuBar.vue";
|
||||||
|
import { RouterView } from "vue-router";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MenuBar />
|
<MenuBar />
|
||||||
<router-view></router-view>
|
<RouterView />
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@@ -6,7 +6,13 @@ export async function fetchCourse(): Promise<string[]> {
|
|||||||
const courses: string[] = [];
|
const courses: string[] = [];
|
||||||
await fetch("/api/courses")
|
await fetch("/api/courses")
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
//check if response type is json
|
||||||
|
const contentType = response.headers.get("content-type");
|
||||||
|
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||||
return response.json();
|
return response.json();
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then((coursesResponse) => {
|
.then((coursesResponse) => {
|
||||||
coursesResponse.forEach((course: string) => courses.push(course));
|
coursesResponse.forEach((course: string) => courses.push(course));
|
||||||
|
39
frontend/src/components/LocaleSwitcher.vue
Normal file
39
frontend/src/components/LocaleSwitcher.vue
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import i18n, { supportedLocales } from "../i18n";
|
||||||
|
import { Ref, ref } from "vue";
|
||||||
|
import router from "../router";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const locales = ref(
|
||||||
|
Object.keys(supportedLocales).map((code) => ({
|
||||||
|
code,
|
||||||
|
name: supportedLocales[code].name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// selectedLocal is the string of the selected locale from i18n matched with the locales array
|
||||||
|
const selectedLocale: Ref<any> = ref();
|
||||||
|
|
||||||
|
const i18n1 = (i18n.vueI18n);
|
||||||
|
|
||||||
|
function onLocaleChange() {
|
||||||
|
const newLocale: string = selectedLocale.value.code;
|
||||||
|
|
||||||
|
// If the selected locale is the same as the
|
||||||
|
// active one, do nothing
|
||||||
|
if (newLocale === i18n.vueI18n.global.locale) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i18n1.global.locale = newLocale;
|
||||||
|
router.push(`/${newLocale}`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Dropdown
|
||||||
|
:options="locales"
|
||||||
|
optionLabel="name"
|
||||||
|
v-model="selectedLocale"
|
||||||
|
@change="onLocaleChange"
|
||||||
|
>
|
||||||
|
</Dropdown>
|
||||||
|
</template>
|
@@ -1,45 +1,59 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
const {t} = useI18n({})
|
import LocaleSwitcher from "./LocaleSwitcher.vue";
|
||||||
|
import i18n from "../i18n";
|
||||||
|
|
||||||
|
const { t, locale } = useI18n();
|
||||||
|
|
||||||
|
console.debug("locale", locale);
|
||||||
|
console.debug(useI18n().locale)
|
||||||
|
|
||||||
const items = ref([
|
const items = ref([
|
||||||
{
|
{
|
||||||
label: t('createCalendar'),
|
label: t("createCalendar"),
|
||||||
icon: "pi pi-fw pi-plus",
|
icon: "pi pi-fw pi-plus",
|
||||||
url: "/",
|
url: `/${locale}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('editCalendar'),
|
label: t("editCalendar"),
|
||||||
icon: "pi pi-fw pi-pencil",
|
icon: "pi pi-fw pi-pencil",
|
||||||
url: "/edit",
|
url: `/${locale}/edit`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('roomFinder'),
|
label: t("roomFinder"),
|
||||||
icon: "pi pi-fw pi-calendar",
|
icon: "pi pi-fw pi-calendar",
|
||||||
url: "/rooms",
|
url: `/${locale}/rooms`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('faq'),
|
label: t("faq"),
|
||||||
icon: "pi pi-fw pi-book",
|
icon: "pi pi-fw pi-book",
|
||||||
url: "/faq",
|
url: `/${i18n.vueI18n.global.locale}/faq`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('imprint'),
|
label: t("imprint"),
|
||||||
icon: "pi pi-fw pi-id-card",
|
icon: "pi pi-fw pi-id-card",
|
||||||
url: "/imprint",
|
url: `/${i18n.vueI18n.global.locale}/imprint`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('privacy'),
|
label: t("privacy"),
|
||||||
url: "/privacy-policy",
|
|
||||||
icon: "pi pi-fw pi-exclamation-triangle",
|
icon: "pi pi-fw pi-exclamation-triangle",
|
||||||
|
url: `/${i18n.vueI18n.global.locale}/privacy-policy`,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
function removeAllItems() {
|
||||||
|
items.value = [];
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Menubar :model="items" class="menubar justify-content-center">
|
<Menubar :model="items" class="menubar justify-content-center">
|
||||||
<template #start></template>
|
<template #start></template>
|
||||||
|
<template #end>
|
||||||
|
<LocaleSwitcher></LocaleSwitcher>
|
||||||
|
<Button @click="removeAllItems()"></Button>
|
||||||
|
</template>
|
||||||
</Menubar>
|
</Menubar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@@ -1,11 +1,55 @@
|
|||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from "vue-i18n";
|
||||||
import messages from "./messages.ts";
|
import { nextTick } from "vue";
|
||||||
|
import defaultMessages from './translations/en.json'
|
||||||
|
|
||||||
const i18n = createI18n({
|
export const supportedLocales= {
|
||||||
|
'en': { name: 'English'},
|
||||||
|
'de': { name: 'Deutsch'},
|
||||||
|
}
|
||||||
|
export let defaultLocale = 'en'
|
||||||
|
// Private instance of VueI18n object
|
||||||
|
let _i18n: any
|
||||||
|
// Initializer
|
||||||
|
function setup(options = { locale: defaultLocale }) {
|
||||||
|
_i18n = createI18n({
|
||||||
legacy: false,
|
legacy: false,
|
||||||
globalInjection: true,
|
locale: options.locale,
|
||||||
locale: 'en',
|
fallbackLocale: defaultLocale,
|
||||||
messages,
|
messages: { [defaultLocale]: defaultMessages },
|
||||||
})
|
})
|
||||||
|
setLocale(options.locale)
|
||||||
|
return _i18n
|
||||||
|
}
|
||||||
|
|
||||||
export default i18n
|
// Sets the active locale.
|
||||||
|
function setLocale(newLocale : any) {
|
||||||
|
_i18n.global.locale = newLocale
|
||||||
|
setDocumentAttributesFor(newLocale)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadMessagesFor(locale: any) {
|
||||||
|
const messages = await import(
|
||||||
|
`./translations/${locale}.json`
|
||||||
|
)
|
||||||
|
|
||||||
|
_i18n.global.setLocaleMessage(locale, messages.default)
|
||||||
|
|
||||||
|
return nextTick()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocumentAttributesFor(locale: any) {
|
||||||
|
const htmlElement = document.querySelector('html')
|
||||||
|
|
||||||
|
htmlElement?.setAttribute('lang', locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public interface
|
||||||
|
export default {
|
||||||
|
// Expose the VueI18n instance via a getter
|
||||||
|
get vueI18n() {
|
||||||
|
return _i18n
|
||||||
|
},
|
||||||
|
setup,
|
||||||
|
setLocale,
|
||||||
|
loadMessagesFor,
|
||||||
|
}
|
@@ -1,18 +1,18 @@
|
|||||||
export default {
|
export default {
|
||||||
en: {
|
en : {
|
||||||
createCalendar: 'Create Calendar',
|
createCalendar: "Create Calendar",
|
||||||
editCalendar: 'Edit Calendar',
|
editCalendar: "Edit Calendar",
|
||||||
roomFinder: 'Room Finder',
|
roomFinder: "Room Finder",
|
||||||
faq: 'FAQ',
|
faq: "FAQ",
|
||||||
imprint: 'Imprint',
|
imprint: "Imprint",
|
||||||
privacy: 'Privacy',
|
privacy: "Privacy Policy",
|
||||||
},
|
},
|
||||||
de: {
|
de : {
|
||||||
createCalendar: 'Kalender erstellen',
|
createCalendar: "Kalender erstellen",
|
||||||
editCalendar: 'Kalender bearbeiten',
|
editCalendar: "Kalender bearbeiten",
|
||||||
roomFinder: 'Raumfinder',
|
roomFinder: "Raumfinder",
|
||||||
faq: 'FAQ',
|
faq: "FAQ",
|
||||||
imprint: 'Impressum',
|
imprint: "Impressum",
|
||||||
privacy: 'Datenschutz',
|
privacy: "Datenschutz"
|
||||||
}
|
}
|
||||||
}
|
}
|
8
frontend/src/i18n/translations/de.json
Normal file
8
frontend/src/i18n/translations/de.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"createCalendar": "Kalender erstellen",
|
||||||
|
"editCalendar": "Kalender bearbeiten",
|
||||||
|
"roomFinder": "Raumfinder",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"imprint": "Impressum",
|
||||||
|
"privacy": "Datenschutz"
|
||||||
|
}
|
8
frontend/src/i18n/translations/en.json
Normal file
8
frontend/src/i18n/translations/en.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"createCalendar": "Create Calendar",
|
||||||
|
"editCalendar": "Edit Calendar",
|
||||||
|
"roomFinder": "Room Finder",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"imprint": "Imprint",
|
||||||
|
"privacy": "Privacy"
|
||||||
|
}
|
@@ -35,12 +35,13 @@ import i18n from "./i18n";
|
|||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
|
||||||
|
i18n.setup();
|
||||||
|
app.use(i18n.vueI18n);
|
||||||
app.use(PrimeVue);
|
app.use(PrimeVue);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(ToastService);
|
app.use(ToastService);
|
||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
app.use(DialogService);
|
app.use(DialogService);
|
||||||
app.use(i18n);
|
|
||||||
app.component("Button", Button);
|
app.component("Button", Button);
|
||||||
app.component("Menu", Menu);
|
app.component("Menu", Menu);
|
||||||
app.component("Menubar", Menubar);
|
app.component("Menubar", Menubar);
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
import Faq from "../components/FaqPage.vue";
|
import Faq from "../components/FaqPage.vue";
|
||||||
import CourseSelection from "../components/CourseSelection.vue";
|
|
||||||
import AdditionalModules from "../components/AdditionalModules.vue";
|
import AdditionalModules from "../components/AdditionalModules.vue";
|
||||||
import CalendarLink from "../components/CalendarLink.vue";
|
import CalendarLink from "../components/CalendarLink.vue";
|
||||||
import Imprint from "../components/ImprintPage.vue";
|
import Imprint from "../components/ImprintPage.vue";
|
||||||
@@ -10,70 +9,89 @@ import RoomFinder from "../components/RoomFinder.vue";
|
|||||||
import EditCalendarView from "../view/editCalendarView.vue";
|
import EditCalendarView from "../view/editCalendarView.vue";
|
||||||
import EditAdditionalModules from "../components/editCalendar/EditAdditionalModules.vue";
|
import EditAdditionalModules from "../components/editCalendar/EditAdditionalModules.vue";
|
||||||
import EditModules from "../components/editCalendar/EditModules.vue";
|
import EditModules from "../components/editCalendar/EditModules.vue";
|
||||||
|
import CourseSelection from "../components/CourseSelection.vue";
|
||||||
|
import i18n, { defaultLocale } from "../i18n";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
redirect: `/${defaultLocale}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/:locale",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
name: "course-selection",
|
name: "course-selection",
|
||||||
component: CourseSelection,
|
component: CourseSelection,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/rooms",
|
path: "rooms",
|
||||||
name: "room-finder",
|
name: "room-finder",
|
||||||
component: RoomFinder,
|
component: RoomFinder,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/faq",
|
path: "faq",
|
||||||
name: "faq",
|
name: "faq",
|
||||||
component: Faq,
|
component: Faq,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/additional-modules",
|
path: "additional-modules",
|
||||||
name: "additional-modules",
|
name: "additional-modules",
|
||||||
component: AdditionalModules,
|
component: AdditionalModules,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/edit-additional-modules",
|
path: "edit-additional-modules",
|
||||||
name: "edit-additional-modules",
|
name: "edit-additional-modules",
|
||||||
component: EditAdditionalModules,
|
component: EditAdditionalModules,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/edit-calendar",
|
path: "edit-calendar",
|
||||||
name: "edit-calendar",
|
name: "edit-calendar",
|
||||||
component: EditModules,
|
component: EditModules,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/calendar-link",
|
path: "calendar-link",
|
||||||
name: "calendar-link",
|
name: "calendar-link",
|
||||||
component: CalendarLink,
|
component: CalendarLink,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/edit",
|
path: "edit",
|
||||||
name: "edit",
|
name: "edit",
|
||||||
component: EditCalendarView,
|
component: EditCalendarView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/privacy-policy",
|
path: "privacy-policy",
|
||||||
name: "privacy-policy",
|
name: "privacy-policy",
|
||||||
component: PrivacyPolicy,
|
component: PrivacyPolicy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/imprint",
|
path: "imprint",
|
||||||
name: "imprint",
|
name: "imprint",
|
||||||
component: Imprint,
|
component: Imprint,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/rename-modules",
|
path: "rename-modules",
|
||||||
name: "rename-modules",
|
name: "rename-modules",
|
||||||
component: RenameModules,
|
component: RenameModules,
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
path: "/:catchAll(.*)",
|
|
||||||
redirect: "/",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from) => {
|
||||||
|
const newLocale = to.params.locale
|
||||||
|
const prevLocale = from.params.locale
|
||||||
|
// If the locale hasn't changed, do nothing
|
||||||
|
if (newLocale === prevLocale) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await i18n.loadMessagesFor(newLocale)
|
||||||
|
i18n.setLocale(newLocale)
|
||||||
|
})
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@@ -1,9 +1,15 @@
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import vue from "@vitejs/plugin-vue";
|
import vue from "@vitejs/plugin-vue";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
}
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
host: true,
|
host: true,
|
||||||
port: 8000,
|
port: 8000,
|
||||||
|
Reference in New Issue
Block a user