Added number formatting to all pluralized counts

closes https://github.com/TryGhost/Ghost/issues/12110

- adds `{{gh-pluralize}}` helper that wraps the `{{pluralize}}` helper from `ember-inflector` but formats the number using our `{{format-number}}` helper
- updates all uses of `{{pluralize}}` to `{{gh-pluralize}}`
This commit is contained in:
Kevin Ansfield 2020-08-10 11:16:03 +01:00
parent fe1394ec59
commit 754f8483e9
11 changed files with 46 additions and 22 deletions

View File

@ -4,9 +4,9 @@
{{else if (or @post.isPublished @post.pastScheduledTime)}}
Published
{{#if (or (eq @post.email.status "submitting") (eq @post.email.status "submitting"))}}
and sending to {{pluralize @post.email.emailCount "member"}}
and sending to {{gh-pluralize @post.email.emailCount "member"}}
{{else if (eq @post.email.status "submitted")}}
and sent to {{pluralize @post.email.emailCount "member"}}
and sent to {{gh-pluralize @post.email.emailCount "member"}}
{{/if}}
{{else if @post.isScheduled}}
<time datetime="{{@post.publishedAtUTC}}" class="ml1 green f8" data-test-schedule-countdown>

View File

@ -14,7 +14,7 @@
</div>
<div class="flex flex-column justify-center">
<p class="ma0 pa0 midgrey">Post was sent by email to</p>
<p class="ma0 pa0 f5 lh-solid">{{pluralize this.post.email.emailCount "member"}}</p>
<p class="ma0 pa0 f5 lh-solid">{{gh-pluralize this.post.email.emailCount "member"}}</p>
</div>
</div>
<div class="pa5 pt3 pb3 f7 bb b--whitegrey">
@ -45,7 +45,7 @@
</div>
<div class="flex flex-column justify-center">
<p class="ma0 pa0 midgrey">Post failed to send to</p>
<p class="ma0 pa0 f5 lh-solid">{{pluralize this.post.email.emailCount "member"}}</p>
<p class="ma0 pa0 f5 lh-solid">{{gh-pluralize this.post.email.emailCount "member"}}</p>
</div>
</div>
<div class="pa5 pt3 pb3 f7 bb b--whitegrey">

View File

@ -1,6 +1,6 @@
import ModalComponent from 'ghost-admin/components/modal-base';
import {computed} from '@ember/object';
import {pluralize} from 'ember-inflector';
import {ghPluralize} from 'ghost-admin/helpers/gh-pluralize';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
@ -22,7 +22,7 @@ export default ModalComponent.extend({
return 'all members';
}
return pluralize(this.get('model.memberCount'), 'member');
return ghPluralize(this.get('model.memberCount'), 'member');
}),
confirmAndCheckError: task(function* () {

View File

@ -7,7 +7,7 @@
<div class="modal-body" data-test-state="delete-unconfirmed">
<p>
You're about to delete
<strong data-test-text="delete-count">{{pluralize this.model.memberCount "member"}}</strong>.
<strong data-test-text="delete-count">{{gh-pluralize this.model.memberCount "member"}}</strong>.
This is permanent! We warned you, k?
</p>
</div>
@ -26,7 +26,7 @@
<div class="flex items-center">
{{svg-jar "check-circle" class="w4 h4 stroke-green mr2"}}
<p class="ma0 pa0">
<span class="fw6" data-test-text="deleted-count">{{pluralize this.response.deleted.count "member"}}</span>
<span class="fw6" data-test-text="deleted-count">{{gh-pluralize this.response.deleted.count "member"}}</span>
deleted
</p>
</div>
@ -35,7 +35,7 @@
{{svg-jar "warning" class="w4 h4 fill-red mr2 nudge-top--3"}}
<div>
<p class="ma0 pa0">
<span class="fw5" data-test-text="invalid-count">{{pluralize this.response.invalid.count "member"}}</span>
<span class="fw5" data-test-text="invalid-count">{{gh-pluralize this.response.invalid.count "member"}}</span>
skipped
</p>
{{#each this.response.invalid.errors as |error|}}

View File

@ -6,7 +6,7 @@
<div class="modal-body">
{{#if this.user.count.posts}}
<p>
<strong>{{this.user.name}}</strong> and their <strong data-test-text="user-post-count">{{pluralize this.user.count.posts 'post'}}</strong> will be permanently deleted. If you dont want to lose these posts, you should assign them to a different author.
<strong>{{this.user.name}}</strong> and their <strong data-test-text="user-post-count">{{gh-pluralize this.user.count.posts 'post'}}</strong> will be permanently deleted. If you dont want to lose these posts, you should assign them to a different author.
</p>
<p>
A backup will be automatically downloaded to your device before deletion.

View File

@ -100,11 +100,11 @@
<div class="flex items-start">
<div class="w-50 gh-member-import-result-summary">
<h2>{{format-number this.importResponse.imported.count}}</h2>
<p>{{pluralize this.importResponse.imported.count "Member" without-count=true}} added</p>
<p>{{gh-pluralize this.importResponse.imported.count "Member" without-count=true}} added</p>
</div>
<div class="bl b--whitegrey w-50 gh-member-import-result-summary">
<h2>{{format-number this.importResponse.invalid.count}}</h2>
<p>{{pluralize this.importResponse.invalid.count "Error" without-count=true}}</p>
<p>{{gh-pluralize this.importResponse.invalid.count "Error" without-count=true}}</p>
</div>
</div>
</div>
@ -114,7 +114,7 @@
<div class="flex items-start">
{{svg-jar "warning" class="w5 h5 fill-red nudge-top--3 mr3"}}
<div class="flex-grow w-100">
<p class="ma0 pa0">{{format-number this.importResponse.invalid.count}} {{pluralize this.importResponse.invalid.count "member" without-count=true}} were skipped due to the following errors:</p>
<p class="ma0 pa0">{{format-number this.importResponse.invalid.count}} {{gh-pluralize this.importResponse.invalid.count "member" without-count=true}} were skipped due to the following errors:</p>
<ul class="ma0 pa0 mt4 list bt b--whitegrey">
{{#each this.importResponse.invalid.errors as |error|}}
<li class="gh-members-import-errormessage">{{error.message}} <span class="fw4">({{format-number error.count}})</span></li>
@ -169,7 +169,7 @@
<span>Start over</span>
</button>
<button class="gh-btn gh-btn-green" {{action "upload"}} disabled={{this.importDisabled}}>
<span>Import{{#if this.fileData.length}} {{format-number this.fileData.length}} {{pluralize this.fileData.length 'member' without-count=true}}{{/if}}</span>
<span>Import{{#if this.fileData.length}} {{format-number this.fileData.length}} {{gh-pluralize this.fileData.length 'member' without-count=true}}{{/if}}</span>
</button>
{{/if}}
{{else}}

View File

@ -3,8 +3,7 @@ import ghostPaths from 'ghost-admin/utils/ghost-paths';
import moment from 'moment';
import {A} from '@ember/array';
import {action} from '@ember/object';
import {formatNumber} from 'ghost-admin/helpers/format-number';
import {pluralize} from 'ember-inflector';
import {ghPluralize} from 'ghost-admin/helpers/pluralize';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {timeout} from 'ember-concurrency';
@ -67,7 +66,7 @@ export default class MembersController extends Controller {
return 'Search result';
}
let count = `${formatNumber(members.length)} ${pluralize(members.length, 'member', {withoutCount: true})}`;
let count = ghPluralize(members.length, 'member');
if (selectedLabel && selectedLabel.slug) {
if (members.length > 1) {

View File

@ -0,0 +1,26 @@
import {formatNumber} from './format-number';
import {helper} from '@ember/component/helper';
import {isBlank} from '@ember/utils';
import {pluralize} from 'ember-inflector';
export function ghPluralize(number, word, {'without-count': withoutCount} = {}) {
let output = [];
if (!isBlank(number) && withoutCount !== true) {
output.push(formatNumber(number));
}
// default {{pluralize}} allows for {{pluralize "word"}} with no number
if (isBlank(number)) {
output.push(pluralize(word, {withoutCount: true}));
} else {
output.push(pluralize(number, word, {withoutCount: true}));
}
return output.join(' ');
}
// like {{pluralize}} but formats the number according to current locale
export default helper(function ([number, word], {'without-count': withoutCount} = {}) {
return ghPluralize(number, word, {'without-count': withoutCount});
});

View File

@ -1,9 +1,8 @@
import MemberImportError from 'ghost-admin/errors/member-import-error';
import Service, {inject as service} from '@ember/service';
import validator from 'validator';
import {formatNumber} from 'ghost-admin/helpers/format-number';
import {ghPluralize} from 'ghost-admin/helpers/gh-pluralize';
import {isEmpty} from '@ember/utils';
import {pluralize} from 'ember-inflector';
export default Service.extend({
ajax: service(),
@ -34,7 +33,7 @@ export default Service.extend({
if (!this.membersUtils.isStripeEnabled) {
validationErrors.push(new MemberImportError({
message: `Missing Stripe connection`,
context: `${formatNumber(totalCount)} ${pluralize(totalCount, 'Stripe customer', {withoutCount: true})} won't be imported. You need to <a href="#/settings/labs">connect to Stripe</a> to import Stripe customers.`,
context: `${ghPluralize(totalCount, 'Stripe customer')} won't be imported. You need to <a href="#/settings/labs">connect to Stripe</a> to import Stripe customers.`,
type: 'warning'
}));
} else {

View File

@ -85,7 +85,7 @@
<div class="absolute flex items-center br3 bg-white {{if editor.headerClass "right-4 bottom-4" "right-6 bottom-6"}}">
<div class="midgrey-l2 {{if editor.headerClass "f-supersmall pl2 pr2" "f8 pl4 pr3"}} fw4">
{{pluralize this.wordCount.wordCount "word"}}
{{gh-pluralize this.wordCount.wordCount "word"}}
</div>
<a href="https://ghost.org/faq/using-the-editor/" class="flex {{if editor.headerClass "pa2" "pa3"}}" target="_blank">{{svg-jar "help" class="w4 h4 stroke-midgrey-l2"}}</a>
</div>

View File

@ -78,7 +78,7 @@
</button>
{{else}}
<h3>Uploading {{pluralize upload.files.length "image"}}...</h3>
<h3>Uploading {{gh-pluralize upload.files.length "image"}}...</h3>
{{upload.progressBar}}
{{/if}}
</div>