Add basic date & time formatters using navigator language (#404)
Adjacent to #400 — while this isn't yet a proper localization pass, at least dates & times will now use the user's browser language/locale settings. When used in Browsertrix, this should ensure dates are formatted more consistently, at least when the user has a locale with a language matching one of the supported languages in Browsertrix set in their browser settings. Also adds tabular numerals in a few places (e.g. lists of dates/times).
This commit is contained in:
@@ -12,6 +12,7 @@ import { tsToDate } from "./pageutils";
|
|||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
import { property } from "lit/decorators.js";
|
import { property } from "lit/decorators.js";
|
||||||
import type { ItemType } from "./types";
|
import type { ItemType } from "./types";
|
||||||
|
import { dateTimeFormatter } from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
export class RWPEmbedReceipt extends LitElement {
|
export class RWPEmbedReceipt extends LitElement {
|
||||||
@@ -184,7 +185,9 @@ export class RWPEmbedReceipt extends LitElement {
|
|||||||
? `https://crt.sh/?q=${certFingerprint}`
|
? `https://crt.sh/?q=${certFingerprint}`
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
const dateStr = tsToDate(this.ts).toLocaleString();
|
const dateStr = this.ts
|
||||||
|
? dateTimeFormatter.format(tsToDate(this.ts) as Date)
|
||||||
|
: "";
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="dropdown mb-4 ${this.active ? "is-active" : ""}">
|
<div class="dropdown mb-4 ${this.active ? "is-active" : ""}">
|
||||||
|
|||||||
+4
-1
@@ -7,6 +7,7 @@ import prettyBytes from "pretty-bytes";
|
|||||||
import type { ItemType } from "./types";
|
import type { ItemType } from "./types";
|
||||||
|
|
||||||
import "./components/labeled-field";
|
import "./components/labeled-field";
|
||||||
|
import { dateTimeFormatter } from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class ItemInfo extends LitElement {
|
class ItemInfo extends LitElement {
|
||||||
@@ -111,7 +112,9 @@ class ItemInfo extends LitElement {
|
|||||||
</wr-labeled-field>`
|
</wr-labeled-field>`
|
||||||
: nothing}
|
: nothing}
|
||||||
<wr-labeled-field label="Date Loaded" class="column is-2">
|
<wr-labeled-field label="Date Loaded" class="column is-2">
|
||||||
${item!.ctime ? new Date(item!.ctime).toLocaleString() : nothing}
|
${item!.ctime
|
||||||
|
? dateTimeFormatter.format(new Date(item!.ctime))
|
||||||
|
: nothing}
|
||||||
</wr-labeled-field>
|
</wr-labeled-field>
|
||||||
<wr-labeled-field label="Total Size" class="column is-2">
|
<wr-labeled-field label="Total Size" class="column is-2">
|
||||||
${prettyBytes(Number(item!.totalSize || item!.size || 0))}
|
${prettyBytes(Number(item!.totalSize || item!.size || 0))}
|
||||||
|
|||||||
+15
-3
@@ -55,6 +55,7 @@ import type { Replay } from "./replay";
|
|||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import "./item-info";
|
import "./item-info";
|
||||||
|
import { dateTimeFormatter } from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
const RWP_SCHEME = "search://";
|
const RWP_SCHEME = "search://";
|
||||||
|
|
||||||
@@ -756,6 +757,7 @@ class Item extends LitElement {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
transition: background-color var(--sl-transition-fast);
|
transition: background-color var(--sl-transition-fast);
|
||||||
color: var(--sl-color-neutral-600);
|
color: var(--sl-color-neutral-600);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timestamp-dropdown-btn:hover {
|
.timestamp-dropdown-btn:hover {
|
||||||
@@ -782,6 +784,10 @@ class Item extends LitElement {
|
|||||||
transform: translateY(0.075em);
|
transform: translateY(0.075em);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timestamp-menu-item {
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
.timestamp-menu-item[aria-selected="true"]::part(label) {
|
.timestamp-menu-item[aria-selected="true"]::part(label) {
|
||||||
color: var(--sl-color-blue-600);
|
color: var(--sl-color-blue-600);
|
||||||
}
|
}
|
||||||
@@ -1245,7 +1251,9 @@ class Item extends LitElement {
|
|||||||
protected renderToolbarRight() {
|
protected renderToolbarRight() {
|
||||||
const isReplay = !!this.tabData.url;
|
const isReplay = !!this.tabData.url;
|
||||||
|
|
||||||
const dateStr = tsToDate(this.ts).toLocaleString();
|
const dateStr = this.ts
|
||||||
|
? dateTimeFormatter.format(tsToDate(this.ts) as Date)
|
||||||
|
: "";
|
||||||
|
|
||||||
return html` <div
|
return html` <div
|
||||||
class="dropdown is-right ${this.menuActive ? "is-active" : ""}"
|
class="dropdown is-right ${this.menuActive ? "is-active" : ""}"
|
||||||
@@ -1419,7 +1427,9 @@ class Item extends LitElement {
|
|||||||
// Filter out invalid dates
|
// Filter out invalid dates
|
||||||
try {
|
try {
|
||||||
const date = getDateFromTS(+ts);
|
const date = getDateFromTS(+ts);
|
||||||
const dateStr = tsToDate(date).toLocaleString();
|
const dateStr = date
|
||||||
|
? dateTimeFormatter.format(tsToDate(date) as Date)
|
||||||
|
: "";
|
||||||
timestampStrs.push({
|
timestampStrs.push({
|
||||||
date,
|
date,
|
||||||
label: dateStr,
|
label: dateStr,
|
||||||
@@ -1428,7 +1438,9 @@ class Item extends LitElement {
|
|||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const currDateStr = tsToDate(this.ts).toLocaleString();
|
const currDateStr = this.ts
|
||||||
|
? dateTimeFormatter.format(tsToDate(this.ts) as Date)
|
||||||
|
: "";
|
||||||
return html`<div id="datetime" class="control is-hidden-mobile">
|
return html`<div id="datetime" class="control is-hidden-mobile">
|
||||||
${timestampStrs.length > 1
|
${timestampStrs.length > 1
|
||||||
? html`
|
? html`
|
||||||
|
|||||||
+12
-19
@@ -9,6 +9,11 @@ import { getPageDateTS, getReplayLink } from "./pageutils";
|
|||||||
|
|
||||||
import { wrapCss } from "./misc";
|
import { wrapCss } from "./misc";
|
||||||
import type { URLResource } from "./types";
|
import type { URLResource } from "./types";
|
||||||
|
import {
|
||||||
|
dateFormatter,
|
||||||
|
dateTimeFormatter,
|
||||||
|
timeFormatter,
|
||||||
|
} from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
class PageEntry extends LitElement {
|
class PageEntry extends LitElement {
|
||||||
@@ -154,6 +159,10 @@ class PageEntry extends LitElement {
|
|||||||
.media-content a {
|
.media-content a {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.col-date {
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,20 +227,8 @@ class PageEntry extends LitElement {
|
|||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
<div class="column col-date is-2">
|
<div class="column col-date is-2">
|
||||||
<div>
|
<div>${date ? dateFormatter.format(date) : ""}</div>
|
||||||
${
|
<div>${date ? timeFormatter.format(date) : ""}</div>
|
||||||
// TODO: Fix this the next time the file is edited.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
date ? date.toLocaleDateString() : ""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
${
|
|
||||||
// TODO: Fix this the next time the file is edited.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
date ? date.toLocaleTimeString() : ""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="media">
|
<div class="media">
|
||||||
@@ -259,11 +256,7 @@ class PageEntry extends LitElement {
|
|||||||
>${this.thumbnailValid ? this.renderFavicon() : ""}
|
>${this.thumbnailValid ? this.renderFavicon() : ""}
|
||||||
</p>
|
</p>
|
||||||
<p class="has-text-grey-dark text is-inline-date">
|
<p class="has-text-grey-dark text is-inline-date">
|
||||||
${
|
${date ? dateTimeFormatter.format(date) : ""}
|
||||||
// TODO: Fix this the next time the file is edited.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
date ? date.toLocaleString() : ""
|
|
||||||
}
|
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
${this.textSnippet
|
${this.textSnippet
|
||||||
|
|||||||
+2
-1
@@ -10,6 +10,7 @@ import { getTS, getReplayLink } from "./pageutils";
|
|||||||
import Split from "split.js";
|
import Split from "split.js";
|
||||||
import { type ItemType } from "./types";
|
import { type ItemType } from "./types";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
import { dateTimeFormatter } from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@customElement("wr-coll-story")
|
@customElement("wr-coll-story")
|
||||||
@@ -364,7 +365,7 @@ class Story extends LitElement {
|
|||||||
<p class="is-size-6 has-text-weight-bold has-text-link">${p.title}</p>
|
<p class="is-size-6 has-text-weight-bold has-text-link">${p.title}</p>
|
||||||
<p class="has-text-dark">${p.url}</p>
|
<p class="has-text-dark">${p.url}</p>
|
||||||
</a>
|
</a>
|
||||||
<p>${date.toLocaleString()}</p>
|
<p>${dateTimeFormatter.format(date)}</p>
|
||||||
<p>${p.desc}</p>
|
<p>${p.desc}</p>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import fasSearch from "@fortawesome/fontawesome-free/svgs/solid/search.svg";
|
|||||||
import "keyword-mark-element/lib/keyword-mark.js";
|
import "keyword-mark-element/lib/keyword-mark.js";
|
||||||
import { type ItemType } from "./types";
|
import { type ItemType } from "./types";
|
||||||
import { type URLResource } from "./types";
|
import { type URLResource } from "./types";
|
||||||
|
import { dateTimeFormatter } from "./utils/dateTimeFormatter";
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
/**
|
/**
|
||||||
@@ -544,7 +545,7 @@ class URLResources extends LitElement {
|
|||||||
</td>
|
</td>
|
||||||
<td class="column col-ts is-2">
|
<td class="column col-ts is-2">
|
||||||
<p class="minihead is-hidden-tablet">Date</p>
|
<p class="minihead is-hidden-tablet">Date</p>
|
||||||
${new Date(result.date).toLocaleString()}
|
${dateTimeFormatter.format(new Date(result.date))}
|
||||||
</td>
|
</td>
|
||||||
<td class="column col-mime is-3">
|
<td class="column col-mime is-3">
|
||||||
<p class="minihead is-hidden-tablet">Media Type</p>
|
<p class="minihead is-hidden-tablet">Media Type</p>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
export const dateTimeFormatter = new Intl.DateTimeFormat(
|
||||||
|
[...navigator.languages],
|
||||||
|
{
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const dateFormatter = new Intl.DateTimeFormat([...navigator.languages], {
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const timeFormatter = new Intl.DateTimeFormat([...navigator.languages], {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user