🌐 (app) init 18n in en and french
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="chilled-music">
|
||||
<transition name="fade">
|
||||
<img v-show="!ready" src="@/assets/loader.svg" alt="loading" />
|
||||
<img v-show="!ready" src="@/assets/loader.svg" :alt="$t('loading')" />
|
||||
</transition>
|
||||
<section v-show="false">
|
||||
<div
|
||||
@@ -114,3 +114,14 @@ img {
|
||||
animation: rotating 4s linear infinite;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"en": {
|
||||
"loading": "loading..."
|
||||
},
|
||||
"fr": {
|
||||
"loading": "chargement..."
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
<template>
|
||||
<div class="interval-input">
|
||||
<transition name="fade" mode="out-in">
|
||||
<button v-if="editable" class="spacer" @click="minus">
|
||||
<img key="minus" src="@/assets/minus.svg" alt="minus" />
|
||||
</button>
|
||||
<div v-else class="spacer"></div>
|
||||
</transition>
|
||||
<h3>{{ label }}</h3>
|
||||
<transition name="fade" mode="out-in">
|
||||
<button v-if="editable" class="spacer" @click="plus">
|
||||
<img key="plus" src="@/assets/plus.svg" alt="plus" />
|
||||
</button>
|
||||
<div v-else class="spacer"></div>
|
||||
</transition>
|
||||
<div class="button-container minus">
|
||||
<transition name="fade" mode="out-in">
|
||||
<button v-if="editable" class="spacer" @click="minus">
|
||||
<img key="minus" src="@/assets/minus.svg" alt="minus" />
|
||||
</button>
|
||||
<div v-else class="spacer"></div>
|
||||
</transition>
|
||||
</div>
|
||||
<h3 v-if="isMinuteSession">
|
||||
{{ $tc('minuteSession', interval, { interval }) }}
|
||||
</h3>
|
||||
<h3 v-else>{{ $t('secondSession') }}</h3>
|
||||
<div class="button-container plus">
|
||||
<transition name="fade" mode="out-in">
|
||||
<button v-if="editable" class="spacer" @click="plus">
|
||||
<img key="plus" src="@/assets/plus.svg" alt="plus" />
|
||||
</button>
|
||||
<div v-else class="spacer"></div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from '@vue/composition-api'
|
||||
import { defineComponent } from '@vue/composition-api'
|
||||
import { useInterval } from '../hooks/useInterval'
|
||||
|
||||
export default defineComponent({
|
||||
@@ -26,20 +33,13 @@ export default defineComponent({
|
||||
editable: { type: Boolean, required: true }
|
||||
},
|
||||
setup() {
|
||||
const { interval, minInterval, minus, plus } = useInterval()
|
||||
|
||||
const label = computed(() => {
|
||||
if (interval.value === minInterval) {
|
||||
return '30 second session'
|
||||
}
|
||||
|
||||
return `${interval.value} minute session`
|
||||
})
|
||||
const { interval, isMinuteSession, minus, plus } = useInterval()
|
||||
|
||||
return {
|
||||
interval,
|
||||
isMinuteSession,
|
||||
minus,
|
||||
plus,
|
||||
label
|
||||
plus
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -53,12 +53,25 @@ $button-size: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
h3 {
|
||||
flex: 1;
|
||||
flex: 2;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
&.minus {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
&.plus {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -73,3 +86,16 @@ $button-size: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"en": {
|
||||
"minuteSession": "{interval} minute session",
|
||||
"secondSession": "30 second session"
|
||||
},
|
||||
"fr": {
|
||||
"minuteSession": "session de {interval} minute | session de {interval} minutes",
|
||||
"secondSession": "session de 30 secondes"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
<div class="zone-music plume" v-if="isMusicAvailable">
|
||||
<div class="pm-field">
|
||||
<label for="use-music" data-pm-holder>
|
||||
<span class="focus" :class="{ selected: !hasMusic, disabled: hasMusic }"
|
||||
>focus</span
|
||||
>
|
||||
<span
|
||||
class="focus"
|
||||
:class="{ selected: !hasMusic, disabled: hasMusic }"
|
||||
v-t="'focus'"
|
||||
></span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="use-music"
|
||||
@@ -17,7 +19,7 @@
|
||||
class="chill"
|
||||
:class="{ selected: hasMusic, disabled: !hasMusic }"
|
||||
>
|
||||
chill
|
||||
<span v-t="'chill'"></span>
|
||||
<ChilledMusic
|
||||
class="chilled-music"
|
||||
v-if="hasMusic"
|
||||
@@ -92,6 +94,10 @@ label[data-pm-holder] {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
span {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.chilled-music {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
@@ -105,3 +111,16 @@ label[data-pm-holder] {
|
||||
color: desaturate($color, 70%);
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"en": {
|
||||
"focus": "focus",
|
||||
"chill": "chill"
|
||||
},
|
||||
"fr": {
|
||||
"focus": "concentré",
|
||||
"chill": "détendu"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useGetters, useActions } from 'vuex-composition-helpers'
|
||||
import { GetterTree } from 'vuex'
|
||||
import { State, RootActions } from '@/store'
|
||||
import { computed } from '@vue/composition-api'
|
||||
|
||||
const MIN_INTERVAL = 0.5
|
||||
const MAX_INTERVAL = 60
|
||||
@@ -19,8 +20,11 @@ export const useInterval = () => {
|
||||
setInterval(Math.min(Math.floor(interval.value + 1), MAX_INTERVAL))
|
||||
}
|
||||
|
||||
const isMinuteSession = computed(() => interval.value >= 1)
|
||||
|
||||
return {
|
||||
interval,
|
||||
isMinuteSession,
|
||||
minInterval: MIN_INTERVAL,
|
||||
minus,
|
||||
plus
|
||||
|
||||
@@ -28,8 +28,8 @@ export const useTimer = () => {
|
||||
const session = computed(() => formatSeconds(sessionSeconds.value))
|
||||
const intervalSeconds = computed(() => interval.value * 60)
|
||||
|
||||
let stopwatchId: number | null = null
|
||||
let stopWatchSessionId: number | null = null
|
||||
let stopwatchId: NodeJS.Timeout | null = null
|
||||
let stopWatchSessionId: NodeJS.Timeout | null = null
|
||||
|
||||
watch(interval, () => {
|
||||
sessionSeconds.value = interval.value * 60
|
||||
|
||||
32
src/i18n.ts
Normal file
32
src/i18n.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import Vue from 'vue'
|
||||
import VueI18n, { LocaleMessages } from 'vue-i18n'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
|
||||
function loadLocaleMessages(): LocaleMessages {
|
||||
const locales = require.context(
|
||||
'./locales',
|
||||
true,
|
||||
/[A-Za-z0-9-_,\s]+\.json$/i
|
||||
)
|
||||
const messages: LocaleMessages = {}
|
||||
locales.keys().forEach((key) => {
|
||||
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
|
||||
if (matched && matched.length > 1) {
|
||||
const locale = matched[1]
|
||||
messages[locale] = locales(key)
|
||||
}
|
||||
})
|
||||
return messages
|
||||
}
|
||||
|
||||
const lang = navigator.language
|
||||
?.split('-')
|
||||
.shift()
|
||||
?.toLowerCase()
|
||||
|
||||
export default new VueI18n({
|
||||
locale: lang || 'en',
|
||||
fallbackLocale: 'en',
|
||||
messages: loadLocaleMessages()
|
||||
})
|
||||
@@ -4,6 +4,7 @@ import './registerServiceWorker'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import VueCompositionAPI from '@vue/composition-api'
|
||||
import i18n from './i18n'
|
||||
|
||||
Vue.use(VueCompositionAPI)
|
||||
|
||||
@@ -12,5 +13,6 @@ Vue.config.productionTip = false
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
i18n,
|
||||
render: (h) => h(App)
|
||||
}).$mount('#app')
|
||||
|
||||
@@ -12,7 +12,7 @@ const routes: RouteConfig[] = [
|
||||
},
|
||||
{
|
||||
path: '/play',
|
||||
name: 'Home',
|
||||
name: 'HomePlay',
|
||||
component: Home,
|
||||
props: { play: true }
|
||||
}
|
||||
|
||||
@@ -165,3 +165,20 @@ footer {
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
{
|
||||
"en": {
|
||||
"madeBy": "Made by",
|
||||
"juju": "juju",
|
||||
"chillWith": "chill with",
|
||||
"chilled cow": "chilled cow"
|
||||
},
|
||||
"fr": {
|
||||
"madeBy": "Fait par",
|
||||
"juju": "juju",
|
||||
"chillWith": "Détendez-vous avec",
|
||||
"chilled cow": "chilled cow"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
Reference in New Issue
Block a user