From d74683b5fd33c0f234b661c5d66eaa2811d27074 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 14 Jul 2019 13:21:33 -0400 Subject: [PATCH] fix: i18n client caching --- .../admin/admin-utilities-content.vue | 39 +++++++++--- ...ilities-mutation-content-migratelocale.gql | 4 +- client/modules/localization.js | 63 ++++++++++--------- package.json | 3 +- server/graph/schemas/page.graphql | 5 +- yarn.lock | 17 +++-- 6 files changed, 88 insertions(+), 43 deletions(-) diff --git a/client/components/admin/admin-utilities-content.vue b/client/components/admin/admin-utilities-content.vue index e836163c..e662a7b0 100644 --- a/client/components/admin/admin-utilities-content.vue +++ b/client/components/admin/admin-utilities-content.vue @@ -3,11 +3,30 @@ v-toolbar(flat, color='primary', dark, dense) .subheading {{ $t('admin:utilities.contentTitle') }} v-card-text - v-subheader.pl-0.primary--text Migrate all pages to base language + v-subheader.pl-0.primary--text Migrate all pages to target locale .body-1 If you created content before selecting a different locale and activating the namespacing capabilities, you may want to transfer all content to the base locale. .body-1.red--text: strong This operation is destructive and cannot be reversed! Make sure you have proper backups! - .body-1.mt-3 Based on your current configuration, all pages will be migrated to the locale #[v-chip(label, small): strong {{currentLocale.toUpperCase()}}] - .body-1.mt-3 Pages that are already in the target locale will not be touched. If a page already exists at the target, the source page will not be modified as it would create a conflict. If you want to overwrite the target content, you must first delete that page. + v-toolbar.radius-7.mt-3.wiki-form(flat, color='grey lighten-4', height='80') + v-select( + label='Source Locale' + outline + hide-details + :items='locales' + item-text='name' + item-value='code' + v-model='sourceLocale' + ) + v-icon.mx-3(large) arrow_forward + v-select( + label='Target Locale' + outline + hide-details + :items='locales' + item-text='name' + item-value='code' + v-model='targetLocale' + ) + .body-1.mt-3 Pages that are already in the target locale will not be touched. If a page already exists at the target, the source page will not be modified as it would create a conflict. If you want to overwrite the target page, you must first delete it. v-btn(outline, color='primary', @click='migrateToLocale', :disabled='loading').ml-0.mt-3 v-icon(left) build span Proceed @@ -17,17 +36,22 @@ import _ from 'lodash' import utilityContentMigrateLocaleMutation from 'gql/admin/utilities/utilities-mutation-content-migratelocale.gql' -/* global siteLang */ +/* global siteLangs, siteConfig */ export default { data: () => { return { - loading: false + loading: false, + sourceLocale: '', + targetLocale: '' } }, computed: { - currentLocale() { + currentLocale () { return siteConfig.lang + }, + locales () { + return siteLangs } }, methods: { @@ -39,7 +63,8 @@ export default { const respRaw = await this.$apollo.mutate({ mutation: utilityContentMigrateLocaleMutation, variables: { - targetLocale: siteConfig.lang + sourceLocale: this.sourceLocale, + targetLocale: this.targetLocale } }) const resp = _.get(respRaw, 'data.pages.migrateToLocale.responseResult', {}) diff --git a/client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql b/client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql index 43fb27a2..04c2558e 100644 --- a/client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql +++ b/client/graph/admin/utilities/utilities-mutation-content-migratelocale.gql @@ -1,6 +1,6 @@ -mutation { +mutation($sourceLocale: String!, $targetLocale: String!) { pages { - migrateToLocale { + migrateToLocale(sourceLocale: $sourceLocale, targetLocale: $targetLocale) { responseResult { succeeded errorCode diff --git a/client/modules/localization.js b/client/modules/localization.js index 9c533473..a9f618eb 100644 --- a/client/modules/localization.js +++ b/client/modules/localization.js @@ -1,6 +1,7 @@ import i18next from 'i18next' +import Backend from 'i18next-chained-backend' +import LocalStorageBackend from 'i18next-localstorage-backend' import i18nextXHR from 'i18next-xhr-backend' -import i18nextCache from 'i18next-localstorage-cache' import VueI18Next from '@panter/vue-i18next' import _ from 'lodash' @@ -12,37 +13,43 @@ export default { VueI18Next, init() { i18next - .use(i18nextXHR) - .use(i18nextCache) + .use(Backend) .init({ backend: { - loadPath: '{{lng}}/{{ns}}', - parse: (data) => data, - ajax: (url, opts, cb, data) => { - let langParams = url.split('/') - graphQL.query({ - query: localeQuery, - variables: { - locale: langParams[0], - namespace: langParams[1] - } - }).then(resp => { - let ns = {} - if (_.get(resp, 'data.localization.translations', []).length > 0) { - resp.data.localization.translations.forEach(entry => { - _.set(ns, entry.key, entry.value) + backends: [ + LocalStorageBackend, + i18nextXHR + ], + backendOptions: [ + { + expirationTime: 1000*60*60*24 // 24h + }, + { + loadPath: '{{lng}}/{{ns}}', + parse: (data) => data, + ajax: (url, opts, cb, data) => { + let langParams = url.split('/') + graphQL.query({ + query: localeQuery, + variables: { + locale: langParams[0], + namespace: langParams[1] + } + }).then(resp => { + let ns = {} + if (_.get(resp, 'data.localization.translations', []).length > 0) { + resp.data.localization.translations.forEach(entry => { + _.set(ns, entry.key, entry.value) + }) + } + return cb(ns, {status: '200'}) + }).catch(err => { + console.error(err) + return cb(null, {status: '404'}) }) } - return cb(ns, {status: '200'}) - }).catch(err => { - console.error(err) - return cb(null, {status: '404'}) - }) - } - }, - cache: { - enabled: true, - expiration: 60 * 60 * 1000 + } + ] }, defaultNS: 'common', lng: siteConfig.lang, diff --git a/package.json b/package.json index fa919f5d..604e5dcd 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,6 @@ "highlight.js": "9.15.8", "i18next": "17.0.4", "i18next-express-middleware": "1.8.0", - "i18next-localstorage-cache": "1.1.1", "i18next-node-fs-backend": "2.1.3", "image-size": "0.7.4", "js-base64": "2.5.1", @@ -231,6 +230,8 @@ "hammerjs": "2.0.8", "html-webpack-plugin": "3.2.0", "html-webpack-pug-plugin": "2.0.0", + "i18next-chained-backend": "2.0.0", + "i18next-localstorage-backend": "3.0.0", "i18next-xhr-backend": "3.0.0", "ignore-loader": "0.1.2", "js-cookie": "2.2.0", diff --git a/server/graph/schemas/page.graphql b/server/graph/schemas/page.graphql index f22ec17f..6eaf0545 100644 --- a/server/graph/schemas/page.graphql +++ b/server/graph/schemas/page.graphql @@ -74,7 +74,10 @@ type PageMutation { flushCache: DefaultResponse @auth(requires: ["manage:system"]) - migrateToLocale: DefaultResponse @auth(requires: ["manage:system"]) + migrateToLocale( + sourceLocale: String! + targetLocale: String! + ): DefaultResponse @auth(requires: ["manage:system"]) } # ----------------------------------------------- diff --git a/yarn.lock b/yarn.lock index 94da4136..ea2a54ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7056,6 +7056,13 @@ hyphenate-style-name@^1.0.2: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ== +i18next-chained-backend@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/i18next-chained-backend/-/i18next-chained-backend-2.0.0.tgz#faf2e8b5f081a01e74fbec1fe580c184bc64e25b" + integrity sha512-NAwfxzNUojtYc3nTCFIyNUYsxT+RFpfWc75dHbv7BsYxfbpKV1NISiFGU77D4u0wtq5IqM87YSINX/2miH9qvg== + dependencies: + "@babel/runtime" "^7.4.5" + i18next-express-middleware@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/i18next-express-middleware/-/i18next-express-middleware-1.8.0.tgz#8ef73a56036b404b162d81d4aec23cfa0ab2a609" @@ -7063,10 +7070,12 @@ i18next-express-middleware@1.8.0: dependencies: cookies "0.7.1" -i18next-localstorage-cache@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/i18next-localstorage-cache/-/i18next-localstorage-cache-1.1.1.tgz#575256cc35e8cb2d88148f754766fdd2d24bb1b7" - integrity sha1-V1JWzDXoyy2IFI91R2b90tJLsbc= +i18next-localstorage-backend@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/i18next-localstorage-backend/-/i18next-localstorage-backend-3.0.0.tgz#19b4e836e9a79e564631b88b8ba1c738375e636f" + integrity sha512-jOvnvVYP7VlA87aO0wgNeXRoj/vQHqO56UB/R6DlglWn/Ipz4rNGZUyzejJVLFaypZTZ6rpqNsB/pjSVtZm4YQ== + dependencies: + "@babel/runtime" "^7.4.5" i18next-node-fs-backend@2.1.3: version "2.1.3"