From eb66ae608843501ae41b6189237171976641ce6b Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 9 Jun 2019 23:39:37 -0400 Subject: [PATCH] feat: admin translations --- client/components/admin/admin-auth.vue | 4 +- client/components/admin/admin-contribute.vue | 4 +- client/components/admin/admin-dashboard.vue | 18 +++---- client/components/admin/admin-general.vue | 37 +++++++------ client/components/admin/admin-locale.vue | 5 +- client/components/admin/admin-search.vue | 22 ++++---- client/components/admin/admin-storage.vue | 56 ++++++++++---------- 7 files changed, 76 insertions(+), 70 deletions(-) diff --git a/client/components/admin/admin-auth.vue b/client/components/admin/admin-auth.vue index 0e7d84dc..c9b1b347 100644 --- a/client/components/admin/admin-auth.vue +++ b/client/components/admin/admin-auth.vue @@ -247,7 +247,7 @@ export default { async refresh() { await this.$apollo.queries.strategies.refetch() this.$store.commit('showNotification', { - message: 'List of strategies has been refreshed.', + message: this.$t('admin:auth.refreshSuccess'), style: 'success', icon: 'cached' }) @@ -274,7 +274,7 @@ export default { } }) this.$store.commit('showNotification', { - message: 'Authentication configuration saved successfully.', + message: this.$t('admin:auth.saveSuccess'), style: 'success', icon: 'check' }) diff --git a/client/components/admin/admin-contribute.vue b/client/components/admin/admin-contribute.vue index 3a9b32cd..3b57e773 100644 --- a/client/components/admin/admin-contribute.vue +++ b/client/components/admin/admin-contribute.vue @@ -73,11 +73,11 @@ .body-1.pl-3 ul i18next(path='admin:contribute.submitAnIdea', tag='li') - a(href='https://requests.requarks.io/wiki', target='_blank') {{ $t('admin:contribute.submitAnIdeaLink') }} + a(href='https://wiki.js.org/feedback', target='_blank') {{ $t('admin:contribute.submitAnIdeaLink') }} i18next(path='admin:contribute.foundABug', tag='li') a(href='https://github.com/Requarks/wiki/issues', target='_blank') Github i18next(path='admin:contribute.helpTranslate', tag='li') - a(href='https://gitter.im/Requarks/wiki', target='_blank') Gitter + a(href='https://wiki.requarks.io/slack', target='_blank') Slack v-divider.mt-3 v-subheader {{ $t('admin:contribute.spreadTheWord') }} .body-1.pl-3 diff --git a/client/components/admin/admin-dashboard.vue b/client/components/admin/admin-dashboard.vue index f3d74442..e87285a8 100644 --- a/client/components/admin/admin-dashboard.vue +++ b/client/components/admin/admin-dashboard.vue @@ -11,7 +11,7 @@ v-card.primary.dashboard-card.animated.fadeInUp(dark) v-card-text v-icon.dashboard-icon insert_drive_file - .subheading Pages + .subheading {{$t('admin:dashboard.pages')}} animated-number.display-1( :value='info.pagesTotal' :duration='2000' @@ -22,7 +22,7 @@ v-card.indigo.lighten-1.dashboard-card.animated.fadeInUp.wait-p2s(dark) v-card-text v-icon.dashboard-icon person - .subheading Users + .subheading {{$t('admin:dashboard.users')}} animated-number.display-1( :value='info.usersTotal' :duration='2000' @@ -33,7 +33,7 @@ v-card.indigo.lighten-2.dashboard-card.animated.fadeInUp.wait-p4s(dark) v-card-text v-icon.dashboard-icon people - .subheading Groups + .subheading {{$t('admin:dashboard.groups')}} animated-number.display-1( :value='info.groupsTotal' :duration='2000' @@ -50,8 +50,8 @@ v-card-text v-icon.dashboard-icon blur_on .subheading Wiki.js {{info.currentVersion}} - .body-2(v-if='isLatestVersion') You are running the latest version. - .body-2(v-else) A new version is available: {{info.latestVersion}} + .body-2(v-if='isLatestVersion') {{$t('admin:dashboard.versionLatest')}} + .body-2(v-else) {{$t('admin:dashboard.versionNew', { version: info.latestVersion })}} v-flex(xs12) v-card.radius-7 v-card-title.subheading(:class='$vuetify.dark ? `grey darken-2` : `grey lighten-5`') Recent Pages @@ -92,10 +92,10 @@ v-card-text img(src='/svg/icon-heart-health.svg', alt='Contribute', style='height: 80px;') .pl-3 - .subheading Contribute - .body-2.pt-2 Wiki.js is a free and open source project. There are several ways you can contribute to the project. - .body-1 We need your help! - v-btn.mx-0.mt-2(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outline, small, to='/contribute') Learn More + .subheading {{$t('admin:contribute.title')}} + .body-2.pt-2 {{$t('admin:dashboard.contributeSubtitle')}} + .body-1 {{$t('admin:dashboard.contributeHelp')}} + v-btn.mx-0.mt-2(:color='$vuetify.dark ? `indigo lighten-3` : `indigo`', outline, small, to='/contribute') {{$t('admin:dashboard.contributeLearnMore')}} diff --git a/client/components/admin/admin-general.vue b/client/components/admin/admin-general.vue index 209f58c5..c8a2c689 100644 --- a/client/components/admin/admin-general.vue +++ b/client/components/admin/admin-general.vue @@ -19,75 +19,75 @@ v-toolbar(color='primary', dark, dense, flat) v-toolbar-title .subheading {{ $t('admin:general.siteInfo') }} - v-subheader General + v-subheader {{$t('admin:general.general')}} .px-3.pb-3 v-text-field( outline - label='Site URL' + :label='$t(`admin:general.siteUrl`)' required :counter='255' v-model='config.host' prepend-icon='label_important' - hint='Full URL to your wiki, without the trailing slash. (e.g. https://wiki.example.com)' + :hint='$t(`admin:general.siteUrlHint`)' persistent-hint ) v-text-field.mt-2( outline - label='Site Title' + :label='$t(`admin:general.siteTitle`)' required :counter='50' v-model='config.title' prepend-icon='public' - hint='Displayed in the top bar and appended to all pages meta title.' + :hint='$t(`admin:general.siteTitleHint`)' persistent-hint ) v-divider - v-subheader Logo #[v-chip.ml-2(label, color='grey', small, outline) coming soon] + v-subheader {{$t('admin:general.logo')}} #[v-chip.ml-2(label, color='grey', small, outline) coming soon] v-card-text.pb-4.pl-5 v-layout.px-3(row, align-center) v-avatar(size='100', :color='$vuetify.dark ? `grey darken-2` : `grey lighten-3`', :tile='config.logoIsSquare') .ml-4 v-btn.mx-0(color='teal', depressed, disabled) v-icon(left) cloud_upload - span Upload Logo + span {{$t('admin:general.uploadLogo')}} v-btn(color='teal', depressed, disabled) v-icon(left) clear - span Clear - .caption.grey--text An image of 120x120 pixels is recommended for best results. - .caption.grey--text SVG, PNG or JPG files only. + span {{$t('admin:general.uploadClear')}} + .caption.grey--text {{$t('admin:general.uploadSizeHint', { size: '120x120' })}} + .caption.grey--text {{$t('admin:general.uploadTypesHint', { typeList: 'SVG, PNG', lastType: 'JPG' })}}. v-divider - v-subheader Footer Copyright + v-subheader {{$t('admin:general.footerCopyright')}} .px-3.pb-3 v-text-field( outline - label='Company / Organization Name' + :label='$t(`admin:general.companyName`)' v-model='config.company' :counter='255' prepend-icon='business' persistent-hint - hint='Name to use when displaying copyright notice in the footer. Leave empty to hide.' + :hint='$t(`admin:general.companyNameHint`)' ) v-divider v-subheader SEO .px-3.pb-3 v-text-field( outline - label='Site Description' + :label='$t(`admin:general.siteDescription`)' :counter='255' v-model='config.description' prepend-icon='explore' - hint='Default description when none is provided for a page.' + :hint='$t(`admin:general.siteDescriptionHint`)' persistent-hint ) v-select.mt-2( outline - label='Meta Robots' + :label='$t(`admin:general.metaRobots`)' multiple :items='metaRobots' v-model='config.robots' prepend-icon='explore' :return-object='false' - hint='Default: Index, Follow. Can also be set on a per-page basis.' + :hint='$t(`admin:general.metaRobotsHint`)' persistent-hint ) @@ -155,6 +155,7 @@ v-model='config.featurePageRatings' persistent-hint hint='Allow users to rate pages.' + disabled ) v-divider.mt-3 @@ -164,6 +165,7 @@ v-model='config.featurePageComments' persistent-hint hint='Allow users to leave comments on pages.' + disabled ) v-divider.mt-3 @@ -173,6 +175,7 @@ v-model='config.featurePersonalWikis' persistent-hint hint='Allow users to have their own personal wiki.' + disabled ) diff --git a/client/components/admin/admin-locale.vue b/client/components/admin/admin-locale.vue index e16d17df..7fefc486 100644 --- a/client/components/admin/admin-locale.vue +++ b/client/components/admin/admin-locale.vue @@ -113,8 +113,9 @@ v-list-tile-sub-title(v-html='lc.nativeName') v-list-tile-action(v-if='lc.isRTL') v-chip(label, small, :class='$vuetify.dark ? `text--lighten-5` : `text--darken-2`').caption.grey--text RTL - v-list-tile-action(v-if='lc.isInstalled && lc.installDate < lc.updatedAt', @click='download(lc.code)') - v-icon.blue--text cached + v-list-tile-action(v-if='lc.isInstalled && lc.installDate < lc.updatedAt') + v-btn(icon, @click='download(lc)') + v-icon.blue--text cached v-list-tile-action(v-else-if='lc.isInstalled') v-icon.green--text check v-list-tile-action(v-else-if='lc.isDownloading') diff --git a/client/components/admin/admin-search.vue b/client/components/admin/admin-search.vue index eaa0d464..a34a73f3 100644 --- a/client/components/admin/admin-search.vue +++ b/client/components/admin/admin-search.vue @@ -5,14 +5,14 @@ .admin-header img.animated.fadeInUp(src='/svg/icon-search.svg', alt='Search Engine', style='width: 80px;') .admin-header-title - .headline.primary--text.animated.fadeInLeft Search Engine - .subheading.grey--text.animated.fadeInLeft.wait-p2s Configure the search capabilities of your wiki + .headline.primary--text.animated.fadeInLeft {{$t('admin:search.title')}} + .subheading.grey--text.animated.fadeInLeft.wait-p2s {{$t('admin:search.subtitle')}} v-spacer v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large) v-icon refresh v-btn.animated.fadeInDown.wait-p1s(color='black', dark, large, depressed, @click='rebuild') v-icon(left) cached - span Rebuild Index + span {{$t('admin:search.rebuildIndex')}} v-btn.animated.fadeInDown(color='success', @click='save', depressed, large) v-icon(left) check span {{$t('common:actions.apply')}} @@ -20,7 +20,7 @@ v-flex(lg3, xs12) v-card.animated.fadeInUp v-toolbar(flat, color='primary', dark, dense) - .subheading Search Engine + .subheading {{$t('admin:search.searchEngine')}} v-list.py-0(two-line, dense) template(v-for='(eng, idx) in engines') v-list-tile(:key='eng.key', @click='selectedEngine = eng.key', :disabled='!eng.isAvailable') @@ -45,8 +45,8 @@ .caption.pt-3 {{engine.description}} .caption.pb-3: a(:href='engine.website') {{engine.website}} v-divider.mt-3 - v-subheader.pl-0 Engine Configuration - .body-1.ml-3(v-if='!engine.config || engine.config.length < 1') This engine has no configuration options you can modify. + v-subheader.pl-0 {{$t('admin:search.engineConfig')}} + .body-1.ml-3(v-if='!engine.config || engine.config.length < 1') {{$t('admin:search.engineNoConfig')}} template(v-else, v-for='cfg in engine.config') v-select( v-if='cfg.value.type === "string" && cfg.value.enum' @@ -112,7 +112,7 @@ export default { async refresh() { await this.$apollo.queries.engines.refetch() this.$store.commit('showNotification', { - message: 'List of search engines has been refreshed.', + message: this.$t('admin:search.listRefreshSuccess'), style: 'success', icon: 'cached' }) @@ -132,12 +132,12 @@ export default { }) if (_.get(resp, 'data.search.updateSearchEngines.responseResult.succeeded', false)) { this.$store.commit('showNotification', { - message: 'Search engine configuration saved successfully.', + message: this.$t('admin:search.configSaveSuccess'), style: 'success', icon: 'check' }) } else { - throw new Error(_.get(resp, 'data.search.updateSearchEngines.responseResult.message', 'An unexpected error occured')) + throw new Error(_.get(resp, 'data.search.updateSearchEngines.responseResult.message', this.$t('common:error.unexpected'))) } } catch (err) { this.$store.commit('pushGraphError', err) @@ -152,12 +152,12 @@ export default { }) if (_.get(resp, 'data.search.rebuildIndex.responseResult.succeeded', false)) { this.$store.commit('showNotification', { - message: 'Index rebuilt successfully.', + message: this.$t('admin:search.indexRebuildSuccess'), style: 'success', icon: 'check' }) } else { - throw new Error(_.get(resp, 'data.search.rebuildIndex.responseResult.message', 'An unexpected error occured')) + throw new Error(_.get(resp, 'data.search.rebuildIndex.responseResult.message', this.$t('common:error.unexpected'))) } } catch (err) { this.$store.commit('pushGraphError', err) diff --git a/client/components/admin/admin-storage.vue b/client/components/admin/admin-storage.vue index 92aa5d73..7fa2d98e 100644 --- a/client/components/admin/admin-storage.vue +++ b/client/components/admin/admin-storage.vue @@ -5,8 +5,8 @@ .admin-header img.animated.fadeInUp(src='/svg/icon-cloud-storage.svg', alt='Storage', style='width: 80px;') .admin-header-title - .headline.primary--text.animated.fadeInLeft Storage - .subheading.grey--text.animated.fadeInLeft.wait-p4s Set backup and sync targets for your content + .headline.primary--text.animated.fadeInLeft {{$t('admin:storage.title')}} + .subheading.grey--text.animated.fadeInLeft.wait-p4s {{$t('admin:storage.subtitle')}} v-spacer v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', @click='refresh', large) v-icon refresh @@ -17,7 +17,7 @@ v-flex(lg3, xs12) v-card.animated.fadeInUp v-toolbar(flat, color='primary', dark, dense) - .subheading Targets + .subheading {{$t('admin:storage.targets')}} v-list(two-line, dense).py-0 template(v-for='(tgt, idx) in targets') v-list-tile(:key='tgt.key', @click='selectedTarget = tgt.key', :disabled='!tgt.isAvailable') @@ -34,7 +34,7 @@ v-card.mt-3.animated.fadeInUp.wait-p2s v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-l5` : `grey darken-3`', dark, dense) - .subheading Status + .subheading {{$t('admin:storage.status')}} v-spacer looping-rhombuses-spinner( :animation-duration='5000' @@ -57,24 +57,24 @@ v-icon(color='white') check_circle v-list-tile-content v-list-tile-title.body-2 {{tgt.title}} - v-list-tile-sub-title.green--text.caption Last synchronization {{tgt.lastAttempt | moment('from') }} + v-list-tile-sub-title.green--text.caption {{$t('admin:storage.lastSync', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}} template(v-else) v-list-tile-avatar(color='red') v-icon(color='white') highlight_off v-list-tile-content v-list-tile-title.body-2 {{tgt.title}} - v-list-tile-sub-title.red--text.caption Last attempt was {{tgt.lastAttempt | moment('from') }} + v-list-tile-sub-title.red--text.caption {{$t('admin:storage.lastSyncAttempt', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}} v-list-tile-action v-menu v-btn(slot='activator', icon) v-icon(color='red') info v-card(width='450') - v-toolbar(flat, color='red', dark, dense) Error Message + v-toolbar(flat, color='red', dark, dense) {{$t('admin:storage.errorMsg')}} v-card-text {{tgt.message}} v-divider(v-if='n < status.length - 1') v-list-tile(v-if='status.length < 1') - em You don't have any active storage target. + em {{$t('admin:storage.noTarget')}} v-flex(xs12, lg9) v-card.wiki-form.animated.fadeInUp.wait-p2s @@ -88,8 +88,8 @@ .caption {{target.description}} .caption: a(:href='target.website') {{target.website}} v-divider.mt-3 - v-subheader.pl-0 Target Configuration - .body-1.ml-3(v-if='!target.config || target.config.length < 1') This storage target has no configuration options you can modify. + v-subheader.pl-0 {{$t('admin:storage.targetConfig')}} + .body-1.ml-3(v-if='!target.config || target.config.length < 1') {{$t('admin:storage.noConfigOption')}} template(v-else, v-for='cfg in target.config') v-select( v-if='cfg.value.type === "string" && cfg.value.enum' @@ -127,48 +127,50 @@ :class='cfg.value.hint ? "mb-2" : ""' ) v-divider.mt-3 - v-subheader.pl-0 Sync Direction - .body-1.ml-3 Choose how content synchronization is handled for this storage target. + v-subheader.pl-0 {{$t('admin:storage.syncDirection')}} + .body-1.ml-3 {{$t('admin:storage.syncDirectionSubtitle')}} .pr-3.pt-3 v-radio-group.ml-3.py-0(v-model='target.mode') v-radio( - label='Bi-directional' + :label='$t(`admin:storage.syncDirBi`)' color='primary' value='sync' :disabled='target.supportedModes.indexOf(`sync`) < 0' ) v-radio( - label='Push to target' + :label='$t(`admin:storage.syncDirPush`)' color='primary' value='push' :disabled='target.supportedModes.indexOf(`push`) < 0' ) v-radio( - label='Pull from target' + :label='$t(`admin:storage.syncDirPull`)' color='primary' value='pull' :disabled='target.supportedModes.indexOf(`pull`) < 0' ) .body-1.ml-3 - strong Bi-directional #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`sync`) < 0') Unsupported] - .pb-3 In bi-directional mode, content is first pulled from the storage target. Any newer content overwrites local content. New content since last sync is then pushed to the storage target, overwriting any content on target if present. - strong Push to target #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`push`) < 0') Unsupported] - .pb-3 Content is always pushed to the storage target, overwriting any existing content. This is safest choice for backup scenarios. - strong Pull from target #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`pull`) < 0') Unsupported] - .pb-3 Content is always pulled from the storage target, overwriting any local content which already exists. This choice is usually reserved for single-use content import. Caution with this option as any local content will always be overwritten! + strong {{$t('admin:storage.syncDirBi')}} #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`sync`) < 0') {{$t('admin:storage.unsupported')}}] + .pb-3 {{$t('admin:storage.syncDirBiHint')}} + strong {{$t('admin:storage.syncDirPush')}} #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`push`) < 0') {{$t('admin:storage.unsupported')}}] + .pb-3 {{$t('admin:storage.syncDirPushHint')}} + strong {{$t('admin:storage.syncDirPull')}} #[em.red--text.text--lighten-2(v-if='target.supportedModes.indexOf(`pull`) < 0') {{$t('admin:storage.unsupported')}}] + .pb-3 {{$t('admin:storage.syncDirPullHint')}} template(v-if='target.hasSchedule') v-divider.mt-3 - v-subheader.pl-0 Sync Schedule - .body-1.ml-3 For performance reasons, this storage target synchronize changes on an interval-based schedule, instead of on every change. Define at which interval should the synchronization occur. + v-subheader.pl-0 {{$t('admin:storage.syncSchedule')}} + .body-1.ml-3 {{$t('admin:storage.syncScheduleHint')}} .pa-3 duration-picker(v-model='target.syncInterval') - .caption.mt-3 Currently set to every #[strong {{getDefaultSchedule(target.syncInterval)}}]. - .caption The default is every #[strong {{getDefaultSchedule(target.syncIntervalDefault)}}]. + i18next.caption.mt-3(path='admin:storage.syncScheduleCurrent', tag='div') + strong(place='schedule') {{getDefaultSchedule(target.syncInterval)}} + i18next.caption(path='admin:storage.syncScheduleDefault', tag='div') + strong {{getDefaultSchedule(target.syncIntervalDefault)}} template(v-if='target.actions && target.actions.length > 0') v-divider.mt-3 - v-subheader.pl-0 Actions + v-subheader.pl-0 {{$t('admin:storage.actions')}} v-container.pt-0(grid-list-xl, fluid) v-layout(row, wrap, fill-height) v-flex(xs12, lg6, xl4, v-for='act of target.actions', :key='act.handler') @@ -182,7 +184,7 @@ :color='$vuetify.dark ? `blue` : `primary`' :disabled='runningAction' :loading='runningActionHandler === act.handler' - ) Run + ) {{$t('admin:storage.actionRun')}}