Skip to content

Commit

Permalink
Ensure dates are formatted with the current app locale (and not brows…
Browse files Browse the repository at this point in the history
…er default) (#1697)

### Motivation

While using the browser default locale is often good enough, we probably
want more full control over locales, especially when we allow users to
choose their own locale — it's a poor experience to not have dates and
numbers formatted consistently with your chosen locale.

### Changes

Ensures (almost) all instances of `<sl-format-date>` as well as `Intl.*`
have the correct locale passed into them from our Lit localization
system.

The one exception here is in `frontend/src/utils/number.ts` where
ordinal suffixes aren't localized, so the locale is hardcoded to `en` —
I'll revisit this in the future.
  • Loading branch information
emma-sg authored Apr 20, 2024
1 parent a60f56b commit c5b808b
Show file tree
Hide file tree
Showing 18 changed files with 50 additions and 17 deletions.
2 changes: 2 additions & 0 deletions frontend/src/features/archived-items/archived-item-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { TailwindElement } from "@/classes/TailwindElement";
import { NavigateController } from "@/controllers/navigate";
import type { ArchivedItem } from "@/types/crawler";
import { renderName } from "@/utils/crawler";
import { getLocale } from "@/utils/localization";

export type CheckboxChangeEventDetail = {
checked: boolean;
Expand Down Expand Up @@ -123,6 +124,7 @@ export class ArchivedItemListItem extends TailwindElement {
</btrix-table-cell>
<btrix-table-cell>
<sl-format-date
lang=${getLocale()}
class="truncate"
date=${`${this.item.finished}Z`}
month="2-digit"
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/features/archived-items/crawl-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { RelativeDuration } from "@/components/ui/relative-duration";
import { NavigateController } from "@/controllers/navigate";
import type { Crawl } from "@/types/crawler";
import { renderName } from "@/utils/crawler";
import { getLocale } from "@/utils/localization";

/**
* @slot menu
Expand Down Expand Up @@ -65,8 +66,7 @@ export class CrawlListItem extends TailwindElement {
@query("btrix-overflow-dropdown")
dropdownMenu!: OverflowDropdown;

// TODO localize
private readonly numberFormatter = new Intl.NumberFormat(undefined, {
private readonly numberFormatter = new Intl.NumberFormat(getLocale(), {
notation: "compact",
});

Expand All @@ -82,6 +82,7 @@ export class CrawlListItem extends TailwindElement {
${this.safeRender(
(crawl) => html`
<sl-format-date
lang=${getLocale()}
date=${`${crawl.started}Z`}
month="2-digit"
day="2-digit"
Expand Down Expand Up @@ -150,6 +151,7 @@ export class CrawlListItem extends TailwindElement {
${this.safeRender(
(crawl) => html`
<sl-format-date
lang=${getLocale()}
date=${`${crawl.started}Z`}
month="2-digit"
day="2-digit"
Expand All @@ -166,6 +168,7 @@ export class CrawlListItem extends TailwindElement {
crawl.finished
? html`
<sl-format-date
lang=${getLocale()}
date=${`${crawl.finished}Z`}
month="2-digit"
day="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/features/archived-items/crawl-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { customElement, property, state } from "lit/decorators.js";

import type { APIPaginatedList } from "@/types/api";
import { truncate } from "@/utils/css";
import { getLocale } from "@/utils/localization";

export type CrawlLog = {
timestamp: string;
Expand Down Expand Up @@ -123,6 +124,7 @@ export class CrawlLogs extends LitElement {
<div class="row">
<div>
<sl-format-date
lang=${getLocale()}
date=${log.timestamp}
month="2-digit"
day="2-digit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { Profile } from "@/pages/org/types";
import type { APIPaginatedList } from "@/types/api";
import type { AuthState } from "@/utils/AuthService";
import LiteElement from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";

type SelectBrowserProfileChangeDetail = {
value: Profile | undefined;
Expand Down Expand Up @@ -83,6 +84,7 @@ export class SelectBrowserProfile extends LiteElement {
<div slot="suffix">
<div class="text-xs">
<sl-format-date
lang=${getLocale()}
date=${`${profile.created}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand Down Expand Up @@ -116,6 +118,7 @@ export class SelectBrowserProfile extends LiteElement {
<span>
${msg("Last edited:")}
<sl-format-date
lang=${getLocale()}
date=${`${this.selectedProfile.created}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/features/collections/collection-workflow-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
import type { Crawl, Workflow } from "@/types/crawler";
import { type AuthState } from "@/utils/AuthService";
import { finishedCrawlStates } from "@/utils/crawler";
import { getLocale } from "@/utils/localization";

export type SelectionChangeDetail = {
selection: Record<string, boolean>;
Expand Down Expand Up @@ -286,6 +287,7 @@ export class CollectionWorkflowList extends TailwindElement {
<div class="grid flex-1 grid-cols-5 items-center">
<div class="col-span-3 md:col-span-1">
<sl-format-date
lang=${getLocale()}
date=${`${crawl.finished}Z`}
month="2-digit"
day="2-digit"
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/features/crawl-workflows/workflow-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { NavigateController } from "@/controllers/navigate";
import type { ListWorkflow } from "@/types/crawler";
import { humanizeSchedule } from "@/utils/cron";
import { srOnly, truncate } from "@/utils/css";
import { getLocale } from "@/utils/localization";
import { numberFormatter } from "@/utils/number";

// postcss-lit-disable-next-line
Expand Down Expand Up @@ -212,7 +213,7 @@ export class WorkflowListItem extends LitElement {

private readonly navigate = new NavigateController(this);

private readonly numberFormatter = numberFormatter(undefined, {
private readonly numberFormatter = numberFormatter(getLocale(), {
notation: "compact",
});

Expand Down Expand Up @@ -275,6 +276,7 @@ export class WorkflowListItem extends LitElement {
${this.safeRender((workflow) => {
if (workflow.lastCrawlTime && workflow.lastCrawlStartTime) {
return html`<sl-format-date
lang=${getLocale()}
date="${workflow.lastRun.toString()}Z"
month="2-digit"
day="2-digit"
Expand Down Expand Up @@ -373,6 +375,7 @@ export class WorkflowListItem extends LitElement {
${this.safeRender(
(workflow) => html`
<sl-format-date
lang=${getLocale()}
date=${workflow.modified.toString()}
month="2-digit"
day="2-digit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { isApiError } from "@/utils/api";
import type { AuthState } from "@/utils/AuthService";
import { finishedCrawlStates, isActive } from "@/utils/crawler";
import { humanizeExecutionSeconds } from "@/utils/executionTimeFormatter";
import { getLocale } from "@/utils/localization";
import { tw } from "@/utils/tailwind";

import "./ui/qa";
Expand Down Expand Up @@ -139,8 +140,7 @@ export class ArchivedItemDetail extends TailwindElement {
return `${this.navigate.orgBasePath}/${path}`;
}

// TODO localize
private readonly numberFormatter = new Intl.NumberFormat();
private readonly numberFormatter = new Intl.NumberFormat(getLocale());
private readonly api = new APIController(this);
private readonly navigate = new NavigateController(this);
private readonly notify = new NotifyController(this);
Expand Down Expand Up @@ -712,6 +712,7 @@ export class ArchivedItemDetail extends TailwindElement {
? html`
<btrix-desc-list-item label=${msg("Uploaded")}>
<sl-format-date
lang=${getLocale()}
date=${`${this.crawl!.finished}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand All @@ -725,6 +726,7 @@ export class ArchivedItemDetail extends TailwindElement {
: html`
<btrix-desc-list-item label=${msg("Start Time")}>
<sl-format-date
lang=${getLocale()}
date=${`${this.crawl!.started}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand All @@ -737,6 +739,7 @@ export class ArchivedItemDetail extends TailwindElement {
<btrix-desc-list-item label=${msg("Finish Time")}>
${this.crawl!.finished
? html`<sl-format-date
lang=${getLocale()}
date=${`${this.crawl!.finished}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/org/archived-item-qa/archived-item-qa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import type { ArchivedItem } from "@/types/crawler";
import type { ArchivedItemQAPage, QARun } from "@/types/qa";
import { type AuthState } from "@/utils/AuthService";
import { finishedCrawlStates, isActive, renderName } from "@/utils/crawler";
import { getLocale } from "@/utils/localization";

const DEFAULT_PAGE_SIZE = 100;

Expand Down Expand Up @@ -701,6 +702,7 @@ export class ArchivedItemQA extends TailwindElement {
this.page,
(page) => html`
<sl-format-date
lang=${getLocale()}
class="font-monostyle text-xs text-neutral-500"
date=${`${page.ts}Z`}
month="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/org/browser-profiles-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { Profile } from "./types";
import { isApiError } from "@/utils/api";
import type { AuthState } from "@/utils/AuthService";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";

/**
* Usage:
Expand Down Expand Up @@ -126,6 +127,7 @@ export class BrowserProfilesDetail extends LiteElement {
${this.profile
? html`
<sl-format-date
lang=${getLocale()}
date=${`${this.profile.created}Z` /** Z for UTC */}
month="2-digit"
day="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/org/browser-profiles-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { APIPaginatedList } from "@/types/api";
import type { Browser } from "@/types/browser";
import type { AuthState } from "@/utils/AuthService";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";

/**
* Usage:
Expand Down Expand Up @@ -140,6 +141,7 @@ export class BrowserProfilesList extends LiteElement {
</btrix-table-cell>
<btrix-table-cell class="whitespace-nowrap">
<sl-format-date
lang=${getLocale()}
date=${`${data.created}Z`}
month="2-digit"
day="2-digit"
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/org/collection-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { Collection } from "@/types/collection";
import type { ArchivedItem, Crawl, CrawlState, Upload } from "@/types/crawler";
import type { AuthState } from "@/utils/AuthService";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";

const ABORT_REASON_THROTTLE = "throttled";
const DESCRIPTION_MAX_HEIGHT_PX = 200;
Expand Down Expand Up @@ -64,8 +65,7 @@ export class CollectionDetail extends LiteElement {
// Use to cancel requests
private getArchivedItemsController: AbortController | null = null;

// TODO localize
private readonly numberFormatter = new Intl.NumberFormat(undefined, {
private readonly numberFormatter = new Intl.NumberFormat(getLocale(), {
notation: "compact",
});

Expand Down Expand Up @@ -496,6 +496,7 @@ export class CollectionDetail extends LiteElement {
msg("Last Updated"),
(col) =>
html`<sl-format-date
lang=${getLocale()}
date=${`${col.modified}Z`}
month="2-digit"
day="2-digit"
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/pages/org/collections-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { UnderlyingFunction } from "@/types/utils";
import { isApiError } from "@/utils/api";
import type { AuthState } from "@/utils/AuthService";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";
import noCollectionsImg from "~assets/images/no-collections-found.webp";

type Collections = APIPaginatedList<Collection>;
Expand Down Expand Up @@ -106,8 +107,7 @@ export class CollectionsList extends LiteElement {
return this.searchByValue.length >= MIN_SEARCH_LENGTH;
}

// TODO localize
private readonly numberFormatter = new Intl.NumberFormat(undefined, {
private readonly numberFormatter = new Intl.NumberFormat(getLocale(), {
notation: "compact",
});

Expand Down Expand Up @@ -544,6 +544,7 @@ export class CollectionsList extends LiteElement {
</btrix-table-cell>
<btrix-table-cell>
<sl-format-date
lang=${getLocale()}
date=${`${col.modified}Z`}
month="2-digit"
day="2-digit"
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/pages/org/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { SelectNewDialogEvent } from ".";
import type { AuthState } from "@/utils/AuthService";
import { humanizeExecutionSeconds } from "@/utils/executionTimeFormatter";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";
import type { OrgData, YearMonth } from "@/utils/orgs";

type Metrics = {
Expand Down Expand Up @@ -786,6 +787,7 @@ export class Dashboard extends LiteElement {
const tableRows = [
html`
<sl-format-date
lang=${getLocale()}
date="${mY}-15T00:00:00.000Z"
time-zone="utc"
month="long"
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/org/workflow-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from "@/utils/crawler";
import { humanizeSchedule } from "@/utils/cron";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";

const SECTIONS = ["crawls", "watch", "settings", "logs"] as const;
type Tab = (typeof SECTIONS)[number];
Expand Down Expand Up @@ -120,11 +121,10 @@ export class WorkflowDetail extends LiteElement {
@state()
private filterBy: Partial<Record<keyof Crawl, string | CrawlState[]>> = {};

// TODO localize
private readonly numberFormatter = new Intl.NumberFormat(undefined, {
private readonly numberFormatter = new Intl.NumberFormat(getLocale(), {
// notation: "compact",
});
private readonly dateFormatter = new Intl.DateTimeFormat(undefined, {
private readonly dateFormatter = new Intl.DateTimeFormat(getLocale(), {
year: "numeric",
month: "numeric",
day: "numeric",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/org/workflow-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import {
} from "@/utils/cron";
import { maxLengthValidator } from "@/utils/form";
import LiteElement, { html } from "@/utils/LiteElement";
import { getLocale } from "@/utils/localization";
import { regexEscape, regexUnescape } from "@/utils/string";

type NewCrawlConfigParams = WorkflowParams & {
Expand Down Expand Up @@ -216,7 +217,7 @@ const getDefaultFormState = (): FormState => ({
function getLocalizedWeekDays() {
const now = new Date();
// TODO accept locale from locale-picker
const { format } = new Intl.DateTimeFormat(undefined, { weekday: "short" });
const { format } = new Intl.DateTimeFormat(getLocale(), { weekday: "short" });
return Array.from({ length: 7 }).map((x, day) =>
format(Date.now() - (now.getDay() - day) * 86400000),
);
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/utils/cron.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { parseCron } from "@cheap-glitch/mi-cron";
import { msg, str } from "@lit/localize";

import { getLocale } from "./localization";
import * as numberUtils from "./number";

export const getNextDate = parseCron.nextDate;
Expand Down Expand Up @@ -91,7 +92,7 @@ export function humanizeSchedule(
intervalMsg = msg(str`Every ${formattedWeekDay}`);
break;
case "monthly": {
const { format } = numberFormatter();
const { format } = numberFormatter(getLocale());
intervalMsg = msg(
str`Monthly on the ${format(days[0], { ordinal: true })}`,
);
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/utils/form.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { msg, str } from "@lit/localize";
import type { SlInput, SlTextarea } from "@shoelace-style/shoelace";

// TODO localize
const numberFormatter = new Intl.NumberFormat(undefined);
import { getLocale } from "./localization";

// TODO listen for localize changes and update
const numberFormatter = new Intl.NumberFormat(getLocale());

export type MaxLengthValidator = {
helpText: string;
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/utils/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export function numberFormatter(
opts?: Intl.NumberFormatOptions,
) {
const numFormat = new Intl.NumberFormat(locales, opts);
// TODO localize
const pluralRules = new Intl.PluralRules("en", { type: "ordinal" });

const suffixes = new Map([
const suffixes = new Map<Intl.LDMLPluralRule, string>([
["one", "st"],
["two", "nd"],
["few", "rd"],
Expand Down

0 comments on commit c5b808b

Please sign in to comment.