move to nuxt-i18n, switch language,address #171

This commit is contained in:
lesion 2022-10-12 12:45:09 +02:00
parent 33084237e9
commit 2cb4359ffd
No known key found for this signature in database
GPG key ID: 352918250B012177
13 changed files with 59 additions and 48 deletions

View file

@ -41,7 +41,11 @@ export default {
},
methods: {
updatePage (page) {
this.$emit('monthchange', page)
if (page.month !== this.page.month || page.year !== this.page.year) {
this.$emit('monthchange', page)
this.page.month = page.month
this.page.year = page.year
}
},
click (day) {
this.$emit('dayclick', day)

View file

@ -21,7 +21,7 @@ v-app-bar(app aria-label='Menu' height=64)
v-icon(v-text='mdiLogin')
client-only
v-menu(v-if='loggedIn' offset-y eager)
v-menu(v-if='loggedIn' offset-y transition="slide-y-transition")
template(v-slot:activator="{ on, attrs }")
v-btn(icon v-bind='attrs' v-on='on' title='Menu' aria-label='Menu')
v-icon(v-text='mdiDotsVertical')
@ -47,12 +47,26 @@ v-app-bar(app aria-label='Menu' height=64)
v-btn(v-if='loggedIn' icon aria-label='Menu' title='Menu')
v-icon(v-text='mdiDotsVertical')
client-only
v-menu(offset-y transition="slide-y-transition" min-width='200px' max-height='400px')
template(v-slot:activator="{ on, attrs }")
v-btn(icon v-bind='attrs' v-on='on' aria-label='Language') {{$i18n.locale}}
v-list
v-list-item(v-for='locale in $i18n.locales' @click.prevent.stop="$i18n.setLocale(locale.code)" :key='locale.code')
v-list-item-content
v-list-item-title {{locale.name}}
v-list-item(nuxt target='_blank' href='https://hosted.weblate.org/engage/gancio/')
v-list-item-content
v-list-item-subtitle(v-text='$t("common.help_translate")')
template(#placeholder)
v-btn(icon aria-label='Language') {{$i18n.locale}}
v-btn(icon target='_blank' :href='`${settings.baseurl}/feed/rss`' title='RSS' aria-label='RSS')
v-icon(color='orange' v-text='mdiRss')
</template>
<script>
const locales = require('../locales/index')
import { mapState } from 'vuex'
import clipboard from '../assets/clipboard'
import { mdiPlus, mdiShareVariant, mdiLogin, mdiDotsVertical, mdiLogout, mdiAccount, mdiCog, mdiRss } from '@mdi/js'
@ -61,7 +75,7 @@ import { mdiPlus, mdiShareVariant, mdiLogin, mdiDotsVertical, mdiLogout, mdiAcco
export default {
name: 'Nav',
data () {
return { mdiPlus, mdiShareVariant, mdiLogout, mdiLogin, mdiDotsVertical, mdiAccount, mdiCog, mdiRss }
return { mdiPlus, mdiShareVariant, mdiLogout, mdiLogin, mdiDotsVertical, mdiAccount, mdiCog, mdiRss, locales }
},
mixins: [clipboard],
computed: {

View file

@ -63,8 +63,8 @@ import SMTP from './SMTP.vue'
import { mapActions, mapState } from 'vuex'
import moment from 'dayjs'
import tzNames from './tz.json'
import locales from '../../locales/esm'
import { mdiAlert, mdiArrowRight } from '@mdi/js'
const locales = require('../../locales/index')
export default {
props: {

View file

@ -89,7 +89,8 @@
"label": "Label",
"collections": "Collections",
"close": "Close",
"plugins": "Plugins"
"plugins": "Plugins",
"help_translate": "Help Translate"
},
"login": {
"description": "By logging in you can publish new events.",

View file

@ -1,13 +0,0 @@
export default {
ca: 'Català',
de: 'Deutsch',
en: 'English',
es: 'Español',
eu: 'Euskara',
fr: 'Francais',
gl: 'Galego',
it: 'Italiano',
nb: 'Norwegian Bokmål',
pl: 'Polski',
sk: 'Slovak'
}

View file

@ -1,13 +1,13 @@
module.exports = {
en: 'English',
eu: 'Euskara',
ca: 'Català',
de: 'Deutsch',
en: 'English',
es: 'Español',
eu: 'Euskara',
fr: 'Francais',
gl: 'Galego',
it: 'Italiano',
ca: 'Català',
fr: 'Francais',
nb: 'Norwegian Bokmål',
sk: 'Slovak',
pl: 'Polski'
pl: 'Polski',
sk: 'Slovak'
}

View file

@ -87,7 +87,8 @@
"import": "Importa",
"max_events": "N. massimo eventi",
"label": "Etichetta",
"collections": "Bolle"
"collections": "Bolle",
"help_translate": "Aiuta a tradurre"
},
"login": {
"description": "Entrando puoi pubblicare nuovi eventi.",

View file

@ -1,5 +1,6 @@
const config = require('./server/config.js')
const minifyTheme = require('minify-css-string').default
const locales = require('./locales/index')
const isDev = (process.env.NODE_ENV !== 'production')
module.exports = {
@ -35,7 +36,6 @@ module.exports = {
** Plugins to load before mounting the App
*/
plugins: [
'@/plugins/i18n.js',
'@/plugins/filters', // text filters, datetime filters, generic transformation helpers etc.
'@/plugins/axios', // axios baseurl configuration
'@/plugins/validators', // inject validators
@ -48,6 +48,7 @@ module.exports = {
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'nuxt-i18n',
'@nuxtjs/axios',
'@nuxtjs/auth',
'@nuxtjs/sitemap'
@ -76,6 +77,23 @@ module.exports = {
}
}
},
i18n: {
locales: Object.keys(locales).map(key => ({
code: key,
name: locales[key],
file: `${key}.json`,
iso: key
})),
vueI18n: {
fallbackLocale: 'en'
},
langDir: 'locales',
lazy: true,
strategy: 'no_prefix',
baseUrl: config.baseurl,
skipSettingLocaleOnNavigate: true,
skipNuxtState: true
},
serverMiddleware: ['server/routes'],

View file

@ -64,6 +64,7 @@
"multer": "^1.4.5-lts.1",
"mysql2": "^2.3.3",
"nuxt-edge": "2.16.0-27720022.54e852f",
"nuxt-i18n": "^6.28.1",
"pg": "^8.8.0",
"sequelize": "^6.23.0",
"sequelize-slugify": "^1.6.2",
@ -74,7 +75,6 @@
"tiptap-extensions": "^1.35.0",
"umzug": "^2.3.0",
"v-calendar": "^2.4.1",
"vue-i18n": "^8.26.7",
"vuetify": "2.6.10",
"winston": "^3.8.2",
"winston-daily-rotate-file": "^4.7.1",

View file

@ -26,21 +26,21 @@ export default ({ app, store }) => {
// set timezone to instance_timezone!!
// to show local time relative to event's place
// not where in the world I'm looking at the page from
app.i18n.defaultLocale = store.state.settings.instance_locale
const instance_timezone = store.state.settings.instance_timezone
const locale = store.state.locale
dayjs.tz.setDefault(instance_timezone)
dayjs.locale(locale)
dayjs.locale(app.i18n.locale || store.state.settings.instance_locale)
// replace links with anchors
// TODO: remove fb tracking id?
Vue.filter('linkify', value => value.replace(/(https?:\/\/([^\s]+))/g, '<a href="$1">$2</a>'))
Vue.filter('url2host', url => url.match(/^https?:\/\/(.[^/:]+)/i)[1])
Vue.filter('datetime', value => dayjs.tz(value).locale(locale).format('ddd, D MMMM HH:mm'))
Vue.filter('datetime', value => dayjs.tz(value).locale(app.i18n.locale || store.state.settings.instance_locale).format('ddd, D MMMM HH:mm'))
Vue.filter('dateFormat', (value, format) => dayjs.tz(value).format(format))
Vue.filter('unixFormat', (timestamp, format) => dayjs.unix(timestamp).tz().format(format))
// shown in mobile homepage
Vue.filter('day', value => dayjs.unix(value).tz().locale(store.state.locale).format('dddd, D MMM'))
Vue.filter('day', value => dayjs.unix(value).tz().locale(app.i18n.locale || store.state.settings.instance_locale).format('dddd, D MMM'))
Vue.filter('mediaURL', (event, type, format = '.jpg') => {
const mediaPath = type === 'download' ? '/download/' : '/media/'
if (event.media && event.media.length) {
@ -76,9 +76,8 @@ export default ({ app, store }) => {
})
Vue.filter('when', (event) => {
const start = dayjs.unix(event.start_datetime).tz()
const end = dayjs.unix(event.end_datetime).tz()
const start = dayjs.unix(event.start_datetime).tz().locale(app.i18n.locale || store.state.settings.instance_locale)
const end = dayjs.unix(event.end_datetime).tz().locale(app.i18n.locale || store.state.settings.instance_locale)
// multidate
if (event.multidate) {
return `${start.format('dddd D MMMM HH:mm')} - ${end.format('dddd D MMMM HH:mm')}`

View file

@ -63,13 +63,6 @@ module.exports = {
})
},
async setUserLocale(req, res, next) {
// select locale based on cookie? and accept-language header
acceptLanguage.languages(Object.keys(locales))
res.locals.acceptedLocale = acceptLanguage.get(req.headers['accept-language'])
dayjs.locale(res.locals.acceptedLocale)
next()
},
async initSettings(_req, res, next) {
// initialize settings

View file

@ -5,7 +5,6 @@ const initialize = require('./initialize.server')
const config = require('./config')
const helpers = require('./helpers')
app.use(helpers.setUserLocale)
app.use(helpers.initSettings)
app.use(helpers.logRequest)
app.use(helpers.serveStatic())
@ -73,10 +72,9 @@ async function main () {
// remaining request goes to nuxt
// first nuxt component is ./pages/index.vue (with ./layouts/default.vue)
// prefill current events, tags, places and announcements (used in every path)
app.use(async (_req, res, next) => {
if (config.status === 'READY') {
// TODO: fetch into layout!
const announceController = require('./api/controller/announce')
res.locals.announcements = await announceController._getVisible()
}

View file

@ -1,5 +1,4 @@
export const state = () => ({
locale: '',
user_locale: {},
settings: {
instance_timezone: 'Europe/Rome',
@ -25,9 +24,6 @@ export const mutations = {
setSetting (state, setting) {
state.settings[setting.key] = setting.value
},
setLocale (state, locale) {
state.locale = locale
},
setUserlocale (state, messages) {
state.user_locale = messages
},