1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-10 22:11:50 +02:00

All: Add plural forms for notes, users, hours, minutes, days (#12171)

This commit is contained in:
Mihai Vasiliu
2025-04-29 15:54:09 +03:00
committed by GitHub
parent 27be923fe6
commit c785388c51
6 changed files with 19 additions and 18 deletions

View File

@@ -1,6 +1,6 @@
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import { _, _n } from '@joplin/lib/locale';
import Note from '@joplin/lib/models/Note';
import BaseModel, { DeleteOptions } from '@joplin/lib/BaseModel';
import { NoteEntity } from '@joplin/lib/services/database/types';
@@ -31,13 +31,13 @@ class Command extends BaseCommand {
let ok = true;
if (!force && notes.length > 1) {
ok = await this.prompt(_('%d notes match this pattern. Delete them?', notes.length), { booleanAnswerDefault: 'n' });
ok = await this.prompt(_n('%d note matches this pattern. Delete it?', '%d notes match this pattern. Delete them?', notes.length, notes.length), { booleanAnswerDefault: 'n' });
}
const permanent = (args.options?.permanent === true) || notes.every(n => !!n.deleted_time);
if (!force && permanent) {
const message = (
notes.length === 1 ? _('This will permanently delete the note "%s". Continue?', notes[0].title) : _('%d notes will be permanently deleted. Continue?', notes.length)
_n('%d note will be permanently deleted. Continue?', '%d notes will be permanently deleted. Continue?', notes.length, notes.length)
);
ok = await this.prompt(message, { booleanAnswerDefault: 'n' });
}

View File

@@ -564,7 +564,7 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
const folder = await Folder.load(folderId);
const ok = noteIds.length > 1 ? await shim.showConfirmationDialog(_('Move %d notes to notebook "%s"?', noteIds.length, folder.title)) : true;
const ok = noteIds.length > 1 ? await shim.showConfirmationDialog(_n('Move %d note to notebook "%s"?', 'Move %d notes to notebook "%s"?', noteIds.length, noteIds.length, folder.title)) : true;
if (!ok) return;
this.props.dispatch({ type: 'NOTE_SELECTION_END' });

View File

@@ -13,7 +13,7 @@ import Resource from './Resource';
import syncDebugLog from '../services/synchronizer/syncDebugLog';
import { toFileProtocolPath, toForwardSlashes } from '../path-utils';
const { pregQuote, substrWithEllipsis } = require('../string-utils.js');
const { _ } = require('../locale');
const { _, _n } = require('../locale');
import { pull, removeElement, unique } from '../ArrayUtils';
import { LoadOptions, SaveOptions } from './utils/types';
import ActionLogger from '../utils/ActionLogger';
@@ -941,7 +941,7 @@ export default class Note extends BaseItem {
if (!note) return null;
msg = _('Permanently delete note "%s"?', substrWithEllipsis(note.title, 0, 32));
} else {
msg = _('Permanently delete these %d notes?', noteIds.length);
msg = _n('Permanently delete this note?', 'Permanently delete these %d notes?', noteIds.length, noteIds.length);
}
return msg;
}

View File

@@ -1,6 +1,6 @@
import { rtrimSlashes } from '@joplin/utils/path';
import SyncTargetRegistry from '../../SyncTargetRegistry';
import { _, defaultLocale, supportedLocalesToLanguages } from '../../locale';
import { _, _n, defaultLocale, supportedLocalesToLanguages } from '../../locale';
import shim from '../../shim';
import time from '../../time';
import type SettingType from '../Setting';
@@ -1276,12 +1276,12 @@ const builtInMetadata = (Setting: typeof SettingType) => {
options: () => {
return {
0: _('Disabled'),
300: _('%d minutes', 5),
600: _('%d minutes', 10),
1800: _('%d minutes', 30),
3600: _('%d hour', 1),
43200: _('%d hours', 12),
86400: _('%d hours', 24),
300: _n('%d minute', '%d minutes', 5, 5),
600: _n('%d minute', '%d minutes', 10, 10),
1800: _n('%d minute', '%d minutes', 30, 30),
3600: _n('%d hour', '%d hours', 1, 1),
43200: _n('%d hour', '%d hours', 12, 12),
86400: _n('%d hour', '%d hours', 24, 24),
};
},
storage: SettingStorage.File,
@@ -1535,7 +1535,7 @@ const builtInMetadata = (Setting: typeof SettingType) => {
maximum: 365 * 2,
step: 1,
unitLabel: (value: number = null) => {
return value === null ? _('days') : _('%d days', value);
return value === null ? _('days') : _n('%d day', '%d days', value, value);
},
label: () => _('Keep note history for'),
storage: SettingStorage.File,
@@ -1811,7 +1811,7 @@ const builtInMetadata = (Setting: typeof SettingType) => {
maximum: 300,
step: 1,
unitLabel: (value: number = null) => {
return value === null ? _('days') : _('%d days', value);
return value === null ? _('days') : _n('%d day', '%d days', value, value);
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
show: (settings: any) => settings['trash.autoDeletionEnabled'],

View File

@@ -7,7 +7,7 @@ import BaseModel from '../BaseModel';
import DecryptionWorker from './DecryptionWorker';
import ResourceFetcher from './ResourceFetcher';
import Resource from '../models/Resource';
import { _ } from '../locale';
import { _, _n } from '../locale';
const { toTitleCase } = require('../string-utils.js');
enum CanRetryType {
@@ -374,7 +374,8 @@ export default class ReportService {
});
for (let i = 0; i < folders.length; i++) {
section.body.push(_('%s: %d notes', folders[i].title, await Folder.noteCount(folders[i].id)));
const noteCount = await Folder.noteCount(folders[i].id);
section.body.push(_n('%s: %d note', '%s: %d notes', noteCount, folders[i].title, noteCount));
}
sections.push(section);

View File

@@ -405,7 +405,7 @@ export function getPlans(stripeConfig: StripePublicConfig): Record<PlanName, Pla
featureLabelsOff: getFeatureLabelsByPlan(PlanName.Teams, false),
cfaLabel: _('Try it now'),
cfaUrl: '',
footnote: _('Per user. Minimum of %d users.', 2),
footnote: _('Per user. Minimum of 2 users.'),
},
};
}