diff --git a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js index a7b187a0a36bac0edc33fcfb371ee968d46af5c1..63e20478e9494f286abe2c4799cc7a09e32287ba 100644 --- a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js +++ b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.js @@ -11,7 +11,7 @@ export default { aria-hidden="true" title="Limited to showing 50 events at most" data-placement="top"></i> - {{ 'Showing 50 events' | translate }} + {{ 'Showing %d event' | translate-plural('Showing %d events', 50) }} </span> `, }; diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.js b/app/assets/javascripts/cycle_analytics/components/total_time_component.js index e07963b1b45c60eb335afa26dee29c78f38f61c6..a0d735f159ce01ded646fcc88e0062aa5aa3be54 100644 --- a/app/assets/javascripts/cycle_analytics/components/total_time_component.js +++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.js @@ -12,9 +12,9 @@ global.cycleAnalytics.TotalTimeComponent = Vue.extend({ template: ` <span class="total-time"> <template v-if="Object.keys(time).length"> - <template v-if="time.days">{{ time.days }} <span>{{ time.days === 1 ? 'day' : 'days' | translate }}</span></template> + <template v-if="time.days">{{ time.days }} <span>{{ 'day' | translate-plural('days', time.days) }}</span></template> <template v-if="time.hours">{{ time.hours }} <span v-translate>hr</span></template> - <template v-if="time.mins && !time.days">{{ time.mins }} <span v-translate>mins</span></template> + <template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ 'min' | translate-plural('mins', time.mins) }}</span></template> <template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>s</span></template> </template> <template v-else> diff --git a/app/assets/javascripts/vue_shared/translate.js b/app/assets/javascripts/vue_shared/translate.js index 88b7c0bb95436d9a40cf2172f3f7b358af10157e..072828b310ece4f132a1206e7d452b5501960ba8 100644 --- a/app/assets/javascripts/vue_shared/translate.js +++ b/app/assets/javascripts/vue_shared/translate.js @@ -3,6 +3,9 @@ import locale from '../locale'; export default (Vue) => { Vue.filter('translate', text => locale.gettext(text)); + Vue.filter('translate-plural', (text, pluralText, count) => + locale.ngettext(text, pluralText, count).replace(/%d/g, count)); + Vue.directive('translate', { bind(el) { const $el = el; diff --git a/spec/javascripts/vue_shared/translate_spec.js b/spec/javascripts/vue_shared/translate_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..74bd4ff86b1bb9f364d4a92b3a0b72ade7910f74 --- /dev/null +++ b/spec/javascripts/vue_shared/translate_spec.js @@ -0,0 +1,90 @@ +import Vue from 'vue'; +import Translate from '~/vue_shared/translate'; + +Vue.use(Translate); + +describe('Vue translate filter', () => { + let el; + + beforeEach(() => { + el = document.createElement('div'); + + document.body.appendChild(el); + }); + + it('translate single text', (done) => { + const comp = new Vue({ + el, + template: ` + <span> + {{ 'testing' | translate }} + </span> + `, + }).$mount(); + + Vue.nextTick(() => { + expect( + comp.$el.textContent.trim(), + ).toBe('testing'); + + done(); + }); + }); + + it('translate plural text with single count', (done) => { + const comp = new Vue({ + el, + template: ` + <span> + {{ '%d day' | translate-plural('%d days', 1) }} + </span> + `, + }).$mount(); + + Vue.nextTick(() => { + expect( + comp.$el.textContent.trim(), + ).toBe('1 day'); + + done(); + }); + }); + + it('translate plural text with multiple count', (done) => { + const comp = new Vue({ + el, + template: ` + <span> + {{ '%d day' | translate-plural('%d days', 2) }} + </span> + `, + }).$mount(); + + Vue.nextTick(() => { + expect( + comp.$el.textContent.trim(), + ).toBe('2 days'); + + done(); + }); + }); + + it('translate plural without replacing any text', (done) => { + const comp = new Vue({ + el, + template: ` + <span> + {{ 'day' | translate-plural('days', 2) }} + </span> + `, + }).$mount(); + + Vue.nextTick(() => { + expect( + comp.$el.textContent.trim(), + ).toBe('days'); + + done(); + }); + }); +});