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
43 changes: 31 additions & 12 deletions lighthouse-core/audits/deprecations.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,28 @@
*/

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the use of deprecated APIs. This descriptive title is shown to users when the page does not use deprecated APIs. */
title: 'Avoids deprecated APIs',
/** Title of a Lighthouse audit that provides detail on the use of deprecated APIs. This descriptive title is shown to users when the page uses deprecated APIs. */
failureTitle: 'Uses deprecated APIs',
/** Description of a Lighthouse audit that tells the user why they should not use deprecated APIs on their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
description: 'Deprecated APIs will eventually be removed from the browser. ' +
'[Learn more](https://www.chromestatus.com/features#deprecated).',
/** [ICU Syntax] Label for the audit identifying the number of warnings generated by using deprecated APIs. */
displayValue: `{itemCount, plural,
=1 {1 warning found}
other {# warnings found}
}`,
/** Header of the table column which displays the warning message describing use of a deprecated API by code running in the web page. */
columnDeprecate: 'Deprecation / Warning',
/** Table column header for line of code (eg. 432) that is using a deprecated API. */
columnLine: 'Line',
};

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

class Deprecations extends Audit {
/**
Expand All @@ -21,10 +42,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 All @@ -47,17 +67,15 @@ class Deprecations extends Audit {

/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
{key: 'value', itemType: 'code', text: 'Deprecation / Warning'},
{key: 'url', itemType: 'url', text: 'URL'},
{key: 'lineNumber', itemType: 'text', text: 'Line'},
{key: 'value', itemType: 'code', text: str_(UIStrings.columnDeprecate)},
{key: 'url', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
{key: 'lineNumber', itemType: 'text', text: str_(UIStrings.columnLine)},
];
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 +90,4 @@ class Deprecations extends Audit {
}

module.exports = Deprecations;
module.exports.UIStrings = UIStrings;
26 changes: 21 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,21 @@
'use strict';

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the use of the Application Cache API. This descriptive title is shown to users when they do not use the Application Cache API. */
title: 'Avoids Application Cache',
/** Title of a Lighthouse audit that provides detail on the use of the Application Cache API. This descriptive title is shown to users when they do use the Application Cache API, which is considered bad practice. */
failureTitle: 'Uses Application Cache',
/** Description of a Lighthouse audit that tells the user why they should not use the Application Cache API. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
description: 'Application Cache is deprecated. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).',
/** Label for the audit identifying uses of the Application Cache. */
displayValue: 'Found "{AppCacheManifest}"',
};

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

class AppCacheManifestAttr extends Audit {
/**
Expand All @@ -19,10 +34,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 +47,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 +58,4 @@ class AppCacheManifestAttr extends Audit {
}

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

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the doctype of a page. This descriptive title is shown to users when the pages's doctype is set to HTML. */
title: 'Page has the HTML doctype',
/** Title of a Lighthouse audit that provides detail on the doctype of a page. This descriptive title is shown to users when the page's doctype is not set to HTML. */
failureTitle: 'Page lacks the HTML doctype, thus triggering quirks-mode',
/** Description of a Lighthouse audit that tells the user why they should define an HTML doctype. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
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)',
/** Explanatory message stating that the document has no doctype. */
explanationNoDoctype: 'Document must contain a doctype',
/** Explanatory message stating that the publicId field is not empty. */
explanationPublicId: 'Expected publicId to be an empty string',
/** Explanatory message stating that the systemId field is not empty. */
explanationSystemId: 'Expected systemId to be an empty string',
/** Explanatory message stating that the doctype is set, but is not "html" and is therefore invalid. */
explanationBadDoctype: 'Doctype name must be the lowercase string `html`',
};

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

