1
0

feat: use vue-i18n 9 for vue3

This commit is contained in:
Dominik Pschenitschni
2021-08-20 15:38:16 +02:00
parent 3d6aca3510
commit 7c3c2945f8
19 changed files with 123 additions and 71 deletions

View File

@ -34,7 +34,7 @@ import TopNavigation from './components/home/topNavigation'
import ContentAuth from './components/home/contentAuth'
import ContentLinkShare from './components/home/contentLinkShare'
import ContentNoAuth from './components/home/contentNoAuth'
import {setLanguage} from './i18n/setup'
import {setLanguage} from './i18n'
import AccountDeleteService from '@/services/accountDelete'
export default defineComponent({

View File

@ -112,6 +112,7 @@
<script>
import flatPickr from 'vue-flatpickr-component'
import 'flatpickr/dist/flatpickr.css'
import { i18n } from '@/i18n'
import {format} from 'date-fns'
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'
@ -142,7 +143,7 @@ export default {
chooseDateLabel: {
type: String,
default() {
return this.$t('input.datepicker.chooseDate')
return i18n.global.t('input.datepicker.chooseDate')
},
},
disabled: {

View File

@ -81,6 +81,7 @@
</template>
<script>
import { i18n } from '@/i18n'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
export default {
@ -141,14 +142,14 @@ export default {
createPlaceholder: {
type: String,
default() {
return this.$t('input.multiselect.createPlaceholder')
return i18n.global.t('input.multiselect.createPlaceholder')
},
},
// The text shown next to an option.
selectPlaceholder: {
type: String,
default() {
return this.$t('input.multiselect.selectPlaceholder')
return i18n.global.t('input.multiselect.selectPlaceholder')
},
},
// If true, allows for selecting multiple items. v-model will be an array with all selected values in that case.

View File

@ -23,9 +23,9 @@
</div>
</div>
<div class="api-url-info" v-else>
<i18n path="apiConfig.signInOn">
<i18n-t keypath="apiConfig.signInOn">
<span class="url" v-tooltip="apiUrl"> {{ apiDomain }} </span>
</i18n>
</i18n-t>
<br />
<a @click="() => (configureApi = true)">{{ $t('apiConfig.change') }}</a>
</div>

View File

@ -43,6 +43,8 @@
</template>
<script>
import { i18n } from '@/i18n'
export default {
name: 'create-edit',
props: {
@ -53,7 +55,7 @@ export default {
primaryLabel: {
type: String,
default() {
return this.$t('misc.create')
return i18n.global.t('misc.create')
},
},
primaryIcon: {

View File

@ -1,9 +1,9 @@
<template>
<div class="notification is-danger">
<i18n path="loadingError.failed">
<i18n-t keypath="loadingError.failed">
<a @click="() => location.reload()">{{ $t('loadingError.tryAgain') }}</a>
<a href="https://vikunja.io/contact/" rel="noreferrer noopener nofollow" target="_blank">{{ $t('loadingError.contact') }}</a>
</i18n>
</i18n-t>
</div>
</template>

View File

@ -35,7 +35,7 @@
<div class="filename">{{ a.file.name }}</div>
<div class="info">
<p class="collapses">
<i18n path="task.attachment.createdBy">
<i18n-t keypath="task.attachment.createdBy">
<span v-tooltip="formatDate(a.created)">
{{ formatDateSince(a.created) }}
</span>
@ -44,7 +44,7 @@
:user="a.createdBy"
:is-inline="true"
/>
</i18n>
</i18n-t>
<span>
{{ a.file.getHumanSize() }}
</span>

View File

@ -1,6 +1,8 @@
export const getListTitle = (l, $t) => {
import {i18n} from '@/i18n'
export const getListTitle = (l) => {
if (l.id === -1) {
return $t('list.pseudo.favorites.title')
return i18n.global.t('list.pseudo.favorites.title')
}
return l.title
}

View File

@ -1,12 +1,14 @@
export const getNamespaceTitle = (n, $t) => {
import {i18n} from '@/i18n'
export const getNamespaceTitle = (n) => {
if (n.id === -1) {
return $t('namespace.pseudo.sharedLists.title')
return i18n.global.t('namespace.pseudo.sharedLists.title')
}
if (n.id === -2) {
return $t('namespace.pseudo.favorites.title')
return i18n.global.t('namespace.pseudo.favorites.title')
}
if (n.id === -3) {
return $t('namespace.pseudo.savedFilters.title')
return i18n.global.t('namespace.pseudo.savedFilters.title')
}
return n.title
}

View File

@ -2,6 +2,8 @@ import {createDateFromString} from '@/helpers/time/createDateFromString'
import {format, formatDistance} from 'date-fns'
import {enGB, de, fr, ru} from 'date-fns/locale'
import {i18n} from '@/i18n'
const locales = {en: enGB, de, ch: de, fr, ru}
const dateIsValid = date => {
@ -12,7 +14,7 @@ const dateIsValid = date => {
return date instanceof Date && !isNaN(date)
}
export const formatDate = (date, f, locale) => {
export const formatDate = (date, f, locale = i18n.global.t('date.locale')) => {
if (!dateIsValid(date)) {
return ''
}
@ -22,7 +24,15 @@ export const formatDate = (date, f, locale) => {
return date ? format(date, f, {locale: locales[locale]}) : ''
}
export const formatDateSince = (date, $t) => {
export function formatDateLong(date) {
return formatDate(date, 'PPPPpppp')
}
export function formatDateShort(date) {
return formatDate(date, 'PPpp')
}
export const formatDateSince = (date) => {
if (!dateIsValid(date)) {
return ''
}
@ -30,11 +40,11 @@ export const formatDateSince = (date, $t) => {
date = createDateFromString(date)
const currentDate = new Date()
const distance = formatDistance(date, currentDate, {locale: locales[$t('date.locale')]})
const distance = formatDistance(date, currentDate, {locale: locales[i18n.global.t('date.locale')]})
if (date > currentDate) {
return $t('date.in', {date: distance})
return i18n.global.t('date.in', {date: distance})
}
return $t('date.ago', {date: distance})
return i18n.global.t('date.ago', {date: distance})
}

View File

@ -1,12 +1,10 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { createI18n } from 'vue-i18n'
import langEN from './lang/en.json'
Vue.use(VueI18n)
export const i18n = new VueI18n({
export const i18n = createI18n({
locale: 'en', // set locale
fallbackLocale: 'en',
globalInjection: true,
messages: {
en: langEN,
},

View File

@ -11,7 +11,7 @@ declare global {
}
}
import {formatDate, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateShort, formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
// @ts-ignore
import {VERSION} from './version.json'
@ -28,8 +28,7 @@ import vueShortkey from 'vue-shortkey'
// Vuex
import {store} from './store'
// i18n
import VueI18n from 'vue-i18n' // types
import {i18n} from './i18n/setup'
import {i18n} from './i18n'
console.info(`Vikunja frontend version ${VERSION}`)
@ -77,30 +76,19 @@ app.component('modal', Modal)
app.component('card', Card)
// Mixins
import message from './message'
import {getNamespaceTitle} from './helpers/getNamespaceTitle'
import {getListTitle} from './helpers/getListTitle'
import {colorIsDark} from './helpers/color/colorIsDark'
import {setTitle} from './helpers/setTitle'
app.mixin({
methods: {
formatDateSince(date) {
return formatDateSince(date, (p: VueI18n.Path, params?: VueI18n.Values) => this.$t(p, params))
},
formatDate(date) {
return formatDate(date, 'PPPPpppp', this.$t('date.locale'))
},
formatDateShort(date) {
return formatDate(date, 'PPpp', this.$t('date.locale'))
},
getNamespaceTitle(n) {
return getNamespaceTitle(n, (p: VueI18n.Path) => this.$t(p))
},
getListTitle(l) {
return getListTitle(l, (p: VueI18n.Path) => this.$t(p))
},
colorIsDark: colorIsDark,
setTitle: setTitle,
formatDateSince,
formatDate: formatDateLong,
formatDateShort: formatDateShort,
getNamespaceTitle,
getListTitle,
colorIsDark,
setTitle,
},
})

View File

@ -1,11 +1,11 @@
import {i18n} from '@/i18n/setup'
import {i18n} from '@/i18n'
export const getErrorText = (r) => {
if (r.response && r.response.data) {
if(r.response.data.code) {
const path = `error.${r.response.data.code}`
const message = i18n.t(path)
const message = i18n.global.t(path)
// If message and path are equal no translation exists for that error code
if (path !== message) {
@ -30,7 +30,7 @@ export const getErrorText = (r) => {
export function error(e, context, actions = []) {
context.$notify({
type: 'error',
title: i18n.t('error.error'),
title: i18n.global.t('error.error'),
text: getErrorText(e),
actions: actions,
})
@ -40,7 +40,7 @@ export function error(e, context, actions = []) {
export function success(e, context, actions = []) {
context.$notify({
type: 'success',
title: i18n.t('error.success'),
title: i18n.global.t('error.success'),
text: getErrorText(e),
data: {
actions: actions,

View File

@ -381,22 +381,22 @@
<!-- Created / Updated [by] -->
<p class="created">
<i18n path="task.detail.created">
<i18n-t keypath="task.detail.created">
<span v-tooltip="formatDate(task.created)">{{ formatDateSince(task.created) }}</span>
{{ task.createdBy.getDisplayName() }}
</i18n>
</i18n-t>
<template v-if="+new Date(task.created) !== +new Date(task.updated)">
<br/>
<!-- Computed properties to show the actual date every time it gets updated -->
<i18n path="task.detail.updated">
<i18n-t keypath="task.detail.updated">
<span v-tooltip="updatedFormatted">{{ updatedSince }}</span>
</i18n>
</i18n-t>
</template>
<template v-if="task.done">
<br/>
<i18n path="task.detail.doneAt">
<i18n-t keypath="task.detail.doneAt">
<span v-tooltip="doneFormatted">{{ doneSince }}</span>
</i18n>
</i18n-t>
</template>
</p>
</div>

View File

@ -201,7 +201,7 @@ export default {
return
}
const err = getErrorText(e, p => this.$t(p))
const err = getErrorText(e)
if (typeof err[1] !== 'undefined') {
this.$store.commit(ERROR_MESSAGE, err[1])
return

View File

@ -66,7 +66,7 @@ export default {
this.$router.push({name: 'home'})
})
.catch(e => {
const err = getErrorText(e, p => this.$t(p))
const err = getErrorText(e)
if (typeof err[1] !== 'undefined') {
this.$store.commit(ERROR_MESSAGE, err[1])
return

View File

@ -300,7 +300,7 @@ import TotpService from '../../services/totp'
import UserSettingsService from '../../services/userSettings'
import UserSettingsModel from '../../models/userSettings'
import {playSoundWhenDoneKey} from '@/helpers/playPop'
import {availableLanguages, saveLanguage, getCurrentLanguage} from '../../i18n/setup'
import {availableLanguages, saveLanguage, getCurrentLanguage} from '@/i18n'
import {getQuickAddMagicMode, setQuickAddMagicMode} from '../../helpers/quickAddMagicMode'
import {PrefixMode} from '../../modules/parseTaskText'