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…
	
	Add table
		Add a link
		
	
		Reference in a new issue