diff --git a/src/core/datetime.ts b/src/core/datetime.ts index c22bddd5..f45a8bee 100644 --- a/src/core/datetime.ts +++ b/src/core/datetime.ts @@ -499,7 +499,3 @@ export class DateRange implements TypeAndName { return dateRange?.isBillingCycle || false; } } - -export type AllDateTimeFormatMap = Record | Record | Record | Record; -export type AllDateTimeFormatArray = LongDateFormat[] | ShortDateFormat[] | LongTimeFormat[] | ShortTimeFormat[]; -export type AllDateTimeFormatType = LongDateFormat | ShortDateFormat | LongTimeFormat | ShortTimeFormat; diff --git a/src/global.d.ts b/src/global.d.ts index 5a74c142..531d052f 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -3,7 +3,14 @@ declare const __EZBOOKKEEPING_VERSION__: string; declare const __EZBOOKKEEPING_BUILD_UNIX_TIME__: string; declare const __EZBOOKKEEPING_BUILD_COMMIT_HASH__: string; declare const __EZBOOKKEEPING_LICENSE__: string; -declare const __EZBOOKKEEPING_THIRD_PARTY_LICENSES__: string[]; +declare const __EZBOOKKEEPING_THIRD_PARTY_LICENSES__: LicenseInfo[]; + +declare interface LicenseInfo { + name: string; + copyright?: string; + url?: string; + licenseUrl?: string; +} interface Window { EZBOOKKEEPING_SERVER_SETTINGS?: { diff --git a/src/lib/datetime.ts b/src/lib/datetime.ts index 8a54b316..5e1d1a2f 100644 --- a/src/lib/datetime.ts +++ b/src/lib/datetime.ts @@ -11,9 +11,8 @@ import { type TimeDifference, type RecentMonthDateRange, type LocalizedRecentMonthDateRange, - type AllDateTimeFormatMap, - type AllDateTimeFormatArray, - type AllDateTimeFormatType, + type DateFormat, + type TimeFormat, YearQuarterUnixTime, YearMonthUnixTime, Month, @@ -477,11 +476,11 @@ export function getAllMonthsStartAndEndUnixTimes(startYearMonth: YearMonth | str return allYearMonthTimes; } -export function getDateTimeFormatType(allFormatMap: AllDateTimeFormatMap, allFormatArray: AllDateTimeFormatArray, localeDefaultFormatTypeName: string, systemDefaultFormatType: AllDateTimeFormatType, formatTypeValue: number): AllDateTimeFormatType { +export function getDateTimeFormatType(allFormatMap: Record, allFormatArray: T[], formatTypeValue: number, languageDefaultTypeName: string, systemDefaultFormatType: T): T { if (formatTypeValue > LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE && allFormatArray[formatTypeValue - 1] && allFormatArray[formatTypeValue - 1].key) { return allFormatArray[formatTypeValue - 1]; - } else if (formatTypeValue === LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE && allFormatMap[localeDefaultFormatTypeName] && allFormatMap[localeDefaultFormatTypeName].key) { - return allFormatMap[localeDefaultFormatTypeName]; + } else if (formatTypeValue === LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE && allFormatMap[languageDefaultTypeName] && allFormatMap[languageDefaultTypeName].key) { + return allFormatMap[languageDefaultTypeName]; } else { return systemDefaultFormatType; } diff --git a/src/lib/licenses.ts b/src/lib/licenses.ts index 40dc8b42..79302d21 100644 --- a/src/lib/licenses.ts +++ b/src/lib/licenses.ts @@ -2,6 +2,6 @@ export function getLicense(): string { return __EZBOOKKEEPING_LICENSE__; } -export function getThirdPartyLicenses(): string[] { +export function getThirdPartyLicenses(): LicenseInfo[] { return __EZBOOKKEEPING_THIRD_PARTY_LICENSES__ || []; } diff --git a/src/locales/helper.js b/src/locales/helper.js index d1506676..0ad68a6d 100644 --- a/src/locales/helper.js +++ b/src/locales/helper.js @@ -456,13 +456,13 @@ function getI18nShortMonthDayFormat(translateFn, formatTypeValue) { function isLongDateMonthAfterYear(translateFn, formatTypeValue) { const defaultLongDateFormatTypeName = translateFn('default.longDateFormat'); - const type = getDateTimeFormatType(LongDateFormat.all(), LongDateFormat.values(), defaultLongDateFormatTypeName, LongDateFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(LongDateFormat.all(), LongDateFormat.values(), formatTypeValue, defaultLongDateFormatTypeName, LongDateFormat.Default); return type.isMonthAfterYear; } function isShortDateMonthAfterYear(translateFn, formatTypeValue) { const defaultShortDateFormatTypeName = translateFn('default.shortDateFormat'); - const type = getDateTimeFormatType(ShortDateFormat.all(), ShortDateFormat.values(), defaultShortDateFormatTypeName, ShortDateFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(ShortDateFormat.all(), ShortDateFormat.values(), formatTypeValue, defaultShortDateFormatTypeName, ShortDateFormat.Default); return type.isMonthAfterYear; } @@ -489,25 +489,25 @@ function formatYearQuarter(translateFn, year, quarter) { function isLongTime24HourFormat(translateFn, formatTypeValue) { const defaultLongTimeFormatTypeName = translateFn('default.longTimeFormat'); - const type = getDateTimeFormatType(LongTimeFormat.all(), LongTimeFormat.values(), defaultLongTimeFormatTypeName, LongTimeFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(LongTimeFormat.all(), LongTimeFormat.values(), formatTypeValue, defaultLongTimeFormatTypeName, LongTimeFormat.Default); return type.is24HourFormat; } function isLongTimeMeridiemIndicatorFirst(translateFn, formatTypeValue) { const defaultLongTimeFormatTypeName = translateFn('default.longTimeFormat'); - const type = getDateTimeFormatType(LongTimeFormat.all(), LongTimeFormat.values(), defaultLongTimeFormatTypeName, LongTimeFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(LongTimeFormat.all(), LongTimeFormat.values(), formatTypeValue, defaultLongTimeFormatTypeName, LongTimeFormat.Default); return type.isMeridiemIndicatorFirst; } function isShortTime24HourFormat(translateFn, formatTypeValue) { const defaultShortTimeFormatTypeName = translateFn('default.shortTimeFormat'); - const type = getDateTimeFormatType(ShortTimeFormat.all(), ShortTimeFormat.values(), defaultShortTimeFormatTypeName, ShortTimeFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(ShortTimeFormat.all(), ShortTimeFormat.values(), formatTypeValue, defaultShortTimeFormatTypeName, ShortTimeFormat.Default); return type.is24HourFormat; } function isShortTimeMeridiemIndicatorFirst(translateFn, formatTypeValue) { const defaultShortTimeFormatTypeName = translateFn('default.shortTimeFormat'); - const type = getDateTimeFormatType(ShortTimeFormat.all(), ShortTimeFormat.values(), defaultShortTimeFormatTypeName, ShortTimeFormat.Default, formatTypeValue); + const type = getDateTimeFormatType(ShortTimeFormat.all(), ShortTimeFormat.values(), formatTypeValue, defaultShortTimeFormatTypeName, ShortTimeFormat.Default); return type.isMeridiemIndicatorFirst; } @@ -537,8 +537,7 @@ function getDateTimeFormats(translateFn, allFormatMap, allFormatArray, localeFor } function getDateTimeFormat(translateFn, allFormatMap, allFormatArray, localeFormatPathPrefix, localeDefaultFormatTypeName, systemDefaultFormatType, formatTypeValue) { - const type = getDateTimeFormatType(allFormatMap, allFormatArray, - localeDefaultFormatTypeName, systemDefaultFormatType, formatTypeValue); + const type = getDateTimeFormatType(allFormatMap, allFormatArray, formatTypeValue, localeDefaultFormatTypeName, systemDefaultFormatType); return translateFn(`${localeFormatPathPrefix}.${type.key}`); } diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index 2ff3d4ac..2f882b7e 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -5,9 +5,15 @@ import { type LanguageInfo, allLanguages, DEFAULT_LANGUAGE } from '@/locales/ind import { type LocalizedMeridiemIndicator, + type DateFormat, + type TimeFormat, Month, WeekDay, - MeridiemIndicator + MeridiemIndicator, + LongDateFormat, + ShortDateFormat, + LongTimeFormat, + ShortTimeFormat } from '@/core/datetime.ts'; import type { LocaleDefaultSettings } from '@/core/setting.ts'; @@ -22,12 +28,16 @@ import { import { isPM, - getTimezoneOffset + formatUnixTime, + getTimezoneOffset, + getDateTimeFormatType } from '@/lib/datetime.ts'; import logger from '@/lib/logger.ts'; import services from '@/lib/services.ts'; +import { useUserStore } from '@/stores/user.ts'; + export interface LocalizedErrorParameter { key: string; localized: boolean; @@ -65,6 +75,8 @@ export function getI18nOptions(): object { export function useI18n() { const { t, locale } = useVueI18n(); + const userStore = useUserStore(); + // private functions function getLanguageInfo(languageKey: string): LanguageInfo | undefined { return allLanguages[languageKey]; @@ -223,6 +235,51 @@ export function useI18n() { return ret; } + function getLocalizedDateTimeFormat(type: string, allFormatMap: Record, allFormatArray: T[], formatTypeValue: number, languageDefaultTypeNameKey: string, systemDefaultFormatType: T): string { + const formatType = getDateTimeFormatType(allFormatMap, allFormatArray, formatTypeValue, t(`default.${languageDefaultTypeNameKey}`), systemDefaultFormatType); + return t(`format.${type}.${formatType.key}`); + } + + function getLocalizedLongDateFormat(): string { + return getLocalizedDateTimeFormat('longDate', LongDateFormat.all(), LongDateFormat.values(), userStore.currentUserLongDateFormat, 'longDateFormat', LongDateFormat.Default); + } + + function getLocalizedShortDateFormat(): string { + return getLocalizedDateTimeFormat('shortDate', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); + } + + function getLocalizedLongYearFormat(): string { + return getLocalizedDateTimeFormat('longYear', LongDateFormat.all(), LongDateFormat.values(), userStore.currentUserLongDateFormat, 'longDateFormat', LongDateFormat.Default); + } + + function getLocalizedShortYearFormat(): string { + return getLocalizedDateTimeFormat('shortYear', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); + } + + function getLocalizedLongYearMonthFormat(): string { + return getLocalizedDateTimeFormat('longYearMonth', LongDateFormat.all(), LongDateFormat.values(), userStore.currentUserLongDateFormat, 'longDateFormat', LongDateFormat.Default); + } + + function getLocalizedShortYearMonthFormat(): string { + return getLocalizedDateTimeFormat('shortYearMonth', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); + } + + function getLocalizedLongMonthDayFormat(): string { + return getLocalizedDateTimeFormat('longMonthDay', LongDateFormat.all(), LongDateFormat.values(), userStore.currentUserLongDateFormat, 'longDateFormat', LongDateFormat.Default); + } + + function getLocalizedShortMonthDayFormat(): string { + return getLocalizedDateTimeFormat('shortMonthDay', ShortDateFormat.all(), ShortDateFormat.values(), userStore.currentUserShortDateFormat, 'shortDateFormat', ShortDateFormat.Default); + } + + function getLocalizedLongTimeFormat(): string { + return getLocalizedDateTimeFormat('longTime', LongTimeFormat.all(), LongTimeFormat.values(), userStore.currentUserLongTimeFormat, 'longTimeFormat', LongTimeFormat.Default); + } + + function getLocalizedShortTimeFormat(): string { + return getLocalizedDateTimeFormat('shortTime', ShortTimeFormat.all(), ShortTimeFormat.values(), userStore.currentUserShortTimeFormat, 'shortTimeFormat', ShortTimeFormat.Default); + } + // public functions function translateIf(text: string, isTranslate: boolean): string { if (isTranslate) { @@ -318,6 +375,17 @@ export function useI18n() { return getAllWeekdayNames('min'); } + function formatYearQuarter(year: number, quarter: number): string { + if (1 <= quarter && quarter <= 4) { + return t('format.yearQuarter.q' + quarter, { + year: year, + quarter: quarter + }); + } else { + return ''; + } + } + function setLanguage(languageKey: string | null, force?: boolean): LocaleDefaultSettings | null { if (!languageKey) { languageKey = getDefaultLanguage(); @@ -413,6 +481,19 @@ export function useI18n() { getAllLongWeekdayNames, getAllShortWeekdayNames, getAllMinWeekdayNames, + formatUnixTimeToLongDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat() + ' ' + getLocalizedLongTimeFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortDateTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat() + ' ' + getLocalizedShortTimeFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongDateFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortDate: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortDateFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortYear: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongYearMonthFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortYearMonth: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortYearMonthFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongMonthDayFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortMonthDay: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortMonthDayFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToLongTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedLongTimeFormat(), utcOffset, currentUtcOffset), + formatUnixTimeToShortTime: (unixTime: number, utcOffset?: number, currentUtcOffset?: number) => formatUnixTime(unixTime, getLocalizedShortTimeFormat(), utcOffset, currentUtcOffset), + formatYearQuarter, setLanguage, setTimeZone, initLocale diff --git a/src/views/base/AboutPage.ts b/src/views/base/AboutPage.ts new file mode 100644 index 00000000..e86fe48a --- /dev/null +++ b/src/views/base/AboutPage.ts @@ -0,0 +1,50 @@ +import { computed } from 'vue'; + +import { useI18n } from '@/locales/helpers.ts'; + +import { useExchangeRatesStore } from '@/stores/exchangeRates.ts'; + +import type { LatestExchangeRateResponse } from '@/models/exchange_rate.ts'; + +import { getMapProvider } from '@/lib/server_settings.ts'; +import { getMapWebsite } from '@/lib/map/index.ts'; +import { getLicense, getThirdPartyLicenses } from '@/lib/licenses.ts'; +import { getVersion, getBuildTime } from '@/lib/version.ts'; + +export function useAboutPage() { + const { tt, formatUnixTimeToLongDateTime } = useI18n(); + + const exchangeRatesStore = useExchangeRatesStore(); + + const version = `v${getVersion()}`; + + const buildTime = computed(() => { + const time = getBuildTime(); + + if (!time) { + return time; + } + + return formatUnixTimeToLongDateTime(parseInt(time)); + }); + const exchangeRatesData = computed(() => exchangeRatesStore.latestExchangeRates.data); + const mapProviderName = computed(() => { + const provider = getMapProvider(); + return provider ? tt(`mapprovider.${provider}`) : ''; + }); + const mapProviderWebsite = computed(() => getMapWebsite()); + const licenseLines = computed(() => getLicense().replaceAll(/\r/g, '').split('\n')); + const thirdPartyLicenses = computed(() => getThirdPartyLicenses()); + + return { + // constants + version, + // computed states + buildTime, + exchangeRatesData, + mapProviderName, + mapProviderWebsite, + licenseLines, + thirdPartyLicenses + }; +} diff --git a/src/views/desktop/AboutPage.vue b/src/views/desktop/AboutPage.vue index 9524c5fb..ca4ceef0 100644 --- a/src/views/desktop/AboutPage.vue +++ b/src/views/desktop/AboutPage.vue @@ -1,11 +1,11 @@ - diff --git a/src/views/mobile/AboutPage.vue b/src/views/mobile/AboutPage.vue index 8906b62f..fa17a1bb 100644 --- a/src/views/mobile/AboutPage.vue +++ b/src/views/mobile/AboutPage.vue @@ -1,36 +1,36 @@ -