use Intl.DateTimeFormat and Intl.NumberFormat instead of toLocaleString (#9444)
This commit is contained in:
parent
0222165bd9
commit
c3a36698e5
14 changed files with 42 additions and 18 deletions
|
@ -10,7 +10,7 @@
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkKeyValue class="_formBlock">
|
<MkKeyValue class="_formBlock">
|
||||||
<template #key>{{ i18n.ts.registeredDate }}</template>
|
<template #key>{{ i18n.ts.registeredDate }}</template>
|
||||||
<template #value>{{ new Date(report.targetUser.createdAt).toLocaleString() }} (<MkTime :time="report.targetUser.createdAt"/>)</template>
|
<template #value>{{ dateString(report.targetUser.createdAt) }} (<MkTime :time="report.targetUser.createdAt"/>)</template>
|
||||||
</MkKeyValue>
|
</MkKeyValue>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
|
@ -42,6 +42,7 @@ import MkKeyValue from '@/components/MkKeyValue.vue';
|
||||||
import { acct, userPage } from '@/filters/user';
|
import { acct, userPage } from '@/filters/user';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
report: any;
|
report: any;
|
||||||
|
|
|
@ -40,6 +40,7 @@ import { defaultStore } from '@/store';
|
||||||
import { useChartTooltip } from '@/scripts/use-chart-tooltip';
|
import { useChartTooltip } from '@/scripts/use-chart-tooltip';
|
||||||
import { chartVLine } from '@/scripts/chart-vline';
|
import { chartVLine } from '@/scripts/chart-vline';
|
||||||
import { alpha } from '@/scripts/color';
|
import { alpha } from '@/scripts/color';
|
||||||
|
import date from '@/filters/date';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
src: {
|
src: {
|
||||||
|
@ -171,7 +172,7 @@ const render = () => {
|
||||||
chartInstance = new Chart(chartEl.value, {
|
chartInstance = new Chart(chartEl.value, {
|
||||||
type: props.bar ? 'bar' : 'line',
|
type: props.bar ? 'bar' : 'line',
|
||||||
data: {
|
data: {
|
||||||
labels: new Array(props.limit).fill(0).map((_, i) => getDate(i).toLocaleString()).slice().reverse(),
|
labels: new Array(props.limit).fill(0).map((_, i) => date(getDate(i))).slice().reverse(),
|
||||||
datasets: chartData.series.map((x, i) => ({
|
datasets: chartData.series.map((x, i) => ({
|
||||||
parsing: false,
|
parsing: false,
|
||||||
label: x.name,
|
label: x.name,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<MkA
|
<MkA
|
||||||
v-for="file in items"
|
v-for="file in items"
|
||||||
:key="file.id"
|
:key="file.id"
|
||||||
v-tooltip.mfm="`${file.type}\n${bytes(file.size)}\n${new Date(file.createdAt).toLocaleString()}\nby ${file.user ? '@' + Acct.toString(file.user) : 'system'}`"
|
v-tooltip.mfm="`${file.type}\n${bytes(file.size)}\n${dateString(file.createdAt)}\nby ${file.user ? '@' + Acct.toString(file.user) : 'system'}`"
|
||||||
:to="`/admin/file/${file.id}`"
|
:to="`/admin/file/${file.id}`"
|
||||||
class="file _button"
|
class="file _button"
|
||||||
>
|
>
|
||||||
|
@ -39,6 +39,7 @@ import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
|
||||||
import bytes from '@/filters/bytes';
|
import bytes from '@/filters/bytes';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
pagination: any;
|
pagination: any;
|
||||||
|
|
|
@ -45,11 +45,12 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineAsyncComponent, onMounted, onUnmounted } from 'vue';
|
import { defineAsyncComponent, onMounted, onUnmounted } from 'vue';
|
||||||
import { url as local, lang } from '@/config';
|
import { url as local } from '@/config';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { deviceKind } from '@/scripts/device-kind';
|
import { deviceKind } from '@/scripts/device-kind';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
import { versatileLang } from '@/scripts/intl-const';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -95,11 +96,9 @@ if (requestUrl.hostname === 'music.youtube.com' && requestUrl.pathname.match('^/
|
||||||
requestUrl.hostname = 'www.youtube.com';
|
requestUrl.hostname = 'www.youtube.com';
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP');
|
|
||||||
|
|
||||||
requestUrl.hash = '';
|
requestUrl.hash = '';
|
||||||
|
|
||||||
window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${requestLang}`).then(res => {
|
window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLang}`).then(res => {
|
||||||
res.json().then(info => {
|
res.json().then(info => {
|
||||||
if (info.url == null) {
|
if (info.url == null) {
|
||||||
unknownUrl = true;
|
unknownUrl = true;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import XWindow from '@/components/MkWindow.vue';
|
import XWindow from '@/components/MkWindow.vue';
|
||||||
import { lang } from '@/config';
|
import { versatileLang } from '@/scripts/intl-const';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -35,11 +35,9 @@ let player = $ref({
|
||||||
height: null,
|
height: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const requestLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP');
|
|
||||||
|
|
||||||
const ytFetch = (): void => {
|
const ytFetch = (): void => {
|
||||||
fetching = true;
|
fetching = true;
|
||||||
window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${requestLang}`).then(res => {
|
window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLang}`).then(res => {
|
||||||
res.json().then(info => {
|
res.json().then(info => {
|
||||||
if (info.url == null) return;
|
if (info.url == null) return;
|
||||||
title = info.title;
|
title = info.title;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onUnmounted } from 'vue';
|
import { onUnmounted } from 'vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { dateTimeFormat } from '@/scripts/intl-const';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
time: Date | string;
|
time: Date | string;
|
||||||
|
@ -18,7 +19,7 @@ const props = withDefaults(defineProps<{
|
||||||
});
|
});
|
||||||
|
|
||||||
const _time = typeof props.time === 'string' ? new Date(props.time) : props.time;
|
const _time = typeof props.time === 'string' ? new Date(props.time) : props.time;
|
||||||
const absolute = _time.toLocaleString();
|
const absolute = dateTimeFormat.format(_time);
|
||||||
|
|
||||||
let now = $shallowRef(new Date());
|
let now = $shallowRef(new Date());
|
||||||
const relative = $computed(() => {
|
const relative = $computed(() => {
|
||||||
|
|
4
packages/frontend/src/filters/date.ts
Normal file
4
packages/frontend/src/filters/date.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { dateTimeFormat } from '@/scripts/intl-const';
|
||||||
|
|
||||||
|
export default (d: Date | number | undefined) => dateTimeFormat.format(d);
|
||||||
|
export const dateString = (d: string) => dateTimeFormat.format(new Date(d));
|
|
@ -1 +1,3 @@
|
||||||
export default n => n == null ? 'N/A' : n.toLocaleString();
|
import { numberFormat } from '@/scripts/intl-const';
|
||||||
|
|
||||||
|
export default n => n == null ? 'N/A' : numberFormat.format(n);
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
<MkPagination v-slot="{items}" ref="instances" :key="host + state" :pagination="pagination">
|
||||||
<div class="dqokceoi">
|
<div class="dqokceoi">
|
||||||
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Last communicated: ${new Date(instance.lastCommunicatedAt).toLocaleString()}\nStatus: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
<MkA v-for="instance in items" :key="instance.id" v-tooltip.mfm="`Last communicated: ${dateString(instance.lastCommunicatedAt)}\nStatus: ${getStatus(instance)}`" class="instance" :to="`/instance-info/${instance.host}`">
|
||||||
<MkInstanceCardMini :instance="instance"/>
|
<MkInstanceCardMini :instance="instance"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,6 +56,7 @@ import MkInstanceCardMini from '@/components/MkInstanceCardMini.vue';
|
||||||
import FormSplit from '@/components/form/split.vue';
|
import FormSplit from '@/components/form/split.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
let host = $ref('');
|
let host = $ref('');
|
||||||
let state = $ref('federating');
|
let state = $ref('federating');
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkPagination v-slot="{items}" ref="paginationComponent" :pagination="pagination" class="users">
|
<MkPagination v-slot="{items}" ref="paginationComponent" :pagination="pagination" class="users">
|
||||||
<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${new Date(user.updatedAt).toLocaleString()}`" class="user" :to="`/user-info/${user.id}`">
|
<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/user-info/${user.id}`">
|
||||||
<MkUserCardMini :user="user"/>
|
<MkUserCardMini :user="user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
|
@ -63,6 +63,7 @@ import { lookupUser } from '@/scripts/lookup-user';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
let paginationComponent = $ref<InstanceType<typeof MkPagination>>();
|
let paginationComponent = $ref<InstanceType<typeof MkPagination>>();
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="tab === 'users'" class="_formRoot">
|
<div v-else-if="tab === 'users'" class="_formRoot">
|
||||||
<MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
|
<MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
|
||||||
<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${new Date(user.updatedAt).toLocaleString()}`" class="user" :to="`/user-info/${user.id}`">
|
<MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/user-info/${user.id}`">
|
||||||
<MkUserCardMini :user="user"/>
|
<MkUserCardMini :user="user"/>
|
||||||
</MkA>
|
</MkA>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
|
@ -135,6 +135,7 @@ import { i18n } from '@/i18n';
|
||||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy';
|
import { getProxiedImageUrlNullable } from '@/scripts/media-proxy';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
host: string;
|
host: string;
|
||||||
|
|
|
@ -51,6 +51,7 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
noteId: string;
|
noteId: string;
|
||||||
|
@ -127,7 +128,7 @@ const headerTabs = $computed(() => []);
|
||||||
|
|
||||||
definePageMetadata(computed(() => note ? {
|
definePageMetadata(computed(() => note ? {
|
||||||
title: i18n.ts.note,
|
title: i18n.ts.note,
|
||||||
subtitle: new Date(note.createdAt).toLocaleString(),
|
subtitle: dateString(note.createdAt),
|
||||||
avatar: note.user,
|
avatar: note.user,
|
||||||
path: `/notes/${note.id}`,
|
path: `/notes/${note.id}`,
|
||||||
share: {
|
share: {
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
</dl>
|
</dl>
|
||||||
<dl class="field">
|
<dl class="field">
|
||||||
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
|
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
|
||||||
<dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd>
|
<dd class="value">{{ dateString(user.createdAt) }} (<MkTime :time="user.createdAt"/>)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="user.fields.length > 0" class="fields">
|
<div v-if="user.fields.length > 0" class="fields">
|
||||||
|
@ -127,6 +127,7 @@ import * as os from '@/os';
|
||||||
import { useRouter } from '@/router';
|
import { useRouter } from '@/router';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { $i } from '@/account';
|
import { $i } from '@/account';
|
||||||
|
import { dateString } from '@/filters/date';
|
||||||
|
|
||||||
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
|
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
|
||||||
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
|
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
|
||||||
|
|
12
packages/frontend/src/scripts/intl-const.ts
Normal file
12
packages/frontend/src/scripts/intl-const.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { lang } from '@/config';
|
||||||
|
|
||||||
|
export const versatileLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP');
|
||||||
|
export const dateTimeFormat = new Intl.DateTimeFormat(versatileLang, {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'numeric',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
second: 'numeric',
|
||||||
|
});
|
||||||
|
export const numberFormat = new Intl.NumberFormat(versatileLang);
|
Loading…
Reference in a new issue