Split translations
This commit is contained in:
parent
e46fa9fba1
commit
06801e7777
5 changed files with 139 additions and 125 deletions
12
Makefile
12
Makefile
|
@ -31,11 +31,15 @@ all:
|
|||
@echo choose a target from: clean makemessages translations
|
||||
|
||||
clean:
|
||||
rm -f $(TEMPLATE_POT) $(OUTPUT_DIR)/translations.json
|
||||
rm -rf $(TEMPLATE_POT)
|
||||
|
||||
makemessages: $(TEMPLATE_POT)
|
||||
|
||||
translations: ./$(OUTPUT_DIR)/translations.json
|
||||
translations: $(LOCALE_FILES)
|
||||
mkdir -p $(OUTPUT_DIR)/translations
|
||||
@for lang in $(LOCALES); do \
|
||||
gettext-compile --output $(OUTPUT_DIR)/translations/$$lang.json $(OUTPUT_DIR)/locale/$$lang/LC_MESSAGES/app.po; \
|
||||
done;
|
||||
|
||||
# Create a main .pot template, then generate .po files for each available language.
|
||||
# Thanx to Systematic: https://github.com/Polyconseil/systematic/blob/866d5a/mk/main.mk#L167-L183
|
||||
|
@ -58,7 +62,3 @@ $(TEMPLATE_POT): $(GETTEXT_SOURCES)
|
|||
msgattrib --no-wrap --no-obsolete -o $$PO_FILE $$PO_FILE || break; \
|
||||
fi; \
|
||||
done;
|
||||
|
||||
$(OUTPUT_DIR)/translations.json: $(LOCALE_FILES)
|
||||
mkdir -p $(OUTPUT_DIR)
|
||||
gettext-compile --output $@ $(LOCALE_FILES)
|
||||
|
|
249
src/main.js
249
src/main.js
|
@ -7,17 +7,13 @@ import VueMeta from 'vue-meta'
|
|||
import App from './App.vue'
|
||||
import Home from './views/Home.vue'
|
||||
import Help from './views/Help'
|
||||
import News from './views/News'
|
||||
import Instances from './views/Instances'
|
||||
import HallOfFame from './views/Hall-Of-Fame'
|
||||
import FAQ from './views/FAQ'
|
||||
import AllContentSelections from './views/All-Content-Selections'
|
||||
|
||||
import './scss/main.scss'
|
||||
import CommonMixins from './mixins/CommonMixins'
|
||||
|
||||
const translations = require('./translations.json')
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
// ############# I18N ##############
|
||||
|
@ -32,12 +28,8 @@ const aliasesLanguages = {
|
|||
}
|
||||
const allLocales = Object.keys(availableLanguages).concat(Object.keys(aliasesLanguages))
|
||||
|
||||
Vue.use(GetTextPlugin, {
|
||||
translations,
|
||||
availableLanguages,
|
||||
defaultLanguage: 'en_US',
|
||||
silent: false
|
||||
})
|
||||
const defaultLanguage = 'en_US'
|
||||
let currentLanguage = defaultLanguage
|
||||
|
||||
const localePath = window.location.pathname
|
||||
.replace(/^\//, '')
|
||||
|
@ -46,131 +38,152 @@ const localePath = window.location.pathname
|
|||
const languageFromLocalStorage = localStorage.getItem('language')
|
||||
|
||||
if (allLocales.includes(localePath)) {
|
||||
Vue.config.language = aliasesLanguages[localePath] ? aliasesLanguages[localePath] : localePath
|
||||
localStorage.setItem('language', Vue.config.language)
|
||||
currentLanguage = aliasesLanguages[localePath] ? aliasesLanguages[localePath] : localePath
|
||||
localStorage.setItem('language', currentLanguage)
|
||||
} else if (languageFromLocalStorage) {
|
||||
Vue.config.language = languageFromLocalStorage
|
||||
currentLanguage = languageFromLocalStorage
|
||||
} else {
|
||||
const navigatorLanguage = window.navigator.userLanguage || window.navigator.language
|
||||
const snakeCaseLanguage = navigatorLanguage.replace('-', '_')
|
||||
Vue.config.language = aliasesLanguages[snakeCaseLanguage] ? aliasesLanguages[snakeCaseLanguage] : snakeCaseLanguage
|
||||
currentLanguage = aliasesLanguages[snakeCaseLanguage] ? aliasesLanguages[snakeCaseLanguage] : snakeCaseLanguage
|
||||
}
|
||||
|
||||
Vue.filter('translate', value => {
|
||||
return value ? Vue.prototype.$gettext(value.toString()) : ''
|
||||
})
|
||||
|
||||
// ###########################
|
||||
const p = currentLanguage === defaultLanguage
|
||||
? Promise.resolve({ default: {} })
|
||||
: import('../public/translations/' + currentLanguage + '.json')
|
||||
|
||||
Vue.use(VueMeta)
|
||||
|
||||
Vue.mixin(CommonMixins)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
component: Help
|
||||
},
|
||||
{
|
||||
path: '/news',
|
||||
component: News
|
||||
},
|
||||
{
|
||||
path: '/instances',
|
||||
component: Instances
|
||||
},
|
||||
{
|
||||
path: '/hall-of-fame',
|
||||
component: HallOfFame
|
||||
},
|
||||
{
|
||||
path: '/faq',
|
||||
component: FAQ
|
||||
},
|
||||
{
|
||||
path: '/content-selections',
|
||||
component: AllContentSelections
|
||||
}
|
||||
]
|
||||
|
||||
for (const locale of allLocales) {
|
||||
routes.push({
|
||||
path: '/' + locale,
|
||||
component: Home
|
||||
p.catch(err => {
|
||||
console.error('Cannot load translations.', err)
|
||||
return { default: {} }
|
||||
}).then(module => {
|
||||
Vue.use(GetTextPlugin, {
|
||||
translations: module.default,
|
||||
availableLanguages,
|
||||
defaultLanguage: 'en_US',
|
||||
silent: process.env.NODE_ENV === 'development'
|
||||
})
|
||||
}
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes,
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
if (to.hash) {
|
||||
return { selector: to.hash }
|
||||
} else {
|
||||
return { x: 0, y: 0 }
|
||||
Vue.config.language = currentLanguage
|
||||
|
||||
// ###########################
|
||||
|
||||
Vue.use(VueMeta)
|
||||
|
||||
Vue.mixin(CommonMixins)
|
||||
|
||||
const HallOfFame = () => import('./views/Hall-Of-Fame')
|
||||
const News = () => import('./views/News')
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
component: Help
|
||||
},
|
||||
{
|
||||
path: '/news',
|
||||
component: News
|
||||
},
|
||||
{
|
||||
path: '/instances',
|
||||
component: Instances
|
||||
},
|
||||
{
|
||||
path: '/hall-of-fame',
|
||||
component: HallOfFame
|
||||
},
|
||||
{
|
||||
path: '/faq',
|
||||
component: FAQ
|
||||
},
|
||||
{
|
||||
path: '/content-selections',
|
||||
component: AllContentSelections
|
||||
}
|
||||
]
|
||||
|
||||
for (const locale of allLocales) {
|
||||
routes.push({
|
||||
path: '/' + locale,
|
||||
component: Home
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Stats Matomo
|
||||
if (!(navigator.doNotTrack === 'yes' ||
|
||||
navigator.doNotTrack === '1' ||
|
||||
navigator.msDoNotTrack === '1' ||
|
||||
window.doNotTrack === '1')
|
||||
) {
|
||||
Vue.use(VueMatomo, {
|
||||
// Configure your matomo server and site
|
||||
host: 'https://stats.framasoft.org/',
|
||||
siteId: 68,
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes,
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
if (to.hash) {
|
||||
return { selector: to.hash }
|
||||
} else {
|
||||
return { x: 0, y: 0 }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Enables automatically registering pageviews on the router
|
||||
// Stats Matomo
|
||||
if (!(navigator.doNotTrack === 'yes' ||
|
||||
navigator.doNotTrack === '1' ||
|
||||
navigator.msDoNotTrack === '1' ||
|
||||
window.doNotTrack === '1')
|
||||
) {
|
||||
Vue.use(VueMatomo, {
|
||||
// Configure your matomo server and site
|
||||
host: 'https://stats.framasoft.org/',
|
||||
siteId: 68,
|
||||
|
||||
// Enables automatically registering pageviews on the router
|
||||
router,
|
||||
|
||||
// Require consent before sending tracking information to matomo
|
||||
// Default: false
|
||||
requireConsent: false,
|
||||
|
||||
// Whether to track the initial page view
|
||||
// Default: true
|
||||
trackInitialView: true,
|
||||
|
||||
// Changes the default .js and .php endpoint's filename
|
||||
// Default: 'piwik'
|
||||
trackerFileName: 'p',
|
||||
|
||||
enableLinkTracking: true
|
||||
})
|
||||
|
||||
const _paq = _paq || [] // eslint-disable-line
|
||||
|
||||
// CNIL conformity
|
||||
_paq.push([function piwikCNIL () {
|
||||
const self = this
|
||||
|
||||
function getOriginalVisitorCookieTimeout () {
|
||||
const now = new Date()
|
||||
const nowTs = Math.round(now.getTime() / 1000)
|
||||
const visitorInfo = self.getVisitorInfo()
|
||||
const createTs = parseInt(visitorInfo[2], 10)
|
||||
const cookieTimeout = 33696000 // 13 months in seconds
|
||||
return (createTs + cookieTimeout) - nowTs
|
||||
}
|
||||
|
||||
this.setVisitorCookieTimeout(getOriginalVisitorCookieTimeout())
|
||||
}])
|
||||
}
|
||||
|
||||
new Vue({ // eslint-disable-line no-new
|
||||
el: '#app',
|
||||
router,
|
||||
|
||||
// Require consent before sending tracking information to matomo
|
||||
// Default: false
|
||||
requireConsent: false,
|
||||
|
||||
// Whether to track the initial page view
|
||||
// Default: true
|
||||
trackInitialView: true,
|
||||
|
||||
// Changes the default .js and .php endpoint's filename
|
||||
// Default: 'piwik'
|
||||
trackerFileName: 'p',
|
||||
|
||||
enableLinkTracking: true
|
||||
mounted () {
|
||||
// You'll need this for renderAfterDocumentEvent.
|
||||
document.dispatchEvent(new Event('render-event'))
|
||||
},
|
||||
render: h => h(App)
|
||||
})
|
||||
|
||||
const _paq = _paq || [] // eslint-disable-line
|
||||
|
||||
// CNIL conformity
|
||||
_paq.push([function piwikCNIL () {
|
||||
const self = this
|
||||
|
||||
function getOriginalVisitorCookieTimeout () {
|
||||
const now = new Date()
|
||||
const nowTs = Math.round(now.getTime() / 1000)
|
||||
const visitorInfo = self.getVisitorInfo()
|
||||
const createTs = parseInt(visitorInfo[2], 10)
|
||||
const cookieTimeout = 33696000 // 13 months in seconds
|
||||
return (createTs + cookieTimeout) - nowTs
|
||||
}
|
||||
|
||||
this.setVisitorCookieTimeout(getOriginalVisitorCookieTimeout())
|
||||
}])
|
||||
}
|
||||
|
||||
new Vue({ // eslint-disable-line no-new
|
||||
el: '#app',
|
||||
router,
|
||||
mounted () {
|
||||
// You'll need this for renderAfterDocumentEvent.
|
||||
document.dispatchEvent(new Event('render-event'))
|
||||
},
|
||||
render: h => h(App)
|
||||
})
|
||||
|
|
File diff suppressed because one or more lines are too long
1
src/translations/en_US.json
Normal file
1
src/translations/en_US.json
Normal file
File diff suppressed because one or more lines are too long
1
src/translations/fr_FR.json
Normal file
1
src/translations/fr_FR.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue