[go: nahoru, domu]

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

misc(treemap): i18n #12441

Merged
merged 20 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build/build-treemap.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ async function run() {
fs.readFileSync(require.resolve('tabulator-tables/dist/js/modules/format.js'), 'utf8'),
fs.readFileSync(require.resolve('tabulator-tables/dist/js/modules/resize_columns.js'), 'utf8'),
/* eslint-enable max-len */
{path: '../../lighthouse-core/report/html/renderer/i18n.js'},
{path: '../../lighthouse-core/report/html/renderer/util.js'},
connorjclark marked this conversation as resolved.
Show resolved Hide resolved
{path: 'src/*'},
],
assets: [
Expand Down
11 changes: 11 additions & 0 deletions lighthouse-core/report/html/renderer/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ class I18n {
return `${kbs}${NBSP2}KiB`;
}

/**
* @param {number} size
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 0.1
* @return {string}
*/
formatBytesToMiB(size, granularity = 0.1) {
const formatter = this._byteFormatterForGranularity(granularity);
const kbs = formatter.format(Math.round(size / 1024 ** 2 / granularity) * granularity);
return `${kbs}${NBSP2}MiB`;
}

/**
* @param {number} size
* @param {number=} granularity Controls how coarse the displayed value is, defaults to 1
Expand Down
17 changes: 17 additions & 0 deletions lighthouse-core/report/html/renderer/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,23 @@ Util.UIStrings = {

/** Descriptive explanation for environment throttling that was provided by the runtime environment instead of provided by Lighthouse throttling. */
throttlingProvided: 'Provided by environment',

/** Label for a button that alternates between showing or hiding a table. */
treemapToggleTable: 'Toggle Table',
/** Text for an option in a dropdown menu, when selected the current view of the app is set to all scripts. */
treemapAllScripts: 'All Scripts',
/** Label for a column where the values are URLs, JS module names, or arbitrary identifiers. For simplicity, just 'name' is used. */
treemapName: 'Name',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name or URL / Module ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which column is this in treemap app exactly? it's been awhile since I've used it should we make it part of the vercel deployments on PRs?

Identifier perhaps?

/** Label for a value associated with how many bytes a URL/file is, on-disk. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the on disk distinction. Just saying it's the uncompressed size?

treemapResourceBytes: 'Resource Bytes',
/** Label for a value associated with how many bytes a URL/file is, over-network. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one doesn't seem right

Suggested change
/** Label for a value associated with how many bytes a URL/file is, over-network. */
/** Label for a value stating how many bytes of a URL/file were not used. */

maybe?

treemapUnusedBytes: 'Unused Bytes',
/** Label for a column where the values represent how much of a file is used bytes vs unused bytes (coverage). */
treemapCoverage: 'Coverage',
/** Label for a button that shows everything. */
treemapAll: 'All',
/** Label for a button that highlights information about duplicate modules (aka: files, javascript resources). */
treemapDuplicateModules: 'Duplicate Modules',
};

if (typeof module !== 'undefined' && module.exports) {
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-core/scripts/i18n/collect-strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ if (require.main === module) {

if (collisions > 0) {
console.log(`MEANING COLLISION: ${collisions} string(s) have the same content.`);
assert.equal(collisions, 30, `The number of duplicate strings have changed, update this assertion if that is expected, or reword strings. Collisions: ${collisionStrings.join('\n')}`);
assert.equal(collisions, 32, `The number of duplicate strings have changed, update this assertion if that is expected, or reword strings. Collisions: ${collisionStrings.join('\n')}`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name, and....?

This comment was marked as spam.

}

writeStringsToCtcFiles('en-US', strings);
Expand Down
2 changes: 1 addition & 1 deletion lighthouse-treemap/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

<span class="lh-header__inputs">
<select class="bundle-selector"></select>
<button class="lh-button lh-button--active lh-button--toggle-table">Toggle Table</button>
<button data-i18n="treemapToggleTable" class="lh-button lh-button--active lh-button--toggle-table"></button>
</span>
</div>

Expand Down
54 changes: 46 additions & 8 deletions lighthouse-treemap/app/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/* eslint-env browser */

/* globals webtreemap TreemapUtil Tabulator Cell Row */
/* globals I18n webtreemap TreemapUtil Util Tabulator Cell Row */

const UNUSED_BYTES_IGNORE_THRESHOLD = 20 * 1024;
const UNUSED_BYTES_IGNORE_BUNDLE_SOURCE_RATIO = 0.5;
Expand Down Expand Up @@ -361,6 +361,20 @@ class TreemapViewer {
});
});

