Skip to content

Commit

Permalink
i18n: seo strings prepped for i18n (#6860)
Browse files Browse the repository at this point in the history
  • Loading branch information
exterkamp authored and paulirish committed Feb 14, 2019
1 parent e6dbefa commit 4290080
Show file tree
Hide file tree
Showing 18 changed files with 483 additions and 81 deletions.
2 changes: 1 addition & 1 deletion lighthouse-cli/test/smokehouse/seo/expectations.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ module.exports = [
'font-size': {
rawValue: false,
explanation:
'Text is illegible because there\'s no viewport meta tag optimized for mobile screens',
'Text is illegible because there\'s no viewport meta tag optimized for mobile screens.',
},
'link-text': {
score: 0,
Expand Down
46 changes: 36 additions & 10 deletions lighthouse-core/audits/seo/canonical.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,32 @@ const LinkHeader = require('http-link-header');
const URL = require('../../lib/url-shim');
const MainResource = require('../../computed/main-resource.js');
const LINK_HEADER = 'link';
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on a page's rel=canonical link. This descriptive title is shown to users when the rel=canonical link is valid. "rel=canonical" is an HTML attribute and value and so should not be translated. */
title: 'Document has a valid `rel=canonical`',
/** Title of a Lighthouse audit that provides detail on a page's rel=canonical link. This descriptive title is shown to users when the rel=canonical link is invalid and should be fixed. "rel=canonical" is an HTML attribute and value and so should not be translated. */
failureTitle: 'Document does not have a valid `rel=canonical`',
/** Description of a Lighthouse audit that tells the user *why* they need to have a valid rel=canonical link. 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: 'Canonical links suggest which URL to show in search results. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).',
/** [ICU Syntax] Explanatory message stating that there was a failure in an audit caused by multiple URLs conflicting with each other. "urlList" will be replaced by a list of URLs (e.g. https://example.com, https://example2.com, etc ). */
explanationConflict: 'Multiple conflicting URLs ({urlList})',
/** [ICU Syntax] Explanatory message stating that there was a failure in an audit caused by a URL being invalid. "url" will be replaced by the invalid URL (e.g. https://example.com). */
explanationInvalid: 'Invalid URL ({url})',
/** [ICU Syntax] Explanatory message stating that there was a failure in an audit caused by a URL being relative instead of absolute. "url" will be replaced by the invalid URL (e.g. https://example.com). */
explanationRelative: 'Relative URL ({url})',
/** [ICU Syntax] Explanatory message stating that there was a failure in an audit caused by a URL pointing to a different hreflang than the current context. "url" will be replaced by the invalid URL (e.g. https://example.com). 'hreflang' is an HTML attribute and should not be translated. */
explanationPointsElsewhere: 'Points to another `hreflang` location ({url})',
/** [ICU Syntax] Explanatory message stating that there was a failure in an audit caused by a URL pointing to a different domain. "url" will be replaced by the invalid URL (e.g. https://example.com). */
explanationDifferentDomain: 'Points to a different domain ({url})',
/** Explanatory message stating that the page's canonical URL was pointing to the domain's root URL, which is a common mistake. "points" refers to the action of the 'rel=canonical' referencing another link. "root" refers to the starting/home page of the website. "domain" refers to the registered domain name of the website. */
explanationRoot: 'Points to the domain\'s root URL (the homepage), ' +
'instead of an equivalent page of content',
};

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

/**
* @param {string} headerValue
Expand Down Expand Up @@ -62,10 +88,9 @@ class Canonical extends Audit {
static get meta() {
return {
id: 'canonical',
title: 'Document has a valid `rel=canonical`',
failureTitle: 'Document does not have a valid `rel=canonical`',
description: 'Canonical links suggest which URL to show in search results. ' +
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['Canonical', 'Hreflang', 'URL'],
};
}
Expand Down Expand Up @@ -118,7 +143,7 @@ class Canonical extends Audit {
if (canonicals.length > 1) {
return {
rawValue: false,
explanation: `Multiple conflicting URLs (${canonicals.join(', ')})`,
explanation: str_(UIStrings.explanationConflict, {urlList: canonicals.join(', ')}),
};
}

Expand All @@ -127,14 +152,14 @@ class Canonical extends Audit {
if (!isValidRelativeOrAbsoluteURL(canonical)) {
return {
rawValue: false,
explanation: `Invalid URL (${canonical})`,
explanation: str_(UIStrings.explanationInvalid, {url: canonical}),
};
}

if (!URL.isValid(canonical)) {
return {
rawValue: false,
explanation: `Relative URL (${canonical})`,
explanation: str_(UIStrings.explanationRelative, {url: canonical}),
};
}

Expand All @@ -145,7 +170,7 @@ class Canonical extends Audit {
baseURL.href !== canonicalURL.href) {
return {
rawValue: false,
explanation: `Points to another hreflang location (${baseURL.href})`,
explanation: str_(UIStrings.explanationPointsElsewhere, {url: baseURL.href}),
};
}

Expand All @@ -154,7 +179,7 @@ class Canonical extends Audit {
if (getPrimaryDomain(canonicalURL) !== getPrimaryDomain(baseURL)) {
return {
rawValue: false,
explanation: `Points to a different domain (${canonicalURL})`,
explanation: str_(UIStrings.explanationDifferentDomain, {url: canonicalURL}),
};
}

Expand All @@ -163,7 +188,7 @@ class Canonical extends Audit {
canonicalURL.pathname === '/' && baseURL.pathname !== '/') {
return {
rawValue: false,
explanation: 'Points to a root of the same origin',
explanation: str_(UIStrings.explanationRoot),
};
}

Expand All @@ -175,3 +200,4 @@ class Canonical extends Audit {
}

module.exports = Canonical;
module.exports.UIStrings = UIStrings;
31 changes: 21 additions & 10 deletions lighthouse-core/audits/seo/font-size.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@ const ViewportAudit = require('../viewport');
const MINIMAL_PERCENTAGE_OF_LEGIBLE_TEXT = 60;

const UIStrings = {
/** Imperative title of a Lighthouse audit that tells the user that they should use font sizes that are easily read by the user. This is displayed in a list of audit titles that Lighthouse generates. */
/** Title of a Lighthouse audit that provides detail on the font sizes used on the page. This descriptive title is shown to users when the fonts used on the page are large enough to be considered legible. */
title: 'Document uses legible font sizes',
/** Imperative title of a Lighthouse audit that tells the user that they should use font sizes that are easily read by the user. This imperative title is shown to users when there is a font that is too small to be read by the user. */
/** Title of a Lighthouse audit that provides detail on the font sizes used on the page. This descriptive title is shown to users when there is a font that may be too small to be read by users. */
failureTitle: 'Document doesn\'t use legible font sizes',
/** Description of a Lighthouse audit that tells the user *why* they need to use a larger font size. 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: 'Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/font-sizes).',
/** [ICU Syntax] Label for the audit identifying font sizes that are too small. */
displayValue: '{decimalProportion, number, extendedPercent} legible text',
/** Explanatory message stating that there was a failure in an audit caused by a missing page viewport meta tag configuration. "viewport" and "meta" are HTML terms and should not be translated. */
explanationViewport: 'Text is illegible because there\'s no viewport meta tag optimized ' +
'for mobile screens.',
/** Explanatory message stating that there was a failure in an audit caused by a certain percentage of the text on the page being too small. "decimalProportion" will be replaced by a percentage between 0 and 100%. */
explanation: '{decimalProportion, number, extendedPercent} of text is too small.',
/** Explanatory message stating that there was a failure in an audit caused by a certain percentage of the text on the page being too small, based on a sample size of text that was less than 100% of the text on the page. "decimalProportion" will be replaced by a percentage between 0 and 100%. */
explanationWithDisclaimer: '{decimalProportion, number, extendedPercent} of text is too ' +
'small (based on {decimalProportionVisited, number, extendedPercent} sample).',
};

const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);
Expand Down Expand Up @@ -212,8 +220,7 @@ class FontSize extends Audit {
if (!hasViewportSet) {
return {
rawValue: false,
explanation:
'Text is illegible because there\'s no viewport meta tag optimized for mobile screens',
explanation: str_(UIStrings.explanationViewport),
};
}

Expand Down Expand Up @@ -287,16 +294,20 @@ class FontSize extends Audit {

let explanation;
if (!passed) {
const percentageOfFailingText = parseFloat((100 - percentageOfPassingText).toFixed(2));
let disclaimer = '';
const percentageOfFailingText = (100 - percentageOfPassingText) / 100;

// if we were unable to visit all text nodes we should disclose that information
if (visitedTextLength < totalTextLength) {
const percentageOfVisitedText = visitedTextLength / totalTextLength * 100;
disclaimer = ` (based on ${percentageOfVisitedText.toFixed()}% sample)`;
const percentageOfVisitedText = (visitedTextLength / totalTextLength);
explanation = str_(UIStrings.explanationWithDisclaimer,
{
decimalProportion: percentageOfFailingText,
decimalProportionVisited: percentageOfVisitedText,
});
} else {
explanation = str_(UIStrings.explanation,
{decimalProportion: percentageOfFailingText});
}

explanation = `${percentageOfFailingText}% of text is too small${disclaimer}.`;
}

return {
Expand Down
23 changes: 18 additions & 5 deletions lighthouse-core/audits/seo/hreflang.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@ const MainResource = require('../../computed/main-resource.js');
const VALID_LANGS = importValidLangs();
const LINK_HEADER = 'link';
const NO_LANGUAGE = 'x-default';
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the `hreflang` attribute on a page. This descriptive title is shown when the page's `hreflang` attribute is configured correctly. "hreflang" is an HTML attribute and should not be translated. */
title: 'Document has a valid `hreflang`',
/** Title of a Lighthouse audit that provides detail on the `hreflang` attribute on a page. This descriptive title is shown when the page's `hreflang` attribute is not valid and needs to be fixed. "hreflang" is an HTML attribute and should not be translated. */
failureTitle: 'Document doesn\'t have a valid `hreflang`',
/** Description of a Lighthouse audit that tells the user *why* they need to have an hreflang link 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. "hreflang" is an HTML attribute and should not be translated. */
description: 'hreflang links tell search engines what version of a page they should ' +
'list in search results for a given language or region. [Learn more]' +
'(https://developers.google.com/web/tools/lighthouse/audits/hreflang).',
};

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

/**
* Import list of valid languages from axe core without including whole axe-core package
Expand Down Expand Up @@ -65,11 +79,9 @@ class Hreflang extends Audit {
static get meta() {
return {
id: 'hreflang',
title: 'Document has a valid `hreflang`',
failureTitle: 'Document doesn\'t have a valid `hreflang`',
description: 'hreflang links tell search engines what version of a page they should ' +
'list in search results for a given language or region. [Learn more]' +
'(https://developers.google.com/web/tools/lighthouse/audits/hreflang).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['Hreflang', 'URL'],
};
}
Expand Down Expand Up @@ -120,3 +132,4 @@ class Hreflang extends Audit {
}

module.exports = Hreflang;
module.exports.UIStrings = UIStrings;
23 changes: 18 additions & 5 deletions lighthouse-core/audits/seo/http-status-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ const Audit = require('../audit');
const MainResource = require('../../computed/main-resource.js');
const HTTP_UNSUCCESSFUL_CODE_LOW = 400;
const HTTP_UNSUCCESSFUL_CODE_HIGH = 599;
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on the HTTP status code a page responds with. This descriptive title is shown when the page has responded with a valid HTTP status code. */
title: 'Page has successful HTTP status code',
/** Descriptive title of a Lighthouse audit that provides detail on the HTTP status code a page responds with. This descriptive title is shown when the page responds to requests with an HTTP status code that indicates the request was unsuccessful. */
failureTitle: 'Page has unsuccessful HTTP status code',
/** Description of a Lighthouse audit that tells the user *why* they need to serve pages with a valid HTTP status code. 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: 'Pages with unsuccessful HTTP status codes may not be indexed properly. ' +
'[Learn more]' +
'(https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).',
};

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

class HTTPStatusCode extends Audit {
/**
Expand All @@ -17,11 +31,9 @@ class HTTPStatusCode extends Audit {
static get meta() {
return {
id: 'http-status-code',
title: 'Page has successful HTTP status code',
failureTitle: 'Page has unsuccessful HTTP status code',
description: 'Pages with unsuccessful HTTP status codes may not be indexed properly. ' +
'[Learn more]' +
'(https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['devtoolsLogs', 'URL'],
};
}
Expand Down Expand Up @@ -55,3 +67,4 @@ class HTTPStatusCode extends Audit {
}

module.exports = HTTPStatusCode;
module.exports.UIStrings = UIStrings;
23 changes: 18 additions & 5 deletions lighthouse-core/audits/seo/is-crawlable.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ const BLOCKLIST = new Set([
]);
const ROBOTS_HEADER = 'x-robots-tag';
const UNAVAILABLE_AFTER = 'unavailable_after';
const i18n = require('../../lib/i18n/i18n.js');

const UIStrings = {
/** Title of a Lighthouse audit that provides detail on if search-engine crawlers are blocked from indexing the page. This title is shown when the page is not blocked from indexing and can be crawled. */
title: 'Page isn’t blocked from indexing',
/** Title of a Lighthouse audit that provides detail on if search-engine crawlers are blocked from indexing the page. This title is shown when the page has been configured to block indexing and therefore cannot be indexed by search engines. */
failureTitle: 'Page is blocked from indexing',
/** Description of a Lighthouse audit that tells the user *why* allowing search-engine crawling of their page is beneficial. 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: 'Search engines are unable to include your pages in search results ' +
'if they don\'t have permission to crawl them. [Learn ' +
'more](https://developers.google.com/web/tools/lighthouse/audits/indexing).',
};

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

/**
* Checks if given directive is a valid unavailable_after directive with a date in the past
Expand Down Expand Up @@ -64,11 +78,9 @@ class IsCrawlable extends Audit {
static get meta() {
return {
id: 'is-crawlable',
title: 'Page isn’t blocked from indexing',
failureTitle: 'Page is blocked from indexing',
description: 'Search engines are unable to include your pages in search results ' +
'if they don\'t have permission to crawl them. [Learn ' +
'more](https://developers.google.com/web/tools/lighthouse/audits/indexing).',
title: str_(UIStrings.title),
failureTitle: str_(UIStrings.failureTitle),
description: str_(UIStrings.description),
requiredArtifacts: ['MetaElements', 'RobotsTxt', 'URL'],
};
}
Expand Down Expand Up @@ -135,3 +147,4 @@ class IsCrawlable extends Audit {
}

module.exports = IsCrawlable;
module.exports.UIStrings = UIStrings;
Loading

0 comments on commit 4290080

Please sign in to comment.