feat: Implement internationalization (i18n) with language switching and establish core backend services and frontend pages for course management.

This commit is contained in:
supalerk-ar66 2026-01-19 15:11:47 +07:00
parent 6a05e6fdb6
commit dbf62feea9
13 changed files with 3195 additions and 1463 deletions

View file

@ -0,0 +1,89 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { locale, setLocale } = useI18n()
// Language options
const languages = [
{ code: 'th', label: 'TH', fullLabel: 'ไทย', flagSrc: '/flags/th.svg' },
{ code: 'en', label: 'EN', fullLabel: 'English', flagSrc: '/flags/en.svg' }
]
// Get current language object
const currentLang = computed(() =>
languages.find(l => l.code === locale.value) || languages[0]
)
// Change language function
const changeLanguage = (langCode: string) => {
setLocale(langCode)
}
</script>
<template>
<q-btn
rounded
flat
no-caps
class="text-slate-700 dark:text-slate-200"
:aria-label="$t('app.title') || 'Change Language'"
>
<div class="flex items-center gap-2">
<img
:src="currentLang.flagSrc"
alt="flag"
class="w-5 h-5 rounded-full object-cover border border-slate-200 dark:border-slate-600"
/>
<span class="font-bold">{{ currentLang.label }}</span>
<q-icon name="arrow_drop_down" />
</div>
<!-- Tooltip -->
<q-tooltip>ภาษา / Language</q-tooltip>
<!-- Dropdown Menu -->
<q-menu
auto-close
transition-show="jump-down"
transition-hide="jump-up"
class="rounded-xl shadow-lg border border-slate-100 bg-white dark:bg-slate-800 dark:border-slate-700"
>
<q-list style="min-width: 150px" class="py-2">
<q-item
v-for="lang in languages"
:key="lang.code"
clickable
v-close-popup
:active="locale === lang.code"
active-class="bg-blue-50 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400"
class="text-black dark:text-white hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors"
@click="changeLanguage(lang.code)"
>
<q-item-section avatar>
<img
:src="lang.flagSrc"
alt="flag"
class="w-6 h-6 rounded-full object-cover border border-slate-200 dark:border-slate-600"
/>
</q-item-section>
<q-item-section>
<span :class="{ 'font-bold': locale === lang.code }">{{ lang.fullLabel }}</span>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</template>
<style scoped>
/* Optional: adjust Quasar overrides if needed */
</style>
<style scoped>
.font-emoji {
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
/* Tooltip directive placeholder if not globally available,
though usually handled by a library like Floating Vue or simple title attr */
</style>