/** @param {'resourceBytes'|'unusedBytes'} field */
const makeBytesTooltip = (field) => {
/** @param {Tabulator.CellComponent} cell */
const fn = (cell) => {
/** @type {typeof data[number]} */
const dataRow = cell.getRow().getData();
const value = dataRow[field];
if (value === undefined) return '';

return Util.i18n.formatBytes(value);
};
return fn;
};

/** @param {Tabulator.CellComponent} cell */
const makeNameTooltip = (cell) => {
/** @type {typeof data[number]} */
Expand All @@ -377,7 +391,7 @@ class TreemapViewer {
if (!dataRow.unusedBytes) return '';

const percent = Math.floor(100 * dataRow.unusedBytes / dataRow.resourceBytes);
return `${percent}% bytes unused`;
return `${Util.i18n.formatNumber(percent)}% bytes unused`;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have a good way to handle this; thoughts? It's just a tooltip...

should we do the "nearly correct" thing and just string concat this formatted number w/ a Util.i18n.bytesUnused ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof, um what about filling with a prefilled value and replacing in the report?

e.g. ask translators to do {percentUnused}% bytes unused and for rendererFormattedStrings we prefill percentUnused to be 123456789 or some specific predetermined number?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but how would we do the value replacement at runtime? can we do something like

const data = replaceIcuMessages({string: str_(myStringWithPlaceholders, {value: 123}})
// get string from data ....

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah IDK, but either way I think we can punt for now :)

Maybe we start an issue with i18n frontend use cases? This happens in the report to some extent too we just chopped off the explanations to make them less helpful.

};

const gridEl = document.createElement('div');
Expand All @@ -397,19 +411,21 @@ class TreemapViewer {
{column: 'resourceBytes', dir: 'desc'},
],
columns: [
{title: 'Name', field: 'name', widthGrow: 5, tooltip: makeNameTooltip},
{title: 'Size', field: 'resourceBytes', headerSortStartingDir: 'desc', formatter: cell => {
// eslint-disable-next-line max-len
{title: Util.i18n.strings.treemapName, field: 'name', widthGrow: 5, tooltip: makeNameTooltip},
// eslint-disable-next-line max-len
{title: Util.i18n.strings.treemapResourceBytes, field: 'resourceBytes', headerSortStartingDir: 'desc', tooltip: makeBytesTooltip('resourceBytes'), formatter: cell => {
const value = cell.getValue();
return TreemapUtil.formatBytes(value);
}},
// eslint-disable-next-line max-len
{title: 'Unused', field: 'unusedBytes', widthGrow: 1, sorterParams: {alignEmptyValues: 'bottom'}, headerSortStartingDir: 'desc', formatter: cell => {
{title: Util.i18n.strings.treemapUnusedBytes, field: 'unusedBytes', widthGrow: 1, sorterParams: {alignEmptyValues: 'bottom'}, headerSortStartingDir: 'desc', tooltip: makeBytesTooltip('unusedBytes'), formatter: cell => {
const value = cell.getValue();
if (value === undefined) return '';
return TreemapUtil.formatBytes(value);
}},
// eslint-disable-next-line max-len
{title: 'Coverage', widthGrow: 3, headerSort: false, tooltip: makeCoverageTooltip, formatter: cell => {
{title: Util.i18n.strings.treemapCoverage, widthGrow: 3, headerSort: false, tooltip: makeCoverageTooltip, formatter: cell => {
/** @type {typeof data[number]} */
const dataRow = cell.getRow().getData();

Expand Down Expand Up @@ -450,6 +466,10 @@ class TreemapViewer {
*/
makeCaption(node) {
const partitionBy = this.currentViewMode.partitionBy || 'resourceBytes';
const partitionByStr = {
resourceBytes: Util.i18n.strings.treemapResourceBytes,
unusedBytes: Util.i18n.strings.treemapUnusedBytes,
}[partitionBy];
const bytes = node[partitionBy];
const total = this.currentTreemapRoot[partitionBy];

Expand All @@ -458,10 +478,11 @@ class TreemapViewer {
];

if (bytes !== undefined && total !== undefined) {
let str = `${TreemapUtil.formatBytes(bytes)} (${Math.round(bytes / total * 100)}%)`;
const percentStr = `${Util.i18n.formatNumber(Math.round(bytes / total * 100))}%`;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is concating % here OK?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, good question, but there's a lot of concat going on here with the partitionByStr: and then parts.join too so I'm not sure that's even our biggest issue. Since we're best effort on this already, seems fine file an issue to solve this report use case? 🤷

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for plain % (not concatenating to another string), there's new Intl.NumberFormat(locale, {style: 'percent'}).format(value). You have to be careful with report formatting stuff because Safari formatting support has really lagged the other browsers (and Node), but 'percent' has been supported for a while now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then this value isn't just ##%, it's put into let str = `${TreemapUtil.formatBytes(bytes)} (${percentStr})`;, so agree with the 🤷 :)

let str = `${TreemapUtil.formatBytes(bytes)} (${percentStr})`;
// Only add label for bytes on the root node.
if (node === this.currentTreemapRoot) {
str = `${partitionBy}: ${str}`;
str = `${partitionByStr}: ${str}`;
}
parts.push(str);
}
Expand Down Expand Up @@ -569,6 +590,23 @@ function injectOptions(options) {
* @param {LH.Treemap.Options} options
*/
function init(options) {
const report = Util.prepareReportResult(options.lhr);
const i18n = new I18n(report.configSettings.locale, {
// Set missing renderer strings to default (english) values.
...Util.UIStrings,
...report.i18n.rendererFormattedStrings,
});
Util.i18n = i18n;
Util.reportJson = report;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this? I thought this was just for the performance category renderer


// Fill in all i18n data.
for (const node of document.querySelectorAll('[data-i18n]')) {
// These strings are guaranteed to (at least) have a default English string in Util.UIStrings,
// so this cannot be undefined as long as `report-ui-features.data-i18n` test passes.
connorjclark marked this conversation as resolved.
Show resolved Hide resolved
const i18nAttr = /** @type {keyof LH.I18NRendererStrings} */ (node.getAttribute('data-i18n'));
node.textContent = Util.i18n.strings[i18nAttr];
}

treemapViewer = new TreemapViewer(options, TreemapUtil.find('div.lh-treemap'));

injectOptions(options);
Expand Down
12 changes: 7 additions & 5 deletions lighthouse-treemap/app/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

/* eslint-env browser */

/* globals Util */

/** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElementByTagName */
/** @template {string} T @typedef {import('typed-query-selector/parser').ParseSelector<T, Element>} ParseSelector */

Expand Down Expand Up @@ -126,9 +128,9 @@ class TreemapUtil {
* @param {number} bytes
*/
static formatBytes(bytes) {
connorjclark marked this conversation as resolved.
Show resolved Hide resolved
if (bytes >= MiB) return (bytes / MiB).toFixed(2) + '\xa0MiB';
if (bytes >= KiB) return (bytes / KiB).toFixed(0) + '\xa0KiB';
return bytes + '\xa0B';
if (bytes >= MiB) return Util.i18n.formatBytesToMiB(bytes);
if (bytes >= KiB) return Util.i18n.formatBytesToKiB(bytes);
return Util.i18n.formatNumber(bytes) + '\xa0B';
}

/**
Expand All @@ -137,8 +139,8 @@ class TreemapUtil {
*/
static format(value, unit) {
if (unit === 'bytes') return TreemapUtil.formatBytes(value);
if (unit === 'time') return `${value}\xa0ms`;
return `${value} ${unit}`;
if (unit === 'time') return `${Util.i18n.formatNumber(value)}\xa0ms`;
return `${Util.i18n.formatNumber(value)}\xa0${unit}`;
}

/**
Expand Down