Skip to content

Commit 39e5430

Browse files
Connor ClarkDevtools-frontend LUCI CQ
authored andcommitted
Export all UIStrings in insight models, for external usage
We should have no i18n strings defined in insight component modules, since Lighthouse (and any other future external usages) should be able to utilize the exact same translated strings. This was already the case for title/description, but now every translated string has been moved. Bug: 388723721 Change-Id: Ic3e72acb4b697a225b102f64383660b5a0f275af Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6227699 Auto-Submit: Connor Clark <[email protected]> Reviewed-by: Jack Franklin <[email protected]> Commit-Queue: Jack Franklin <[email protected]> Reviewed-by: Adam Raine <[email protected]>
1 parent 9ff3edb commit 39e5430

39 files changed

+480
-460
lines changed

front_end/models/trace/Processor.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ describeWithEnvironment('TraceProcessor', function() {
261261
sinon.stub(Trace.Processor.TraceProcessor, 'getEnabledInsightRunners').callsFake(() => {
262262
return {
263263
RenderBlocking: {
264+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
265+
UIStrings: {} as any,
266+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
267+
i18nString: (() => {}) as any,
264268
generateInsight: () => {
265269
throw new Error('forced error');
266270
},

front_end/models/trace/insights/CLSCulprits.ts

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ import type * as Protocol from '../../../generated/protocol.js';
88
import * as Helpers from '../helpers/helpers.js';
99
import * as Types from '../types/types.js';
1010

11-
import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
12-
13-
const UIStrings = {
11+
import {
12+
InsightCategory,
13+
type InsightModel,
14+
type InsightSetContext,
15+
type PartialInsightModel,
16+
type RequiredData
17+
} from './types.js';
18+
19+
export const UIStrings = {
1420
/** Title of an insight that provides details about why elements shift/move on the page. The causes for these shifts are referred to as culprits ("reasons"). */
1521
title: 'Layout shift culprits',
1622
/**
@@ -19,11 +25,53 @@ const UIStrings = {
1925
*/
2026
description:
2127
'Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://web.dev/articles/optimize-cls), such as elements being added, removed, or their fonts changing as the page loads.',
28+
/**
29+
*@description Text indicating the worst layout shift cluster.
30+
*/
31+
worstLayoutShiftCluster: 'Worst layout shift cluster',
32+
/**
33+
* @description Text indicating the worst layout shift cluster.
34+
*/
35+
worstCluster: 'Worst cluster',
36+
/**
37+
* @description Text indicating a layout shift cluster and its start time.
38+
* @example {32 ms} PH1
39+
*/
40+
layoutShiftCluster: 'Layout shift cluster @ {PH1}',
41+
/**
42+
*@description Text indicating the biggest reasons for the layout shifts.
43+
*/
44+
topCulprits: 'Top layout shift culprits',
45+
/**
46+
* @description Text for a culprit type of Injected iframe.
47+
*/
48+
injectedIframe: 'Injected iframe',
49+
/**
50+
* @description Text for a culprit type of Font request.
51+
*/
52+
fontRequest: 'Font request',
53+
/**
54+
* @description Text for a culprit type of Animation.
55+
*/
56+
animation: 'Animation',
57+
/**
58+
* @description Text for a culprit type of Unsized images.
59+
*/
60+
unsizedImages: 'Unsized Images',
61+
/**
62+
* @description Text status when there were no layout shifts detected.
63+
*/
64+
noLayoutShifts: 'No layout shifts',
65+
/**
66+
* @description Text status when there no layout shifts culprits/root causes were found.
67+
*/
68+
noCulprits: 'Could not detect any layout shift culprits',
2269
};
70+
2371
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/CLSCulprits.ts', UIStrings);
24-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
72+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
2573

26-
export type CLSCulpritsInsightModel = InsightModel<{
74+
export type CLSCulpritsInsightModel = InsightModel<typeof UIStrings, {
2775
animationFailures: readonly NoncompositedAnimationFailure[],
2876
shifts: Map<Types.Events.SyntheticLayoutShift, LayoutShiftRootCausesData>,
2977
clusters: Types.Events.SyntheticLayoutShiftCluster[],
@@ -425,8 +473,7 @@ function getFontRootCauses(
425473
return rootCausesByShift;
426474
}
427475

428-
function finalize(partialModel: Omit<CLSCulpritsInsightModel, 'title'|'description'|'category'|'shouldShow'>):
429-
CLSCulpritsInsightModel {
476+
function finalize(partialModel: PartialInsightModel<CLSCulpritsInsightModel>): CLSCulpritsInsightModel {
430477
let maxScore = 0;
431478
for (const cluster of partialModel.clusters) {
432479
if (cluster.clusterCumulativeScore > maxScore) {
@@ -435,6 +482,7 @@ function finalize(partialModel: Omit<CLSCulpritsInsightModel, 'title'|'descripti
435482
}
436483

437484
return {
485+
strings: UIStrings,
438486
title: i18nString(UIStrings.title),
439487
description: i18nString(UIStrings.description),
440488
category: InsightCategory.CLS,

front_end/models/trace/insights/DOMSize.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ import * as Handlers from '../handlers/handlers.js';
77
import * as Helpers from '../helpers/helpers.js';
88
import * as Types from '../types/types.js';
99

10-
import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
11-
12-
const UIStrings = {
10+
import {
11+
InsightCategory,
12+
type InsightModel,
13+
type InsightSetContext,
14+
type PartialInsightModel,
15+
type RequiredData
16+
} from './types.js';
17+
18+
export const UIStrings = {
1319
/**
1420
* @description Title of an insight that recommends reducing the size of the DOM tree as a means to improve page responsiveness. "DOM" is an acronym and should not be translated.
1521
*/
@@ -19,10 +25,34 @@ const UIStrings = {
1925
*/
2026
description:
2127
'A large DOM can increase the duration of style calculations and layout reflows, impacting page responsiveness. A large DOM will also increase memory usage. [Learn how to avoid an excessive DOM size](https://developer.chrome.com/docs/lighthouse/performance/dom-size/).',
28+
/**
29+
* @description Header for a column containing the names of statistics as opposed to the actual statistic values.
30+
*/
31+
statistic: 'Statistic',
32+
/**
33+
* @description Header for a column containing the value of a statistic.
34+
*/
35+
value: 'Value',
36+
/**
37+
* @description Header for a column containing the page element related to a statistic.
38+
*/
39+
element: 'Element',
40+
/**
41+
* @description Label for a value representing the total number of elements on the page.
42+
*/
43+
totalElements: 'Total elements',
44+
/**
45+
* @description Label for a value representing the maximum depth of the Document Object Model (DOM). "DOM" is a acronym and should not be translated.
46+
*/
47+
maxDOMDepth: 'DOM depth',
48+
/**
49+
* @description Label for a value representing the maximum number of child elements of any parent element on the page.
50+
*/
51+
maxChildren: 'Most children',
2252
};
2353

2454
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DOMSize.ts', UIStrings);
25-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
55+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
2656

2757
const DOM_SIZE_DURATION_THRESHOLD = Helpers.Timing.milliToMicro(Types.Timing.Milli(40));
2858

@@ -32,7 +62,7 @@ const DOM_SIZE_DURATION_THRESHOLD = Helpers.Timing.milliToMicro(Types.Timing.Mil
3262
const LAYOUT_OBJECTS_THRESHOLD = 100;
3363
const STYLE_RECALC_ELEMENTS_THRESHOLD = 300;
3464

35-
export type DOMSizeInsightModel = InsightModel<{
65+
export type DOMSizeInsightModel = InsightModel<typeof UIStrings, {
3666
largeLayoutUpdates: Types.Events.Layout[],
3767
largeStyleRecalcs: Types.Events.UpdateLayoutTree[],
3868
maxDOMStats?: Types.Events.DOMStats,
@@ -42,10 +72,10 @@ export function deps(): ['Renderer', 'AuctionWorklets', 'DOMStats'] {
4272
return ['Renderer', 'AuctionWorklets', 'DOMStats'];
4373
}
4474

45-
function finalize(partialModel: Omit<DOMSizeInsightModel, 'title'|'description'|'category'|'shouldShow'>):
46-
DOMSizeInsightModel {
75+
function finalize(partialModel: PartialInsightModel<DOMSizeInsightModel>): DOMSizeInsightModel {
4776
const relatedEvents = [...partialModel.largeLayoutUpdates, ...partialModel.largeStyleRecalcs];
4877
return {
78+
strings: UIStrings,
4979
title: i18nString(UIStrings.title),
5080
description: i18nString(UIStrings.description),
5181
category: InsightCategory.INP,

front_end/models/trace/insights/DocumentLatency.ts

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import {
1111
type InsightModel,
1212
type InsightSetContext,
1313
InsightWarning,
14+
type PartialInsightModel,
1415
type RequiredData
1516
} from './types.js';
1617

17-
const UIStrings = {
18+
export const UIStrings = {
1819
/**
1920
*@description Title of an insight that provides a breakdown for how long it took to download the main document.
2021
*/
@@ -24,10 +25,56 @@ const UIStrings = {
2425
*/
2526
description:
2627
'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.',
28+
/**
29+
* @description Text to tell the user that the document request does not have redirects.
30+
*/
31+
passingRedirects: 'Avoids redirects',
32+
/**
33+
* @description Text to tell the user that the document request had redirects.
34+
*/
35+
failedRedirects: 'Had redirects',
36+
/**
37+
* @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.
38+
*/
39+
passingServerResponseTime: 'Server responds quickly',
40+
/**
41+
* @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.
42+
*/
43+
failedServerResponseTime: 'Server responded slowly',
44+
/**
45+
* @description Text to tell the user that text compression (like gzip) was applied.
46+
*/
47+
passingTextCompression: 'Applies text compression',
48+
/**
49+
* @description Text to tell the user that text compression (like gzip) was not applied.
50+
*/
51+
failedTextCompression: 'No compression applied',
52+
/**
53+
* @description Text for a label describing a network request event as having redirects.
54+
*/
55+
redirectsLabel: 'Redirects',
56+
/**
57+
* @description Text for a label describing a network request event as taking too long to start delivery by the server.
58+
*/
59+
serverResponseTimeLabel: 'Server response time',
60+
/**
61+
* @description Text for a label describing a network request event as taking longer to download because it wasn't compressed.
62+
*/
63+
uncompressedDownload: 'Uncompressed download',
64+
/**
65+
*@description Text for a screen-reader label to tell the user that the icon represents a successful insight check
66+
*@example {Server response time} PH1
67+
*/
68+
successAriaLabel: 'Insight check passed: {PH1}',
69+
/**
70+
*@description Text for a screen-reader label to tell the user that the icon represents an unsuccessful insight check
71+
*@example {Server response time} PH1
72+
*/
73+
failedAriaLabel: 'Insight check failed: {PH1}',
2774
};
2875

2976
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings);
30-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
77+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
3178

3279
// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.
3380
// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.
@@ -37,7 +84,7 @@ const TARGET_MS = 100;
3784
// Threshold for compression savings.
3885
const IGNORE_THRESHOLD_IN_BYTES = 1400;
3986

40-
export type DocumentLatencyInsightModel = InsightModel<{
87+
export type DocumentLatencyInsightModel = InsightModel<typeof UIStrings, {
4188
data?: {
4289
serverResponseTime: Types.Timing.Milli,
4390
serverResponseTooSlow: boolean,
@@ -125,15 +172,15 @@ function getCompressionSavings(request: Types.Events.SyntheticNetworkRequest): n
125172
return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;
126173
}
127174

128-
function finalize(partialModel: Omit<DocumentLatencyInsightModel, 'title'|'description'|'category'|'shouldShow'>):
129-
DocumentLatencyInsightModel {
175+
function finalize(partialModel: PartialInsightModel<DocumentLatencyInsightModel>): DocumentLatencyInsightModel {
130176
let hasFailure = false;
131177
if (partialModel.data) {
132178
hasFailure = partialModel.data.redirectDuration > 0 || partialModel.data.serverResponseTooSlow ||
133179
partialModel.data.uncompressedResponseBytes > 0;
134180
}
135181

136182
return {
183+
strings: UIStrings,
137184
title: i18nString(UIStrings.title),
138185
description: i18nString(UIStrings.description),
139186
category: InsightCategory.ALL,

front_end/models/trace/insights/FontDisplay.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,46 @@ import * as Platform from '../../../core/platform/platform.js';
77
import * as Helpers from '../helpers/helpers.js';
88
import * as Types from '../types/types.js';
99

10-
import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
10+
import {
11+
InsightCategory,
12+
type InsightModel,
13+
type InsightSetContext,
14+
type PartialInsightModel,
15+
type RequiredData
16+
} from './types.js';
1117

12-
const UIStrings = {
18+
export const UIStrings = {
1319
/** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */
1420
title: 'Font display',
1521
/**
1622
* @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page.
1723
*/
1824
description:
1925
'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).',
26+
/** Column for a font loaded by the page to render text. */
27+
fontColumn: 'Font',
28+
/** Column for the amount of time wasted. */
29+
wastedTimeColumn: 'Wasted time',
2030
};
2131

2232
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings);
23-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
33+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
2434

2535
export function deps(): ['Meta', 'NetworkRequests', 'LayoutShifts'] {
2636
return ['Meta', 'NetworkRequests', 'LayoutShifts'];
2737
}
2838

29-
export type FontDisplayInsightModel = InsightModel<{
39+
export type FontDisplayInsightModel = InsightModel<typeof UIStrings, {
3040
fonts: Array<{
3141
request: Types.Events.SyntheticNetworkRequest,
3242
display: string,
3343
wastedTime: Types.Timing.Milli,
3444
}>,
3545
}>;
3646

37-
function finalize(partialModel: Omit<FontDisplayInsightModel, 'title'|'description'|'category'|'shouldShow'>):
38-
FontDisplayInsightModel {
47+
function finalize(partialModel: PartialInsightModel<FontDisplayInsightModel>): FontDisplayInsightModel {
3948
return {
49+
strings: UIStrings,
4050
title: i18nString(UIStrings.title),
4151
description: i18nString(UIStrings.description),
4252
category: InsightCategory.INP,

front_end/models/trace/insights/ForcedReflow.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ import {
1313
type ForcedReflowAggregatedData,
1414
InsightCategory,
1515
type InsightModel,
16+
type PartialInsightModel,
1617
type RequiredData,
1718
} from './types.js';
1819

1920
export function deps(): ['Warnings', 'Renderer'] {
2021
return ['Warnings', 'Renderer'];
2122
}
2223

23-
const UIStrings = {
24+
export const UIStrings = {
2425
/**
2526
*@description Title of an insight that provides details about Forced reflow.
2627
*/
@@ -30,12 +31,24 @@ const UIStrings = {
3031
*/
3132
description:
3233
'Many APIs, typically reading layout geometry, force the rendering engine to pause script execution in order to calculate the style and layout. Learn more about [forced reflow](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts) and its mitigations.',
34+
/**
35+
*@description Title of a list to provide related stack trace data
36+
*/
37+
relatedStackTrace: 'Stack trace',
38+
/**
39+
*@description Text to describe the top time-consuming function call
40+
*/
41+
topTimeConsumingFunctionCall: 'Top function call',
42+
/**
43+
* @description Text to describe the total reflow time
44+
*/
45+
totalReflowTime: 'Total reflow time',
3346
};
3447

3548
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/ForcedReflow.ts', UIStrings);
36-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
49+
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
3750

38-
export type ForcedReflowInsightModel = InsightModel<{
51+
export type ForcedReflowInsightModel = InsightModel<typeof UIStrings, {
3952
topLevelFunctionCallData: ForcedReflowAggregatedData | undefined,
4053
aggregatedBottomUpData: BottomUpCallStack[],
4154
}>;
@@ -175,9 +188,9 @@ function aggregateForcedReflow(
175188
return [topLevelFunctionCallData, aggregatedBottomUpData];
176189
}
177190

178-
function finalize(partialModel: Omit<ForcedReflowInsightModel, 'title'|'description'|'category'|'shouldShow'>):
179-
ForcedReflowInsightModel {
191+
function finalize(partialModel: PartialInsightModel<ForcedReflowInsightModel>): ForcedReflowInsightModel {
180192
return {
193+
strings: UIStrings,
181194
title: i18nString(UIStrings.title),
182195
description: i18nString(UIStrings.description),
183196
category: InsightCategory.ALL,

0 commit comments

Comments
 (0)