diff --git a/locales/index.d.ts b/locales/index.d.ts index 96d6c890a8..4142195574 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5605,6 +5605,10 @@ export interface Locale extends ILocale { * 技術的なお問い合わせの際に、以下の情報を併記すると問題の解決に役立つことがあります。 */ "deviceInfoDescription": string; + /** + * 入力が不正なためカレンダーを表示できません + */ + "calendarInvalidDateError": string; "_compression": { "_quality": { /** @@ -9545,6 +9549,36 @@ export interface Locale extends ILocale { */ "saturday": string; }; + "_weekdayShort": { + /** + * 日 + */ + "sunday": string; + /** + * 月 + */ + "monday": string; + /** + * 火 + */ + "tuesday": string; + /** + * 水 + */ + "wednesday": string; + /** + * 木 + */ + "thursday": string; + /** + * 金 + */ + "friday": string; + /** + * 土 + */ + "saturday": string; + }; "_widgets": { /** * プロフィール diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 8e935b5d9e..9cbfc62115 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1396,6 +1396,7 @@ scheduled: "予約" widgets: "ウィジェット" deviceInfo: "デバイス情報" deviceInfoDescription: "技術的なお問い合わせの際に、以下の情報を併記すると問題の解決に役立つことがあります。" +calendarInvalidDateError: "入力が不正なためカレンダーを表示できません" _compression: _quality: @@ -2509,6 +2510,15 @@ _weekday: friday: "金曜日" saturday: "土曜日" +_weekdayShort: + sunday: "日" + monday: "月" + tuesday: "火" + wednesday: "水" + thursday: "木" + friday: "金" + saturday: "土" + _widgets: profile: "プロフィール" instanceInfo: "サーバー情報" diff --git a/packages/frontend-shared/js/intl-const.ts b/packages/frontend-shared/js/intl-const.ts index 33b65b6e9b..58670e9533 100644 --- a/packages/frontend-shared/js/intl-const.ts +++ b/packages/frontend-shared/js/intl-const.ts @@ -9,6 +9,7 @@ import { lang } from '@@/js/config.js'; export const versatileLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP'); let _dateTimeFormat: Intl.DateTimeFormat; + try { _dateTimeFormat = new Intl.DateTimeFormat(versatileLang, { year: 'numeric', @@ -32,6 +33,7 @@ try { second: 'numeric', }); } + export const dateTimeFormat = _dateTimeFormat; export const timeZone = dateTimeFormat.resolvedOptions().timeZone; diff --git a/packages/frontend-shared/js/intl-utils.ts b/packages/frontend-shared/js/intl-utils.ts new file mode 100644 index 0000000000..6770295daf --- /dev/null +++ b/packages/frontend-shared/js/intl-utils.ts @@ -0,0 +1,25 @@ + +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { versatileLang } from '@@/js/intl-const.js'; + +export function createDateTimeFormatter(options: Intl.DateTimeFormatOptions) { + try { + return new Intl.DateTimeFormat(versatileLang, options); + } catch { + // Fallback to en-US + return new Intl.DateTimeFormat('en-US', options); + } +} + +export function createNumberFormatter(options?: Intl.NumberFormatOptions) { + try { + return new Intl.NumberFormat(versatileLang, options); + } catch { + // Fallback to en-US + return new Intl.NumberFormat('en-US', options); + } +} diff --git a/packages/frontend/src/components/MkDateTimeInput.dialog.vue b/packages/frontend/src/components/MkDateTimeInput.dialog.vue new file mode 100644 index 0000000000..537660c27c --- /dev/null +++ b/packages/frontend/src/components/MkDateTimeInput.dialog.vue @@ -0,0 +1,520 @@ + + + + + + + diff --git a/packages/frontend/src/components/MkDateTimeInput.vue b/packages/frontend/src/components/MkDateTimeInput.vue new file mode 100644 index 0000000000..cc84c378d9 --- /dev/null +++ b/packages/frontend/src/components/MkDateTimeInput.vue @@ -0,0 +1,361 @@ + + + + + + + + + diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index 89325dee63..7c8d641298 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -46,10 +46,10 @@ SPDX-License-Identifier: AGPL-3.0-only - + - + @@ -185,6 +185,8 @@ import { store } from '@/store.js'; import MkInfo from '@/components/MkInfo.vue'; import MkTextarea from '@/components/MkTextarea.vue'; import { genId } from '@/utility/id.js'; +import MkDateTimeInput from '@/components/MkDateTimeInput.vue'; +import type { MkDateTimeInputDateObject } from '@/components/MkDateTimeInput.vue'; const $i = ensureSignin(); @@ -207,6 +209,26 @@ const profile = reactive({ isCat: $i.isCat ?? false, }); +const birthday = computed({ + get: () => { + if (!profile.birthday) return null; + const [year, month, date] = (profile.birthday ?? '').split('-').map(v => parseInt(v, 10)); + if (Number.isNaN(year) || Number.isNaN(month) || Number.isNaN(date)) { + return null; + } + return { year, month, date }; + }, + set: (value) => { + if (value === null) { + profile.birthday = null; + } else { + const monthStr = value.month.toString().padStart(2, '0'); + const dayStr = value.date.toString().padStart(2, '0'); + profile.birthday = `${value.year}-${monthStr}-${dayStr}`; + } + }, +}); + watch(() => profile, () => { save(); }, { diff --git a/packages/frontend/src/utility/intl-const.ts b/packages/frontend/src/utility/intl-const.ts deleted file mode 100644 index 385f59ec39..0000000000 --- a/packages/frontend/src/utility/intl-const.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { lang } from '@@/js/config.js'; - -export const versatileLang = (lang ?? 'ja-JP').replace('ja-KS', 'ja-JP'); - -let _dateTimeFormat: Intl.DateTimeFormat; -try { - _dateTimeFormat = new Intl.DateTimeFormat(versatileLang, { - year: 'numeric', - month: 'numeric', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }); -} catch (err) { - console.warn(err); - if (_DEV_) console.log('[Intl] Fallback to en-US'); - - // Fallback to en-US - _dateTimeFormat = new Intl.DateTimeFormat('en-US', { - year: 'numeric', - month: 'numeric', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }); -} -export const dateTimeFormat = _dateTimeFormat; - -export const timeZone = dateTimeFormat.resolvedOptions().timeZone; - -export const hemisphere = /^(australia|pacific|antarctica|indian)\//i.test(timeZone) ? 'S' : 'N'; - -let _numberFormat: Intl.NumberFormat; -try { - _numberFormat = new Intl.NumberFormat(versatileLang); -} catch (err) { - console.warn(err); - if (_DEV_) console.log('[Intl] Fallback to en-US'); - - // Fallback to en-US - _numberFormat = new Intl.NumberFormat('en-US'); -} -export const numberFormat = _numberFormat;