Skip to content

Commit 4b925eb

Browse files
committed
Attach each translator note to its own string, and test that the update steps are translated when asked for
The notes for the dirty-tree answers' details reached their labels too, and the notes for the dirty-tree errors reached the "Unknown error" fallback on the same line. A unit test now loads a catalog after update-plan.cjs is required, so a message turned back into a constant fails it.
1 parent 1790e42 commit 4b925eb

5 files changed

Lines changed: 56 additions & 13 deletions

File tree

‎src/renderer/components/dirty-tree-modal.jsx‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,19 @@ export function DirtyTreeModal({ files, saving, error, onSave, onDiscard, onClos
4444
) : null}
4545
{[
4646
// Each detail carries its own dash: punctuation is the translator's.
47-
// translators: Said after "Save them as a patch first (as a local file)", on the same line.
48-
{ key: 'save', label: __('Save them as a patch first (as a local file)'), detail: __('— a .diff on your machine — nothing is sent to Trac') },
49-
// translators: Said after "Discard them", on the same line.
50-
{ key: 'discard', label: __('Discard them'), detail: __('— your changes are lost; this cannot be undone'), destructive: true }
47+
{
48+
key: 'save',
49+
label: __('Save them as a patch first (as a local file)'),
50+
// translators: Said after "Save them as a patch first (as a local file)", on the same line.
51+
detail: __('— a .diff on your machine — nothing is sent to Trac')
52+
},
53+
{
54+
key: 'discard',
55+
label: __('Discard them'),
56+
// translators: Said after "Discard them", on the same line.
57+
detail: __('— your changes are lost; this cannot be undone'),
58+
destructive: true
59+
}
5160
].map((opt) => {
5261
const selected = dirtyChoice === opt.key;
5362
return (

‎src/renderer/hooks/use-trunk-update.jsx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,16 @@ export function useTrunkUpdate({ sitePath, confirm, confirmAnd, installing, buil
255255
const res = await window.api.savePatch(sitePath);
256256
if (res && res.canceled) return; // stay in the modal
257257
if (!res || !res.ok || !res.filePath) {
258+
const why = res && res.error ? res.error : __('Unknown error');
258259
// translators: %s: why the diff could not be saved.
259-
setDirtyError(sprintf(__('Error saving diff: %s'), res && res.error ? res.error : __('Unknown error')));
260+
setDirtyError(sprintf(__('Error saving diff: %s'), why));
260261
return;
261262
}
262263
const d = await window.api.discardChanges(sitePath);
263264
if (!d || !d.ok) {
265+
const why = d && d.error ? d.error : __('Unknown error');
264266
// translators: 1: the path of the saved patch file. 2: why the reset failed.
265-
setDirtyError(sprintf(__('Saved your changes to %1$s, but resetting the working tree failed: %2$s'), res.filePath, d && d.error ? d.error : __('Unknown error')));
267+
setDirtyError(sprintf(__('Saved your changes to %1$s, but resetting the working tree failed: %2$s'), res.filePath, why));
266268
return;
267269
}
268270
savedPatchPathRef.current = res.filePath;
@@ -282,8 +284,9 @@ export function useTrunkUpdate({ sitePath, confirm, confirmAnd, installing, buil
282284
setDirtyError(null);
283285
const d = await window.api.discardChanges(sitePath);
284286
if (!d || !d.ok) {
287+
const why = d && d.error ? d.error : __('Unknown error');
285288
// translators: %s: why the changes could not be discarded.
286-
setDirtyError(sprintf(__('Failed to discard changes: %s'), d && d.error ? d.error : __('Unknown error')));
289+
setDirtyError(sprintf(__('Failed to discard changes: %s'), why));
287290
return;
288291
}
289292
applyDiscardToNote(discardOutcome(d));

‎src/renderer/update-plan.cjs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,16 @@ function setupOutcome({ stopped, installCode, buildCode } = {}) {
368368
*
369369
* @param {Object} summary
370370
* @param {boolean} summary.lockfileChanged Whether package-lock.json changed.
371-
* @param {?string} [summary.elapsed] The rebuild's time, already formatted (such as 2m 5s), or null.
371+
* @param {?string} [summary.elapsed] The rebuild's time, already formatted (such as 2m 05s), or null.
372372
* @return {string}
373373
*/
374374
function updateSummarySentence({ lockfileChanged, elapsed = null }) {
375375
if (elapsed && lockfileChanged) {
376-
// translators: %s: how long the rebuild took, such as 2m 5s.
376+
// translators: %s: how long the rebuild took, such as 2m 05s.
377377
return sprintf(__('Dependencies updated, rebuilt in %s.'), elapsed);
378378
}
379379
if (elapsed) {
380-
// translators: %s: how long the rebuild took, such as 2m 5s.
380+
// translators: %s: how long the rebuild took, such as 2m 05s.
381381
return sprintf(__('Dependencies unchanged, rebuilt in %s.'), elapsed);
382382
}
383383
return lockfileChanged ? __('Dependencies updated, rebuilt.') : __('Dependencies unchanged, rebuilt.');

‎src/work-item.cjs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
* had to change to gain the other.
1313
*
1414
* The split with project-type.cjs: the registry holds what is true of one
15-
* target (`workItem.label`, which the next step's sentence and the refusal
16-
* to open a pull request with none linked name it by, and `browseUrl`, where
15+
* target (`workItem.label`, which the refusal to open a pull request with
16+
* none linked names it by, and `browseUrl`, where
1717
* a newcomer finds one), this module holds what is true of
1818
* one kind of work item (how to parse a reference, where it lives, whether it
1919
* takes attachments). A second Trac-based target would reuse this provider

‎tests/unit/update-plan.test.cjs‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const {
1212
planUpdateSteps,
1313
updateStepText,
1414
planSetupSteps,
15+
planApplySteps,
1516
updateStepStatuses,
1617
setupOutcome,
1718
updateOutcome
@@ -239,8 +240,38 @@ test('setupOutcome: Stop is not a failure, whatever exit code the kill produced
239240
});
240241

241242
test('updateSummarySentence: one whole sentence for each outcome, not one built from parts', () => {
242-
assert.strictEqual(updateSummarySentence({ lockfileChanged: true, elapsed: '2m 5s' }), 'Dependencies updated, rebuilt in 2m 5s.');
243+
assert.strictEqual(updateSummarySentence({ lockfileChanged: true, elapsed: '2m 05s' }), 'Dependencies updated, rebuilt in 2m 05s.');
243244
assert.strictEqual(updateSummarySentence({ lockfileChanged: false, elapsed: '40s' }), 'Dependencies unchanged, rebuilt in 40s.');
244245
assert.strictEqual(updateSummarySentence({ lockfileChanged: true }), 'Dependencies updated, rebuilt.');
245246
assert.strictEqual(updateSummarySentence({ lockfileChanged: false, elapsed: null }), 'Dependencies unchanged, rebuilt.');
246247
});
248+
249+
// Translated when they are said, not once in English when the module loads:
250+
// the catalog is set after the require above, as the renderer's is.
251+
test('the steps and messages go through the translator when they are asked for', (t) => {
252+
const i18n = require('@wordpress/i18n');
253+
t.after(() => i18n.resetLocaleData());
254+
i18n.setLocaleData({
255+
'Fetch latest trunk': ['T fetch'],
256+
'Dependencies unchanged — skipping %s': ['T skipping %s'],
257+
'The build watch is rebuilding — output in the Logs, under Build watch': ['T watch rebuilding'],
258+
'The build watch will recompile the change': ['T watch recompiles'],
259+
'The build watch rebuilds when it resumes': ['T watch resumes'],
260+
'Apply the patch': ['T apply'],
261+
'Download WordPress': ['T download'],
262+
'Fetching and resetting to trunk…': ['T fetching'],
263+
'Dependencies unchanged, rebuilt.': ['T unchanged']
264+
});
265+
const update = planUpdateSteps({ lockfileChanged: false, buildByWatcher: 'resumed-watch' });
266+
assert.strictEqual(update[0].label, 'T fetch');
267+
assert.strictEqual(update[1].skipMessage, 'T skipping npm install');
268+
assert.strictEqual(update[2].currentMessage, 'T watch rebuilding');
269+
assert.strictEqual(updateStepText(update, { key: 'fetch', status: 'current' }), 'T fetching');
270+
assert.strictEqual(updateStepText(update, { key: 'install', status: 'skipped' }), 'T skipping npm install');
271+
const apply = planApplySteps({ buildByWatcher: 'live-watch' });
272+
assert.strictEqual(apply[0].label, 'T apply');
273+
assert.strictEqual(apply[2].skipMessage, 'T watch recompiles');
274+
assert.strictEqual(planApplySteps({ buildByWatcher: 'resumed-watch' })[2].skipMessage, 'T watch resumes');
275+
assert.strictEqual(planSetupSteps()[0].label, 'T download');
276+
assert.strictEqual(updateSummarySentence({ lockfileChanged: false }), 'T unchanged');
277+
});

0 commit comments

Comments
 (0)