Skip to content

Commit 32f4945

Browse files
authored
Format dates with lingui/core (#1730)
* Format dates with lingui/core * Fix date translation interpolation * Incorporate ai feedback
1 parent f15593b commit 32f4945

10 files changed

Lines changed: 119 additions & 35 deletions

File tree

frontend/pnpm-lock.yaml

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/viewer/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
"vitest": "catalog:"
7979
},
8080
"dependencies": {
81-
"@internationalized/date": "^3.8.1",
8281
"@lingui/core": "^5.2.0",
8382
"@microsoft/dotnet-js-interop": "^8.0.0",
8483
"@microsoft/signalr": "^8.0.0",
Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,40 @@
1-
<script lang="ts">
2-
import { DateFormatter } from '@internationalized/date';
1+
<script lang="ts" module>
2+
import {i18n} from '@lingui/core';
33
import {locale} from 'svelte-i18n-lingui';
4+
import {fromStore} from 'svelte/store';
5+
6+
const currentLocale = fromStore(locale);
7+
8+
export function formatDate(value: Date | string | undefined | null, options?: Intl.DateTimeFormatOptions, defaultValue = ''): string {
9+
if (!value) return defaultValue;
10+
void currentLocale.current;//invalidate when the current locale changes
11+
return i18n.date(value, {
12+
dateStyle: 'medium',
13+
timeStyle: 'short',
14+
...options,
15+
});
16+
}
17+
</script>
18+
19+
<script lang="ts">
420
import type {HTMLAttributes} from 'svelte/elements';
521
622
type Props = HTMLAttributes<HTMLSpanElement> & {
7-
date: Date | undefined | null;
23+
date: Date | string | undefined | null;
824
defaultValue?: string;
25+
options?: Intl.DateTimeFormatOptions;
926
};
1027
1128
const {
1229
date,
13-
defaultValue = '',
30+
defaultValue,
31+
options,
1432
...restProps
1533
}: Props = $props();
1634
17-
const formatter = $derived(new DateFormatter($locale, {
18-
dateStyle: 'medium',
19-
timeStyle: 'short',
20-
}));
21-
22-
const formattedDate = $derived(date ? formatter.format(date) : defaultValue);
35+
const formattedDate = $derived.by(() => {
36+
return formatDate(date, options, defaultValue);
37+
});
2338
</script>
2439

2540
<span {...restProps}>{formattedDate}</span>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import {i18n} from '@lingui/core';
2+
import {fromStore} from 'svelte/store';
3+
import {locale} from 'svelte-i18n-lingui';
24

5+
const currentLocale = fromStore(locale);
36
export function formatNumber(value: number | undefined, options?: Intl.NumberFormatOptions, defaultValue = ''): string {
47
if (value === undefined) return defaultValue;
8+
void currentLocale.current;//invalidate when the current locale changes
59

610
return i18n.number(value, options);
711
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import FormatDate from './format-date.svelte';
1+
import FormatDate, {formatDate} from './format-date.svelte';
22
import {formatNumber} from './format-number';
33

44
export {
55
FormatDate,
6+
formatDate,
67
formatNumber,
78
}

frontend/viewer/src/lib/sandbox/Sandbox.svelte

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import * as Dialog from '$lib/components/ui/dialog';
3131
import {T} from 'svelte-i18n-lingui';
3232
import IfOnce from '$lib/components/if-once/if-once.svelte';
33+
import LocalizationPicker from '$lib/i18n/LocalizationPicker.svelte';
34+
import {formatDate, FormatDate, formatNumber} from '$lib/components/ui/format';
35+
import {SvelteDate} from 'svelte/reactivity';
3336
3437
3538
const testingService = tryUseService(DotnetService.TestingService);
@@ -120,6 +123,8 @@
120123
121124
let show = $state(false);
122125
let reseter = $state(0);
126+
127+
let currentDate = new SvelteDate();
123128
</script>
124129
<DialogsProvider/>
125130
<div class="p-6 shadcn-root">
@@ -331,6 +336,22 @@
331336
{/each}
332337
</div>
333338
</div>
339+
<div class="flex flex-col gap-2 border p-4 justify-between">
340+
<div>
341+
<h3>Formatters</h3>
342+
</div>
343+
<div>
344+
<LocalizationPicker/>
345+
</div>
346+
<div class="grid grid-cols-2 gap-x-4 gap-y-2 items-center">
347+
<div class="font-medium">Date component:</div>
348+
<div><FormatDate date={currentDate} options={{timeStyle: 'medium'}}/></div>
349+
<div class="font-medium">Date function:</div>
350+
<div>{formatDate(currentDate, {timeStyle: 'medium'})}</div>
351+
<div class="font-medium">Number function:</div>
352+
<div>{formatNumber(currentDate.getTime())}</div>
353+
</div>
354+
</div>
334355
</div>
335356
</div>
336357
<div id="bottom" class="fixed bottom-0 left-1/2"></div>

frontend/viewer/src/locales/en.json

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"origin": [
1919
[
2020
"src/project/SyncDialog.svelte",
21-
234
21+
233
2222
]
2323
],
2424
"translation": "{0} - FieldWorks"
@@ -1081,7 +1081,24 @@
10811081
237
10821082
]
10831083
],
1084-
"translation": "Last change: "
1084+
"translation": "Last change: ",
1085+
"obsolete": true
1086+
},
1087+
"rZkl7/": {
1088+
"message": "Last change: {0}",
1089+
"placeholders": {},
1090+
"comments": [],
1091+
"origin": [
1092+
[
1093+
"src/project/SyncDialog.svelte",
1094+
196
1095+
],
1096+
[
1097+
"src/project/SyncDialog.svelte",
1098+
236
1099+
]
1100+
],
1101+
"translation": "Last change: {0}"
10851102
},
10861103
"Cb8zzH": {
10871104
"message": "Lexbox logo",
@@ -1858,7 +1875,7 @@
18581875
],
18591876
[
18601877
"src/project/SyncDialog.svelte",
1861-
219
1878+
218
18621879
],
18631880
[
18641881
"src/project/ProjectSidebar.svelte",
@@ -1878,7 +1895,7 @@
18781895
],
18791896
[
18801897
"src/project/SyncDialog.svelte",
1881-
217
1898+
216
18821899
]
18831900
],
18841901
"translation": "Synchronizing..."

