Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n: localize audits in best-practices #9092

Merged
merged 14 commits into from
Jun 25, 2019
29 changes: 20 additions & 9 deletions lighthouse-core/audits/deprecations.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,20 @@
*/

const Audit = require('./audit.js');
const Util = require('../report/html/renderer/util.js');
const i18n = require('../lib/i18n/i18n.js');

const UIStrings = {
title: 'Avoids deprecated APIs',
failureTitle: 'Uses deprecated APIs',
description: 'Deprecated APIs will eventually be removed from the browser. ' +
'[Learn more](https://www.chromestatus.com/features#deprecated).',
displayValue: `{itemCount, plural,
=1 {1 warning found}
other {# warnings found}
}`,
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class Deprecations extends Audit {
/**
Expand All @@ -21,10 +34,9 @@ class Deprecations extends Audit {
static get meta() {
return {
id: 'deprecations',
title: 'Avoids deprecated APIs',
failureTitle: 'Uses deprecated APIs',
description: 'Deprecated APIs will eventually be removed from the browser. ' +
'[Learn more](https://www.chromestatus.com/features#deprecated).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['ConsoleMessages'],
};
}
Expand Down Expand Up @@ -54,10 +66,8 @@ class Deprecations extends Audit {
const details = Audit.makeTableDetails(headings, deprecations);

let displayValue = '';
if (deprecations.length > 1) {
displayValue = `${Util.formatNumber(deprecations.length)} warnings found`;
} else if (deprecations.length === 1) {
displayValue = `${deprecations.length} warning found`;
if (deprecations.length > 0) {
displayValue = str_(UIStrings.displayValue, {itemCount: deprecations.length});
}

return {
Expand All @@ -72,3 +82,4 @@ class Deprecations extends Audit {
}

module.exports = Deprecations;
module.exports.UIStrings = UIStrings;
22 changes: 17 additions & 5 deletions lighthouse-core/audits/dobetterweb/appcache-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
'use strict';

const Audit = require('../audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Avoids Application Cache',
failureTitle: 'Uses Application Cache',
description: 'Application Cache is deprecated. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).',
displayValue: 'Found "{AppCacheManifest}"',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class AppCacheManifestAttr extends Audit {
/**
Expand All @@ -19,10 +30,9 @@ class AppCacheManifestAttr extends Audit {
static get meta() {
return {
id: 'appcache-manifest',
title: 'Avoids Application Cache',
failureTitle: 'Uses Application Cache',
description: 'Application Cache is deprecated. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['AppCacheManifest'],
};
}
Expand All @@ -33,7 +43,8 @@ class AppCacheManifestAttr extends Audit {
*/
static audit(artifacts) {
const usingAppcache = artifacts.AppCacheManifest !== null;
const displayValue = usingAppcache ? `Found "${artifacts.AppCacheManifest}"` : '';
const displayValue = usingAppcache ?
str_(UIStrings.displayValue, {AppCacheManifest: artifacts.AppCacheManifest}) : '';

return {
score: usingAppcache ? 0 : 1,
Expand All @@ -43,3 +54,4 @@ class AppCacheManifestAttr extends Audit {
}

module.exports = AppCacheManifestAttr;
module.exports.UIStrings = UIStrings;
32 changes: 23 additions & 9 deletions lighthouse-core/audits/dobetterweb/doctype.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
'use strict';

const Audit = require('../audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Page has the HTML doctype',
failureTitle: 'Page is missing the HTML doctype',
exterkamp marked this conversation as resolved.
Show resolved Hide resolved
description: 'Specifying a doctype prevents the browser ' +
'from switching to quirks-mode. Read more on the ' +
'[MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)',
explanationNoDoctype: 'Document must contain a doctype',
explanationPublicId: 'Expected publicId to be an empty string',
explanationSystemId: 'Expected systemId to be an empty string',
explanationBadDoctype: 'Doctype name must be the lowercase string `html`',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class Doctype extends Audit {
/**
Expand All @@ -14,11 +29,9 @@ class Doctype extends Audit {
static get meta() {
return {
id: 'doctype',
title: 'Page has the HTML doctype',
failureTitle: 'Page is missing the HTML doctype',
description: 'Specifying a doctype prevents the browser from switching to quirks-mode.' +
'Read more on the ' +
'[MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['Doctype'],
};
}
Expand All @@ -31,7 +44,7 @@ class Doctype extends Audit {
if (!artifacts.Doctype) {
return {
score: 0,
explanation: 'Document must contain a doctype',
explanation: str_(UIStrings.explanationNoDoctype),
};
}

Expand All @@ -43,14 +56,14 @@ class Doctype extends Audit {
if (doctypePublicId !== '') {
return {
score: 0,
explanation: 'Expected publicId to be an empty string',
explanation: str_(UIStrings.explanationPublicId),
};
}

if (doctypeSystemId !== '') {
return {
score: 0,
explanation: 'Expected systemId to be an empty string',
explanation: str_(UIStrings.explanationSystemId),
};
}

Expand All @@ -64,10 +77,11 @@ class Doctype extends Audit {
} else {
return {
score: 0,
explanation: 'Doctype name must be the lowercase string `html`',
explanation: str_(UIStrings.explanationBadDoctype),
};
}
}
}

module.exports = Doctype;
module.exports.UIStrings = UIStrings;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@

const URL = require('../../lib/url-shim.js');
const Audit = require('../audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Links to cross-origin destinations are safe',
failureTitle: 'Links to cross-origin destinations are unsafe',
description: 'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve ' +
'performance and prevent security vulnerabilities. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).',
warning: 'Unable to determine the destination for anchor ({anchorHTML}). ' +
'If not used as a hyperlink, consider removing target=_blank.',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class ExternalAnchorsUseRelNoopenerAudit extends Audit {
/**
Expand All @@ -15,11 +28,9 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit {
static get meta() {
return {
id: 'external-anchors-use-rel-noopener',
title: 'Links to cross-origin destinations are safe',
failureTitle: 'Links to cross-origin destinations are unsafe',
description: 'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve ' +
'performance and prevent security vulnerabilities. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['URL', 'AnchorElements'],
};
}
Expand All @@ -40,8 +51,7 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit {
try {
return new URL(anchor.href).host !== pageHost;
} catch (err) {
warnings.push(`Unable to determine the destination for anchor (${anchor.outerHTML}). ` +
'If not used as a hyperlink, consider removing target=_blank.');
warnings.push(str_(UIStrings.warning, {anchorHTML: anchor.outerHTML}));
return true;
}
})
Expand Down Expand Up @@ -78,3 +88,4 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit {
}

module.exports = ExternalAnchorsUseRelNoopenerAudit;
module.exports.UIStrings = UIStrings;
20 changes: 15 additions & 5 deletions lighthouse-core/audits/dobetterweb/geolocation-on-start.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
'use strict';

const ViolationAudit = require('../violation-audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Avoids requesting the geolocation permission on page load',
failureTitle: 'Requests the geolocation permission on page load',
description: 'Users are mistrustful of or confused by sites that request their ' +
'location without context. Consider tying the request to user gestures instead. ' +
exterkamp marked this conversation as resolved.
Show resolved Hide resolved
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class GeolocationOnStart extends ViolationAudit {
/**
Expand All @@ -20,11 +31,9 @@ class GeolocationOnStart extends ViolationAudit {
static get meta() {
return {
id: 'geolocation-on-start',
title: 'Avoids requesting the geolocation permission on page load',
failureTitle: 'Requests the geolocation permission on page load',
description: 'Users are mistrustful of or confused by sites that request their ' +
'location without context. Consider tying the request to user gestures instead. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['ConsoleMessages'],
};
}
Expand Down Expand Up @@ -57,3 +66,4 @@ class GeolocationOnStart extends ViolationAudit {
}

module.exports = GeolocationOnStart;
module.exports.UIStrings = UIStrings;
13 changes: 11 additions & 2 deletions lighthouse-core/audits/dobetterweb/js-libraries.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
'use strict';

const Audit = require('../audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Detected JavaScript libraries',
description: 'All front-end JavaScript libraries detected on the page.',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class JsLibrariesAudit extends Audit {
/**
Expand All @@ -19,8 +27,8 @@ class JsLibrariesAudit extends Audit {
static get meta() {
return {
id: 'js-libraries',
title: 'Detected JavaScript libraries',
description: 'All front-end JavaScript libraries detected on the page.',
title: str_(UIStrings.title),
description: str_(UIStrings.description),
requiredArtifacts: ['Stacks'],
};
}
Expand Down Expand Up @@ -53,3 +61,4 @@ class JsLibrariesAudit extends Audit {
}

module.exports = JsLibrariesAudit;
module.exports.UIStrings = UIStrings;
20 changes: 15 additions & 5 deletions lighthouse-core/audits/dobetterweb/no-document-write.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
'use strict';

const ViolationAudit = require('../violation-audit.js');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Avoids `document.write()`',
failureTitle: 'Uses `document.write()`',
description: 'For users on slow connections, external scripts dynamically injected via ' +
'`document.write()` can delay page load by tens of seconds. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

class NoDocWriteAudit extends ViolationAudit {
/**
Expand All @@ -19,11 +30,9 @@ class NoDocWriteAudit extends ViolationAudit {
static get meta() {
return {
id: 'no-document-write',
title: 'Avoids `document.write()`',
failureTitle: 'Uses `document.write()`',
description: 'For users on slow connections, external scripts dynamically injected via ' +
'`document.write()` can delay page load by tens of seconds. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['ConsoleMessages'],
};
}
Expand Down Expand Up @@ -54,3 +63,4 @@ class NoDocWriteAudit extends ViolationAudit {
}

module.exports = NoDocWriteAudit;
module.exports.UIStrings = UIStrings;
34 changes: 23 additions & 11 deletions lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ const Audit = require('../audit.js');
const Sentry = require('../../lib/sentry.js');
const semver = require('semver');
const snykDatabase = require('../../../third-party/snyk/snapshot.json');
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
title: 'Avoids front-end JavaScript libraries' +
' with known security vulnerabilities',
failureTitle: 'Includes front-end JavaScript libraries' +
' with known security vulnerabilities',
description: 'Some third-party scripts may contain known security vulnerabilities ' +
'that are easily identified and exploited by attackers. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).',
displayValue: `{itemCount, plural,
=1 {1 vulnerability detected}
other {# vulnerabilities detected}
}`,
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);

const SEMVER_REGEX = /^(\d+\.\d+\.\d+)[^-0-9]+/;

Expand All @@ -29,13 +46,9 @@ class NoVulnerableLibrariesAudit extends Audit {
static get meta() {
return {
id: 'no-vulnerable-libraries',
title: 'Avoids front-end JavaScript libraries'
+ ' with known security vulnerabilities',
failureTitle: 'Includes front-end JavaScript libraries'
+ ' with known security vulnerabilities',
description: 'Some third-party scripts may contain known security vulnerabilities ' +
'that are easily identified and exploited by attackers. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['Stacks'],
};
}
Expand Down Expand Up @@ -179,10 +192,8 @@ class NoVulnerableLibrariesAudit extends Audit {
});

let displayValue = '';
if (totalVulns > 1) {
displayValue = `${totalVulns} vulnerabilities detected`;
} else if (totalVulns === 1) {
displayValue = `${totalVulns} vulnerability detected`;
if (totalVulns > 0) {
displayValue = str_(UIStrings.displayValue, {itemCount: totalVulns});
}

/** @type {LH.Audit.Details.Table['headings']} */
Expand All @@ -206,3 +217,4 @@ class NoVulnerableLibrariesAudit extends Audit {
}

module.exports = NoVulnerableLibrariesAudit;
module.exports.UIStrings = UIStrings;
Loading