class Doctype extends Audit {
/**
Expand All @@ -14,11 +36,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 +51,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 +63,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 +84,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,27 @@

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the cross-origin links that the web page contains, and whether the links can be considered safe. This descriptive title is shown to users when all links are safe. */
title: 'Links to cross-origin destinations are safe',
/** Title of a Lighthouse audit that provides detail on the cross-origin links that the web page contains, and whether the links can be considered safe. This descriptive title is shown to users when not all links can be considered safe. */
failureTitle: 'Links to cross-origin destinations are unsafe',
/** Description of a Lighthouse audit that tells the user why and how they should secure cross-origin links. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
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 that some links' destinations cannot be determined and therefore the audit cannot evaluate the link's safety. */
warning: 'Unable to determine the destination for anchor ({anchorHTML}). ' +
'If not used as a hyperlink, consider removing target=_blank.',
/** Label for a column in a data table; entries will be the target attribute of a link. Each entry is either an empty string or a string like `_blank`. */
columnTarget: 'Target',
/** Label for a column in a data table; entries will be the values of the html "rel" attribute from link in a page. */
columnRel: 'Rel',
};

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

class ExternalAnchorsUseRelNoopenerAudit extends Audit {
/**
Expand All @@ -15,11 +36,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 +59,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 All @@ -59,9 +77,9 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit {

/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
{key: 'href', itemType: 'url', text: 'URL'},
{key: 'target', itemType: 'text', text: 'Target'},
{key: 'rel', itemType: 'text', text: 'Rel'},
{key: 'href', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
{key: 'target', itemType: 'text', text: str_(UIStrings.columnTarget)},
{key: 'rel', itemType: 'text', text: str_(UIStrings.columnRel)},
];

const details = Audit.makeTableDetails(headings, failingAnchors);
Expand All @@ -78,3 +96,4 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit {
}

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

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on geolocation permission requests while the page is loading. This descriptive title is shown to users when the page does not ask for geolocation permissions on load. */
title: 'Avoids requesting the geolocation permission on page load',
/** Title of a Lighthouse audit that provides detail on geolocation permissions requests. This descriptive title is shown to users when the page does ask for geolocation permissions on load. */
failureTitle: 'Requests the geolocation permission on page load',
/** Description of a Lighthouse audit that tells the user why they should not ask for geolocation permissions on load. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */
description: 'Users are mistrustful of or confused by sites that request their ' +
'location without context. Consider tying the request to a user action instead. ' +
'[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 +34,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 All @@ -39,8 +51,8 @@ class GeolocationOnStart extends ViolationAudit {

/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
{key: 'url', itemType: 'url', text: 'URL'},
{key: 'label', itemType: 'text', text: 'Location'},
{key: 'url', itemType: 'url', text: str_(i18n.UIStrings.columnURL)},
{key: 'label', itemType: 'text', text: str_(i18n.UIStrings.columnLocation)},
];
// TODO(bckenny): there should actually be a ts error here. results[0].stackTrace
// should violate the results type. Shouldn't be removed from details items regardless.
Expand All @@ -57,3 +69,4 @@ class GeolocationOnStart extends ViolationAudit {
}

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

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

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the Javascript libraries that are used on the page. */
title: 'Detected JavaScript libraries',
/** Description of a Lighthouse audit that tells the user what this audit is detecting. This is displayed after a user expands the section to see more. No character length limits. */
description: 'All front-end JavaScript libraries detected on the page.',
/** Label for a column in a data table; entries will be the names of the detected Javascript libraries. */
columnName: 'Name',
/** Label for a column in a data table; entries will be the version numbers of the detected Javascript libraries. */
columnVersion: 'Version',
};

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

class JsLibrariesAudit extends Audit {
/**
Expand All @@ -19,8 +33,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 All @@ -40,8 +54,8 @@ class JsLibrariesAudit extends Audit {

/** @type {LH.Audit.Details.Table['headings']} */
const headings = [
{key: 'name', itemType: 'text', text: 'Name'},
{key: 'version', itemType: 'text', text: 'Version'},
{key: 'name', itemType: 'text', text: str_(UIStrings.columnName)},
{key: 'version', itemType: 'text', text: str_(UIStrings.columnVersion)},
];
const details = Audit.makeTableDetails(headings, libDetails, {});

Expand All @@ -53,3 +67,4 @@ class JsLibrariesAudit extends Audit {
}

module.exports = JsLibrariesAudit;
module.exports.UIStrings = UIStrings;
Loading