frontend/viewer/src/locales/es.json

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"origin": [
1919
[
2020
"src/project/SyncDialog.svelte",
21-
234
21+
233
2222
]
2323
],
2424
"translation": ""
@@ -1081,6 +1081,23 @@
10811081
237
10821082
]
10831083
],
1084+
"translation": "",
1085+
"obsolete": true
1086+
},
1087+
"rZkl7/": {
1088+
"message": "Last change: {0}",
1089+
"placeholders": {},
1090+
"comments": [],
1091+
"origin": [
1092+
[
1093+
"src/project/SyncDialog.svelte",
1094+
196
1095+
],
1096+
[
1097+
"src/project/SyncDialog.svelte",
1098+
236
1099+
]
1100+
],
10841101
"translation": ""
10851102
},
10861103
"Cb8zzH": {
@@ -1858,7 +1875,7 @@
18581875
],
18591876
[
18601877
"src/project/SyncDialog.svelte",
1861-
219
1878+
218
18621879
],
18631880
[
18641881
"src/project/ProjectSidebar.svelte",
@@ -1878,7 +1895,7 @@
18781895
],
18791896
[
18801897
"src/project/SyncDialog.svelte",
1881-
217
1898+
216
18821899
]
18831900
],
18841901
"translation": ""

frontend/viewer/src/locales/fr.json

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"origin": [
1919
[
2020
"src/project/SyncDialog.svelte",
21-
234
21+
233
2222
]
2323
],
2424
"translation": ""
@@ -1081,6 +1081,23 @@
10811081
237
10821082
]
10831083
],
1084+
"translation": "",
1085+
"obsolete": true
1086+
},
1087+
"rZkl7/": {
1088+
"message": "Last change: {0}",
1089+
"placeholders": {},
1090+
"comments": [],
1091+
"origin": [
1092+
[
1093+
"src/project/SyncDialog.svelte",
1094+
196
1095+
],
1096+
[
1097+
"src/project/SyncDialog.svelte",
1098+
236
1099+
]
1100+
],
10841101
"translation": ""
10851102
},
10861103
"Cb8zzH": {
@@ -1858,7 +1875,7 @@
18581875
],
18591876
[
18601877
"src/project/SyncDialog.svelte",
1861-
219
1878+
218
18621879
],
18631880
[
18641881
"src/project/ProjectSidebar.svelte",
@@ -1878,7 +1895,7 @@
18781895
],
18791896
[
18801897
"src/project/SyncDialog.svelte",
1881-
217
1898+
216
18821899
]
18831900
],
18841901
"translation": ""

frontend/viewer/src/project/SyncDialog.svelte

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import { QueryParamStateBool } from '$lib/utils/url.svelte';
1111
import Loading from '$lib/components/Loading.svelte';
1212
import { useSyncStatusService } from '$lib/services/sync-status-service';
13-
import { FormatDate } from '$lib/components/ui/format';
13+
import { formatDate } from '$lib/components/ui/format';
1414
import { watch } from 'runed';
1515
import { fade } from 'svelte/transition';
1616
import { delay } from '$lib/utils/time';
@@ -191,12 +191,9 @@
191191
<Icon icon="i-mdi-cloud-outline" />
192192
{$t`${serverName} - FieldWorks Lite`}
193193
</span>
194-
{#if lastLocalSyncDate}
195-
<span class="text-foreground/80">
196-
{$t`Last change: `}
197-
<FormatDate date={lastLocalSyncDate} />
198-
</span>
199-
{/if}
194+
<span class="text-foreground/80">
195+
{$t`Last change: ${formatDate(lastLocalSyncDate)}`}
196+
</span>
200197
</div>
201198
<div class="text-center content-center">
202199
{flexToLbCount}
@@ -234,8 +231,7 @@
234231
{$t`${serverName} - FieldWorks`}
235232
</span>
236233
<span class="text-foreground/80">
237-
{$t`Last change: `}
238-
<FormatDate date={lastFlexSyncDate} />
234+
{$t`Last change: ${formatDate(lastFlexSyncDate)}`}
239235
</span>
240236
</div>
241237
</div>

0 commit comments

Comments
 (0)