feat: add i18n support and translations

This commit is contained in:
Settel 2022-08-29 15:15:25 +02:00
parent ec9a1ef35e
commit f62b8db662
7 changed files with 79 additions and 13 deletions

View File

@ -1,18 +1,27 @@
<template> <template>
<div class="game-controls__container"> <div class="game-controls__container">
<Button class="game-controls__control" :border="!disabled.collect" :disabled="disabled.collect" @click="collect">Collect Quotes</Button> <Button class="game-controls__control" :border="!disabled.collect" :disabled="disabled.collect" @click="collect">{{ $t('collect-quotes') }}</Button>
<Button class="game-controls__control" :border="!disabled.start" :disabled="disabled.start" @click="start">Start</Button> <Button class="game-controls__control" :border="!disabled.start" :disabled="disabled.start" @click="start">{{ $t('start') }}</Button>
<Button class="game-controls__control" :border="!disabled.cont" :disabled="disabled.cont" @click="cont">Continue</Button> <Button class="game-controls__control" :border="!disabled.cont" :disabled="disabled.cont" @click="cont">{{ $t('continue') }}</Button>
<Button class="game-controls__control" :border="!disabled.idle" :disabled="disabled.idle" @click="idle">Idle</Button> <Button class="game-controls__control" :border="!disabled.idle" :disabled="disabled.idle" @click="idle">{{ $t('idle') }}</Button>
<Button class="game-controls__control" :border="!disabled.finish" :disabled="disabled.finish" @click="finish">Finish</Button> <Button class="game-controls__control" :border="!disabled.finish" :disabled="disabled.finish" @click="finish">{{ $t('finish') }}</Button>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import useEngine from '@/composables/useEngine' import useEngine from '@/composables/useEngine'
import useI18n from '@/composables/useI18n'
import { useGameinfoStore } from "@/stores/GameinfoStore" import { useGameinfoStore } from "@/stores/GameinfoStore"
const { $t } = useI18n({
'collect-quotes': { en: 'Collect Quotes', de: 'Aussagen sammeln' },
'start': { en: 'Start', de: 'Start' },
'continue': { en: 'Continue', de: 'Weiter' },
'idle': { en: 'Lobby', de: 'Lobby' },
'finish': { en: 'Highscores', de: 'Highscores' },
})
const game = useGameinfoStore() const game = useGameinfoStore()
const engine = useEngine() const engine = useEngine()
const disabled = computed(() => { const disabled = computed(() => {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="lobby__container"> <div class="lobby__container">
<div class="lobby__message"> <div class="lobby__message">
waiting for gamemaster to start the game ... {{ $t('waiting-for-gamemaster') }}
</div> </div>
<div class="lobby__players-list"> <div class="lobby__players-list">
<PlayerList :players="players" :hide-scores="true" /> <PlayerList :players="players" :hide-scores="true" />
@ -10,7 +10,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import useI18n from '@/composables/useI18n'
import { usePlayersStore } from '@/stores/PlayersStore' import { usePlayersStore } from '@/stores/PlayersStore'
const { $t } = useI18n({
'waiting-for-gamemaster': { en: 'waiting for gamemaster to start the game ...', de: 'warten, bis der/die Gamemaster:in das Spiel startet ...'},
})
const players = usePlayersStore().players const players = usePlayersStore().players
</script> </script>

View File

@ -3,7 +3,7 @@
<form class="login-box__container-inner" @submit.prevent="login"> <form class="login-box__container-inner" @submit.prevent="login">
<input v-model="authCode" v-focus class="login-box__authinput" type="text" size="6" maxlength="6" <input v-model="authCode" v-focus class="login-box__authinput" type="text" size="6" maxlength="6"
placeholder="Code" /> placeholder="Code" />
<Button type="submit">Go!</Button> <Button type="submit">{{ $t('login') }}</Button>
<div v-if="errorMessage" class="login-box__error">{{ errorMessage }}</div> <div v-if="errorMessage" class="login-box__error">{{ errorMessage }}</div>
</form> </form>
</div> </div>
@ -13,6 +13,11 @@
import { useRouter } from '#app' import { useRouter } from '#app'
import { ref, Ref } from 'vue' import { ref, Ref } from 'vue'
import useAuth from '@/composables/useAuth'; import useAuth from '@/composables/useAuth';
import useI18n from '@/composables/useI18n';
const { $t } = useI18n({
'login': { en: 'log in', de: 'login'},
})
const vFocus = { mounted: (el: HTMLElement) => el.focus() } const vFocus = { mounted: (el: HTMLElement) => el.focus() }
@ -36,7 +41,6 @@ const login = (): void => {
.login-box { .login-box {
&__container-outer { &__container-outer {
display: flex; display: flex;
width: 240px;
} }
&__container-inner { &__container-inner {

View File

@ -17,7 +17,7 @@
</div> </div>
<div class="topbar__separator" /> <div class="topbar__separator" />
<div class="topbar__logout-button-container"> <div class="topbar__logout-button-container">
<Button class="topbar__logout-button" :border="false" @click="actionLogout">Logout</Button> <Button class="topbar__logout-button" :border="false" @click="actionLogout">{{ $t('logout') }}</Button>
</div> </div>
</div> </div>
</template> </template>
@ -25,9 +25,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from '#app' import { useRouter } from '#app'
import useAuth from '@/composables/useAuth'; import useAuth from '@/composables/useAuth';
import useI18n from '@/composables/useI18n';
import { useUserinfoStore } from "@/stores/UserinfoStore" import { useUserinfoStore } from "@/stores/UserinfoStore"
import { useGameinfoStore } from "@/stores/GameinfoStore" import { useGameinfoStore } from "@/stores/GameinfoStore"
const { $t, setLang } = useI18n({
'logout': { en: 'Logout', de: 'abmelden' },
})
const user = useUserinfoStore() const user = useUserinfoStore()
const game = useGameinfoStore() const game = useGameinfoStore()

View File

@ -0,0 +1,30 @@
export type i18nMap = {
[key: string]: {
en: string,
de: string,
},
}
let lang = 'de'
const defaultLang = navigator.language ? navigator.language.substr(0, 2) : 'en'
export interface useI18n {
setLang(lang: string): void
$t(key: string): string
}
export default (map: i18nMap): useI18n => {
return {
setLang: (_lang: string): void => {
lang = _lang
},
$t: (key: string): string => {
const t = map[key]
if (!t) {
return key
}
return t[lang] || t[defaultLang] || key
}
}
}

View File

@ -8,7 +8,7 @@
</div> </div>
<div class="page-index__separator" /> <div class="page-index__separator" />
<div class="page-index__create-team"> <div class="page-index__create-team">
<Button disabled>Create Team</Button> <Button disabled>{{ $t('create-team') }}</Button>
</div> </div>
<div class="page-index__space" /> <div class="page-index__space" />
</div> </div>
@ -21,6 +21,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRuntimeConfig, navigateTo } from '#app' import { useRuntimeConfig, navigateTo } from '#app'
import useAuth from '@/composables/useAuth' import useAuth from '@/composables/useAuth'
import useI18n from '@/composables/useI18n'
const { $t } = useI18n({
'create-team': { en: 'Create Team', de: 'Team erstellen' },
})
const config = useRuntimeConfig() const config = useRuntimeConfig()
@ -51,7 +56,7 @@ body {
&__login, &__login,
&__create-team { &__create-team {
width: 240px; width: 320px;
align-self: center; align-self: center;
} }

View File

@ -2,8 +2,8 @@
<div class="page-play__container"> <div class="page-play__container">
<TopBar /> <TopBar />
<AlertBox v-if="!isConnected" mode="alert"> <AlertBox v-if="!isConnected" mode="alert">
connection to server broken {{ $t('connection-broken') }}
<div v-if="retry >= 0">retrying {{ '...'.slice(0, retry % 4) }}</div> <div v-if="retry >= 0">{{ $t('retrying') }} {{ '...'.slice(0, retry % 4) }}</div>
</AlertBox> </AlertBox>
<div class="page-play__playfield-container"> <div class="page-play__playfield-container">
<div class="page-play__playfield-content"> <div class="page-play__playfield-content">
@ -24,6 +24,13 @@ import { computed, onMounted, onBeforeUnmount } from 'vue';
import useAuth from '@/composables/useAuth'; import useAuth from '@/composables/useAuth';
import useEngine from '@/composables/useEngine'; import useEngine from '@/composables/useEngine';
import { useGameinfoStore } from "@/stores/GameinfoStore" import { useGameinfoStore } from "@/stores/GameinfoStore"
import useI18n from '@/composables/useI18n'
const { $t } = useI18n({
'connection-broken': { en: 'connection to server broken.', de: 'Verbindung zum Server ist unterbrochen.' },
'retrying': { en: 'retrying', de: 'verbinde erneut'},
})
// ensure user is authenticated // ensure user is authenticated
const { authenticateAndLoadUserInfo } = useAuth() const { authenticateAndLoadUserInfo } = useAuth()