move to nuxt-i18n, switch language,address #171
This commit is contained in:
@@ -41,7 +41,11 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updatePage (page) {
|
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) {
|
click (day) {
|
||||||
this.$emit('dayclick', day)
|
this.$emit('dayclick', day)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ v-app-bar(app aria-label='Menu' height=64)
|
|||||||
v-icon(v-text='mdiLogin')
|
v-icon(v-text='mdiLogin')
|
||||||
|
|
||||||
client-only
|
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 }")
|
template(v-slot:activator="{ on, attrs }")
|
||||||
v-btn(icon v-bind='attrs' v-on='on' title='Menu' aria-label='Menu')
|
v-btn(icon v-bind='attrs' v-on='on' title='Menu' aria-label='Menu')
|
||||||
v-icon(v-text='mdiDotsVertical')
|
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-btn(v-if='loggedIn' icon aria-label='Menu' title='Menu')
|
||||||
v-icon(v-text='mdiDotsVertical')
|
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-btn(icon target='_blank' :href='`${settings.baseurl}/feed/rss`' title='RSS' aria-label='RSS')
|
||||||
v-icon(color='orange' v-text='mdiRss')
|
v-icon(color='orange' v-text='mdiRss')
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
const locales = require('../locales/index')
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import clipboard from '../assets/clipboard'
|
import clipboard from '../assets/clipboard'
|
||||||
import { mdiPlus, mdiShareVariant, mdiLogin, mdiDotsVertical, mdiLogout, mdiAccount, mdiCog, mdiRss } from '@mdi/js'
|
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 {
|
export default {
|
||||||
name: 'Nav',
|
name: 'Nav',
|
||||||
data () {
|
data () {
|
||||||
return { mdiPlus, mdiShareVariant, mdiLogout, mdiLogin, mdiDotsVertical, mdiAccount, mdiCog, mdiRss }
|
return { mdiPlus, mdiShareVariant, mdiLogout, mdiLogin, mdiDotsVertical, mdiAccount, mdiCog, mdiRss, locales }
|
||||||
},
|
},
|
||||||
mixins: [clipboard],
|
mixins: [clipboard],
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ import SMTP from './SMTP.vue'
|
|||||||
import { mapActions, mapState } from 'vuex'
|
import { mapActions, mapState } from 'vuex'
|
||||||
import moment from 'dayjs'
|
import moment from 'dayjs'
|
||||||
import tzNames from './tz.json'
|
import tzNames from './tz.json'
|
||||||
import locales from '../../locales/esm'
|
|
||||||
import { mdiAlert, mdiArrowRight } from '@mdi/js'
|
import { mdiAlert, mdiArrowRight } from '@mdi/js'
|
||||||
|
const locales = require('../../locales/index')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -89,7 +89,8 @@
|
|||||||
"label": "Label",
|
"label": "Label",
|
||||||
"collections": "Collections",
|
"collections": "Collections",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"plugins": "Plugins"
|
"plugins": "Plugins",
|
||||||
|
"help_translate": "Help Translate"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"description": "By logging in you can publish new events.",
|
"description": "By logging in you can publish new events.",
|
||||||
|
|||||||
@@ -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'
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
en: 'English',
|
ca: 'Català',
|
||||||
eu: 'Euskara',
|
|
||||||
de: 'Deutsch',
|
de: 'Deutsch',
|
||||||
|
en: 'English',
|
||||||
es: 'Español',
|
es: 'Español',
|
||||||
|
eu: 'Euskara',
|
||||||
|
fr: 'Francais',
|
||||||
gl: 'Galego',
|
gl: 'Galego',
|
||||||
it: 'Italiano',
|
it: 'Italiano',
|
||||||
ca: 'Català',
|
|
||||||
fr: 'Francais',
|
|
||||||
nb: 'Norwegian Bokmål',
|
nb: 'Norwegian Bokmål',
|
||||||
sk: 'Slovak',
|
pl: 'Polski',
|
||||||
pl: 'Polski'
|
sk: 'Slovak'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,8 @@
|
|||||||
"import": "Importa",
|
"import": "Importa",
|
||||||
"max_events": "N. massimo eventi",
|
"max_events": "N. massimo eventi",
|
||||||
"label": "Etichetta",
|
"label": "Etichetta",
|
||||||
"collections": "Bolle"
|
"collections": "Bolle",
|
||||||
|
"help_translate": "Aiuta a tradurre"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"description": "Entrando puoi pubblicare nuovi eventi.",
|
"description": "Entrando puoi pubblicare nuovi eventi.",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const config = require('./server/config.js')
|
const config = require('./server/config.js')
|
||||||
const minifyTheme = require('minify-css-string').default
|
const minifyTheme = require('minify-css-string').default
|
||||||
|
const locales = require('./locales/index')
|
||||||
|
|
||||||
const isDev = (process.env.NODE_ENV !== 'production')
|
const isDev = (process.env.NODE_ENV !== 'production')
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@@ -35,7 +36,6 @@ module.exports = {
|
|||||||
** Plugins to load before mounting the App
|
** Plugins to load before mounting the App
|
||||||
*/
|
*/
|
||||||
plugins: [
|
plugins: [
|
||||||
'@/plugins/i18n.js',
|
|
||||||
'@/plugins/filters', // text filters, datetime filters, generic transformation helpers etc.
|
'@/plugins/filters', // text filters, datetime filters, generic transformation helpers etc.
|
||||||
'@/plugins/axios', // axios baseurl configuration
|
'@/plugins/axios', // axios baseurl configuration
|
||||||
'@/plugins/validators', // inject validators
|
'@/plugins/validators', // inject validators
|
||||||
@@ -48,6 +48,7 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
modules: [
|
modules: [
|
||||||
// Doc: https://axios.nuxtjs.org/usage
|
// Doc: https://axios.nuxtjs.org/usage
|
||||||
|
'nuxt-i18n',
|
||||||
'@nuxtjs/axios',
|
'@nuxtjs/axios',
|
||||||
'@nuxtjs/auth',
|
'@nuxtjs/auth',
|
||||||
'@nuxtjs/sitemap'
|
'@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'],
|
serverMiddleware: ['server/routes'],
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"mysql2": "^2.3.3",
|
"mysql2": "^2.3.3",
|
||||||
"nuxt-edge": "2.16.0-27720022.54e852f",
|
"nuxt-edge": "2.16.0-27720022.54e852f",
|
||||||
|
"nuxt-i18n": "^6.28.1",
|
||||||
"pg": "^8.8.0",
|
"pg": "^8.8.0",
|
||||||
"sequelize": "^6.23.0",
|
"sequelize": "^6.23.0",
|
||||||
"sequelize-slugify": "^1.6.2",
|
"sequelize-slugify": "^1.6.2",
|
||||||
@@ -74,7 +75,6 @@
|
|||||||
"tiptap-extensions": "^1.35.0",
|
"tiptap-extensions": "^1.35.0",
|
||||||
"umzug": "^2.3.0",
|
"umzug": "^2.3.0",
|
||||||
"v-calendar": "^2.4.1",
|
"v-calendar": "^2.4.1",
|
||||||
"vue-i18n": "^8.26.7",
|
|
||||||
"vuetify": "2.6.10",
|
"vuetify": "2.6.10",
|
||||||
"winston": "^3.8.2",
|
"winston": "^3.8.2",
|
||||||
"winston-daily-rotate-file": "^4.7.1",
|
"winston-daily-rotate-file": "^4.7.1",
|
||||||
|
|||||||
@@ -26,21 +26,21 @@ export default ({ app, store }) => {
|
|||||||
// set timezone to instance_timezone!!
|
// set timezone to instance_timezone!!
|
||||||
// to show local time relative to event's place
|
// to show local time relative to event's place
|
||||||
// not where in the world I'm looking at the page from
|
// 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 instance_timezone = store.state.settings.instance_timezone
|
||||||
const locale = store.state.locale
|
|
||||||
dayjs.tz.setDefault(instance_timezone)
|
dayjs.tz.setDefault(instance_timezone)
|
||||||
dayjs.locale(locale)
|
dayjs.locale(app.i18n.locale || store.state.settings.instance_locale)
|
||||||
|
|
||||||
// replace links with anchors
|
// replace links with anchors
|
||||||
// TODO: remove fb tracking id?
|
// TODO: remove fb tracking id?
|
||||||
Vue.filter('linkify', value => value.replace(/(https?:\/\/([^\s]+))/g, '<a href="$1">$2</a>'))
|
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('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('dateFormat', (value, format) => dayjs.tz(value).format(format))
|
||||||
Vue.filter('unixFormat', (timestamp, format) => dayjs.unix(timestamp).tz().format(format))
|
Vue.filter('unixFormat', (timestamp, format) => dayjs.unix(timestamp).tz().format(format))
|
||||||
|
|
||||||
// shown in mobile homepage
|
// 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') => {
|
Vue.filter('mediaURL', (event, type, format = '.jpg') => {
|
||||||
const mediaPath = type === 'download' ? '/download/' : '/media/'
|
const mediaPath = type === 'download' ? '/download/' : '/media/'
|
||||||
if (event.media && event.media.length) {
|
if (event.media && event.media.length) {
|
||||||
@@ -76,9 +76,8 @@ export default ({ app, store }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Vue.filter('when', (event) => {
|
Vue.filter('when', (event) => {
|
||||||
const start = dayjs.unix(event.start_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()
|
const end = dayjs.unix(event.end_datetime).tz().locale(app.i18n.locale || store.state.settings.instance_locale)
|
||||||
|
|
||||||
// multidate
|
// multidate
|
||||||
if (event.multidate) {
|
if (event.multidate) {
|
||||||
return `${start.format('dddd D MMMM HH:mm')} - ${end.format('dddd D MMMM HH:mm')}`
|
return `${start.format('dddd D MMMM HH:mm')} - ${end.format('dddd D MMMM HH:mm')}`
|
||||||
|
|||||||
@@ -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) {
|
async initSettings(_req, res, next) {
|
||||||
// initialize settings
|
// initialize settings
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const initialize = require('./initialize.server')
|
|||||||
|
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
const helpers = require('./helpers')
|
const helpers = require('./helpers')
|
||||||
app.use(helpers.setUserLocale)
|
|
||||||
app.use(helpers.initSettings)
|
app.use(helpers.initSettings)
|
||||||
app.use(helpers.logRequest)
|
app.use(helpers.logRequest)
|
||||||
app.use(helpers.serveStatic())
|
app.use(helpers.serveStatic())
|
||||||
@@ -73,10 +72,9 @@ async function main () {
|
|||||||
|
|
||||||
// remaining request goes to nuxt
|
// remaining request goes to nuxt
|
||||||
// first nuxt component is ./pages/index.vue (with ./layouts/default.vue)
|
// 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) => {
|
app.use(async (_req, res, next) => {
|
||||||
if (config.status === 'READY') {
|
if (config.status === 'READY') {
|
||||||
|
// TODO: fetch into layout!
|
||||||
const announceController = require('./api/controller/announce')
|
const announceController = require('./api/controller/announce')
|
||||||
res.locals.announcements = await announceController._getVisible()
|
res.locals.announcements = await announceController._getVisible()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
export const state = () => ({
|
export const state = () => ({
|
||||||
locale: '',
|
|
||||||
user_locale: {},
|
user_locale: {},
|
||||||
settings: {
|
settings: {
|
||||||
instance_timezone: 'Europe/Rome',
|
instance_timezone: 'Europe/Rome',
|
||||||
@@ -25,9 +24,6 @@ export const mutations = {
|
|||||||
setSetting (state, setting) {
|
setSetting (state, setting) {
|
||||||
state.settings[setting.key] = setting.value
|
state.settings[setting.key] = setting.value
|
||||||
},
|
},
|
||||||
setLocale (state, locale) {
|
|
||||||
state.locale = locale
|
|
||||||
},
|
|
||||||
setUserlocale (state, messages) {
|
setUserlocale (state, messages) {
|
||||||
state.user_locale = messages
|
state.user_locale = messages
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user