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
|
@echo choose a target from: clean makemessages translations
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TEMPLATE_POT) $(OUTPUT_DIR)/translations.json
|
rm -rf $(TEMPLATE_POT)
|
||||||
|
|
||||||
makemessages: $(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.
|
# 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
|
# 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; \
|
msgattrib --no-wrap --no-obsolete -o $$PO_FILE $$PO_FILE || break; \
|
||||||
fi; \
|
fi; \
|
||||||
done;
|
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 App from './App.vue'
|
||||||
import Home from './views/Home.vue'
|
import Home from './views/Home.vue'
|
||||||
import Help from './views/Help'
|
import Help from './views/Help'
|
||||||
import News from './views/News'
|
|
||||||
import Instances from './views/Instances'
|
import Instances from './views/Instances'
|
||||||
import HallOfFame from './views/Hall-Of-Fame'
|
|
||||||
import FAQ from './views/FAQ'
|
import FAQ from './views/FAQ'
|
||||||
import AllContentSelections from './views/All-Content-Selections'
|
import AllContentSelections from './views/All-Content-Selections'
|
||||||
|
|
||||||
import './scss/main.scss'
|
import './scss/main.scss'
|
||||||
import CommonMixins from './mixins/CommonMixins'
|
import CommonMixins from './mixins/CommonMixins'
|
||||||
|
|
||||||
const translations = require('./translations.json')
|
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
// ############# I18N ##############
|
// ############# I18N ##############
|
||||||
|
@ -32,12 +28,8 @@ const aliasesLanguages = {
|
||||||
}
|
}
|
||||||
const allLocales = Object.keys(availableLanguages).concat(Object.keys(aliasesLanguages))
|
const allLocales = Object.keys(availableLanguages).concat(Object.keys(aliasesLanguages))
|
||||||
|
|
||||||
Vue.use(GetTextPlugin, {
|
const defaultLanguage = 'en_US'
|
||||||
translations,
|
let currentLanguage = defaultLanguage
|
||||||
availableLanguages,
|
|
||||||
defaultLanguage: 'en_US',
|
|
||||||
silent: false
|
|
||||||
})
|
|
||||||
|
|
||||||
const localePath = window.location.pathname
|
const localePath = window.location.pathname
|
||||||
.replace(/^\//, '')
|
.replace(/^\//, '')
|
||||||
|
@ -46,131 +38,152 @@ const localePath = window.location.pathname
|
||||||
const languageFromLocalStorage = localStorage.getItem('language')
|
const languageFromLocalStorage = localStorage.getItem('language')
|
||||||
|
|
||||||
if (allLocales.includes(localePath)) {
|
if (allLocales.includes(localePath)) {
|
||||||
Vue.config.language = aliasesLanguages[localePath] ? aliasesLanguages[localePath] : localePath
|
currentLanguage = aliasesLanguages[localePath] ? aliasesLanguages[localePath] : localePath
|
||||||
localStorage.setItem('language', Vue.config.language)
|
localStorage.setItem('language', currentLanguage)
|
||||||
} else if (languageFromLocalStorage) {
|
} else if (languageFromLocalStorage) {
|
||||||
Vue.config.language = languageFromLocalStorage
|
currentLanguage = languageFromLocalStorage
|
||||||
} else {
|
} else {
|
||||||
const navigatorLanguage = window.navigator.userLanguage || window.navigator.language
|
const navigatorLanguage = window.navigator.userLanguage || window.navigator.language
|
||||||
const snakeCaseLanguage = navigatorLanguage.replace('-', '_')
|
const snakeCaseLanguage = navigatorLanguage.replace('-', '_')
|
||||||
Vue.config.language = aliasesLanguages[snakeCaseLanguage] ? aliasesLanguages[snakeCaseLanguage] : snakeCaseLanguage
|
currentLanguage = aliasesLanguages[snakeCaseLanguage] ? aliasesLanguages[snakeCaseLanguage] : snakeCaseLanguage
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.filter('translate', value => {
|
Vue.filter('translate', value => {
|
||||||
return value ? Vue.prototype.$gettext(value.toString()) : ''
|
return value ? Vue.prototype.$gettext(value.toString()) : ''
|
||||||
})
|
})
|
||||||
|
|
||||||
// ###########################
|
const p = currentLanguage === defaultLanguage
|
||||||
|
? Promise.resolve({ default: {} })
|
||||||
|
: import('../public/translations/' + currentLanguage + '.json')
|
||||||
|
|
||||||
Vue.use(VueMeta)
|
p.catch(err => {
|
||||||
|
console.error('Cannot load translations.', err)
|
||||||
Vue.mixin(CommonMixins)
|
return { default: {} }
|
||||||
|
}).then(module => {
|
||||||
const routes = [
|
Vue.use(GetTextPlugin, {
|
||||||
{
|
translations: module.default,
|
||||||
path: '/',
|
availableLanguages,
|
||||||
component: Home
|
defaultLanguage: 'en_US',
|
||||||
},
|
silent: process.env.NODE_ENV === 'development'
|
||||||
{
|
|
||||||
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
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
const router = new VueRouter({
|
Vue.config.language = currentLanguage
|
||||||
mode: 'history',
|
|
||||||
base: process.env.BASE_URL,
|
// ###########################
|
||||||
routes,
|
|
||||||
scrollBehavior (to, from, savedPosition) {
|
Vue.use(VueMeta)
|
||||||
if (to.hash) {
|
|
||||||
return { selector: to.hash }
|
Vue.mixin(CommonMixins)
|
||||||
} else {
|
|
||||||
return { x: 0, y: 0 }
|
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
|
const router = new VueRouter({
|
||||||
if (!(navigator.doNotTrack === 'yes' ||
|
mode: 'history',
|
||||||
navigator.doNotTrack === '1' ||
|
base: process.env.BASE_URL,
|
||||||
navigator.msDoNotTrack === '1' ||
|
routes,
|
||||||
window.doNotTrack === '1')
|
scrollBehavior (to, from, savedPosition) {
|
||||||
) {
|
if (to.hash) {
|
||||||
Vue.use(VueMatomo, {
|
return { selector: to.hash }
|
||||||
// Configure your matomo server and site
|
} else {
|
||||||
host: 'https://stats.framasoft.org/',
|
return { x: 0, y: 0 }
|
||||||
siteId: 68,
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 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,
|
router,
|
||||||
|
mounted () {
|
||||||
// Require consent before sending tracking information to matomo
|
// You'll need this for renderAfterDocumentEvent.
|
||||||
// Default: false
|
document.dispatchEvent(new Event('render-event'))
|
||||||
requireConsent: false,
|
},
|
||||||
|
render: h => h(App)
|
||||||
// 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,
|
|
||||||
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