fix some numerals were not displayed according to the numerical system

This commit is contained in:
MaysWind
2025-08-29 00:18:46 +08:00
parent 0e634d83f4
commit 8f6adaa417
13 changed files with 145 additions and 83 deletions
@@ -10,11 +10,12 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { useTransactionsStore } from '@/stores/transaction.ts';
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
import { DISPLAY_HIDDEN_AMOUNT } from '@/consts/numeral.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import type { WeekDayValue } from '@/core/datetime.ts';
import type { LocalizedTimezoneInfo } from '@/core/timezone.ts';
import { TransactionType } from '@/core/transaction.ts';
import { TemplateType } from '@/core/template.ts';
import { DISPLAY_HIDDEN_AMOUNT } from '@/consts/numeral.ts';
import { TRANSACTION_MAX_PICTURE_COUNT } from '@/consts/transaction.ts';
import { Account, type CategorizedAccountWithDisplayBalance } from '@/models/account.ts';
@@ -59,6 +60,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
const {
tt,
getAllTimezones,
getCurrentNumeralSystemType,
getTimezoneDifferenceDisplayText,
formatAmountToLocalizedNumeralsWithCurrency,
getAdaptiveAmountRate,
@@ -89,6 +91,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
const transaction = ref<Transaction | TransactionTemplate>(createNewTransactionModel(transactionDefaultType));
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
@@ -265,7 +268,8 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
});
const transactionDisplayTimezone = computed<string>(() => {
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.value.utcOffset)}`;
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getUtcOffsetByUtcOffsetMinutes(transaction.value.utcOffset));
return `UTC${utcOffset}`;
});
const transactionTimezoneTimeDifference = computed<string>(() => {
@@ -416,6 +420,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
setGeoLocationByClickMap,
transaction,
// computed states
numeralSystem,
currentTimezoneOffsetMinutes,
showAccountBalance,
defaultCurrency,
@@ -10,6 +10,7 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionListFilter, type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts';
import type { TypeAndName } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import { type TextualYearMonthDay, type Year0BasedMonth, type LocalizedDateRange, type WeekDayValue, DateRange, DateRangeScene } from '@/core/datetime.ts';
import { AccountType } from '@/core/account.ts';
import { TransactionType } from '@/core/transaction.ts';
@@ -74,6 +75,7 @@ export function useTransactionListPageBase() {
const {
tt,
getAllDateRanges,
getCurrentNumeralSystemType,
formatUnixTimeToLongDateTime,
formatUnixTimeToLongDate,
formatUnixTimeToLongYearMonth,
@@ -95,6 +97,7 @@ export function useTransactionListPageBase() {
const customMaxDatetime = ref<number>(0);
const currentCalendarDate = ref<TextualYearMonthDay | ''>('');
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const fiscalYearStart = computed<number>(() => userStore.currentUserFiscalYearStart);
@@ -288,11 +291,13 @@ export function useTransactionListPageBase() {
}
function getDisplayTimezone(transaction: Transaction): string {
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)}`;
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset));
return `UTC${utcOffset}`;
}
function getDisplayTimeInDefaultTimezone(transaction: Transaction): string {
return `${formatUnixTimeToLongDateTime(transaction.time)} (UTC${getTimezoneOffset(settingsStore.appSettings.timeZone)})`;
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(settingsStore.appSettings.timeZone));
return `${formatUnixTimeToLongDateTime(transaction.time)} (UTC${utcOffset})`;
}
function getDisplayAmount(transaction: Transaction): string {
+6 -2
View File
@@ -51,7 +51,7 @@
<v-card-text>
<div class="mb-8">
<span class="text-body-1" v-if="!loadingOverview || (allAccounts && allAccounts.length)">{{ tt('format.misc.youHaveAccounts', { count: allAccounts.length }) }}</span>
<span class="text-body-1" v-if="!loadingOverview || (allAccounts && allAccounts.length)">{{ tt('format.misc.youHaveAccounts', { count: displayAccountCount }) }}</span>
<v-skeleton-loader class="skeleton-no-margin mt-1 mb-2 pb-1" width="200px" type="text" :loading="true" v-else-if="loadingOverview && (!allAccounts || !allAccounts.length)"></v-skeleton-loader>
</div>
@@ -201,6 +201,7 @@ import { useHomePageBase } from '@/views/base/HomePageBase.ts';
import { useAccountsStore } from '@/stores/account.ts';
import { useOverviewStore } from '@/stores/overview.ts';
import { type NumeralSystem } from '@/core/numeral.ts';
import { DateRange } from '@/core/datetime.ts';
import { ThemeType } from '@/core/theme.ts';
import { type TransactionMonthlyIncomeAndExpenseData, LATEST_12MONTHS_TRANSACTION_AMOUNTS_REQUEST_TYPES } from '@/models/transaction.ts';
@@ -227,7 +228,7 @@ type SnackBarType = InstanceType<typeof SnackBar>;
const router = useRouter();
const theme = useTheme();
const { tt } = useI18n();
const { tt, getCurrentNumeralSystemType } = useI18n();
const {
showAmountInHomePage,
allAccounts,
@@ -248,6 +249,9 @@ const snackbar = useTemplateRef<SnackBarType>('snackbar');
const loadingOverview = ref<boolean>(true);
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const displayAccountCount = computed<string>(() => allAccounts.value ? numeralSystem.value.formatNumber(allAccounts.value.length) : numeralSystem.value.digitZero);
function clickMonthlyIncomeOrExpense(e: MonthlyIncomeAndExpenseCardClickEvent): void {
const minTime = e.monthStartTime;
@@ -209,7 +209,7 @@
{{ tt('Transactions Per Page') }}
</span>
<v-select class="ms-2" density="compact" max-width="100"
item-title="title"
item-title="name"
item-value="value"
:disabled="loading"
:items="reconciliationStatementsTablePageOptions"
@@ -278,6 +278,8 @@ import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionsStore } from '@/stores/transaction.ts';
import type { NameNumeralValue } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import { TransactionType } from '@/core/transaction.ts';
import { AccountBalanceTrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
import { KnownFileType } from '@/core/file.ts';
@@ -310,16 +312,11 @@ type SnackBarType = InstanceType<typeof SnackBar>;
type AmountInputDialogType = InstanceType<typeof AmountInputDialog>;
type EditDialogType = InstanceType<typeof EditDialog>;
interface ReconciliationStatementDialogTablePageOption {
value: number;
title: string;
}
const emit = defineEmits<{
(e: 'error', message: string): void;
}>();
const { tt, formatNumberToLocalizedNumerals } = useI18n();
const { tt, getCurrentNumeralSystemType, formatNumberToLocalizedNumerals } = useI18n();
const {
accountId,
@@ -383,7 +380,8 @@ const chartDataDateAggregationType = ref<number | undefined>(undefined);
let rejectFunc: ((reason?: unknown) => void) | null = null;
const reconciliationStatementsTablePageOptions = computed<ReconciliationStatementDialogTablePageOption[]>(() => getTablePageOptions(reconciliationStatements.value?.transactions.length));
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const reconciliationStatementsTablePageOptions = computed<NameNumeralValue[]>(() => getTablePageOptions(reconciliationStatements.value?.transactions.length));
const totalPageCount = computed<number>(() => {
if (!reconciliationStatements.value || !reconciliationStatements.value.transactions || reconciliationStatements.value.transactions.length < 1) {
@@ -414,11 +412,11 @@ const dataTableHeaders = computed<object[]>(() => {
return headers;
});
function getTablePageOptions(linesCount?: number): ReconciliationStatementDialogTablePageOption[] {
const pageOptions: ReconciliationStatementDialogTablePageOption[] = [];
function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const pageOptions: NameNumeralValue[] = [];
if (!linesCount || linesCount < 1) {
pageOptions.push({ value: -1, title: tt('All') });
pageOptions.push({ value: -1, name: tt('All') });
return pageOptions;
}
@@ -431,10 +429,10 @@ function getTablePageOptions(linesCount?: number): ReconciliationStatementDialog
break;
}
pageOptions.push({ value: count, title: count.toString() });
pageOptions.push({ value: count, name: numeralSystem.value.formatNumber(count) });
}
pageOptions.push({ value: -1, title: tt('All') });
pageOptions.push({ value: -1, name: tt('All') });
return pageOptions;
}
+22 -5
View File
@@ -33,8 +33,11 @@
</div>
<div class="mx-6 mt-4" v-if="pageType === TransactionListPageType.List.type">
<span class="text-subtitle-2">{{ tt('Transactions Per Page') }}</span>
<v-select class="mt-2" density="compact" :disabled="loading"
:items="[ 5, 10, 15, 20, 25, 30, 50 ]"
<v-select class="mt-2" density="compact"
item-title="name"
item-value="value"
:disabled="loading"
:items="allPageCounts"
v-model="countPerPage"
/>
</div>
@@ -666,7 +669,7 @@ import { useTransactionsStore } from '@/stores/transaction.ts';
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.ts';
import { useDesktopPageStore } from '@/stores/desktopPage.ts';
import type { TypeAndDisplayName } from '@/core/base.ts';
import type { NameNumeralValue, TypeAndDisplayName } from '@/core/base.ts';
import {
type Year0BasedMonth,
type LocalizedRecentMonthDateRange,
@@ -674,7 +677,7 @@ import {
DateRangeScene,
DateRange
} from '@/core/datetime.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { type NumeralSystem, AmountFilterType } from '@/core/numeral.ts';
import { ThemeType } from '@/core/theme.ts';
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
import { TemplateType } from '@/core/template.ts';
@@ -774,7 +777,8 @@ const {
tt,
getAllRecentMonthDateRanges,
getAllTransactionTagFilterTypes,
getWeekdayLongName
getWeekdayLongName,
getCurrentNumeralSystemType
} = useI18n();
const {
@@ -874,6 +878,19 @@ const showFilterCategoryDialog = ref<boolean>(false);
const showFilterTagDialog = ref<boolean>(false);
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const allPageCounts = computed<NameNumeralValue[]>(() => {
const pageCounts: NameNumeralValue[] = [];
const availableCountPerPage: number[] = [ 5, 10, 15, 20, 25, 30, 50 ];
for (let i = 0; i < availableCountPerPage.length; i++) {
const count = availableCountPerPage[i];
pageCounts.push({ value: count, name: numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(count.toString()) });
}
return pageCounts;
});
const recentMonthDateRanges = computed<LocalizedRecentMonthDateRange[]>(() => getAllRecentMonthDateRanges(pageType.value === TransactionListPageType.List.type, true));
@@ -503,7 +503,7 @@
<v-spacer/>
<span>{{ tt('Lines Per Page') }}</span>
<v-select class="ms-2" density="compact" max-width="100"
item-title="title"
item-title="name"
item-value="value"
:disabled="loading || submitting"
:items="parsedFileLinesTablePageOptions"
@@ -794,12 +794,12 @@
<div class="title-and-toolbar d-flex align-center text-no-wrap mt-2"
v-if="importTransactions && importTransactions.length > 10">
<span :class="{ 'text-error': selectedInvalidTransactionCount > 0 }">
{{ tt('format.misc.selectedCount', { count: selectedImportTransactionCount, totalCount: importTransactions.length }) }}
{{ tt('format.misc.selectedCount', { count: getDisplayCount(selectedImportTransactionCount), totalCount: getDisplayCount(importTransactions.length) }) }}
</span>
<v-spacer/>
<span>{{ tt('Transactions Per Page') }}</span>
<v-select class="ms-2" density="compact" max-width="100"
item-title="title"
item-title="name"
item-value="value"
:disabled="loading || submitting"
:items="importTransactionsTablePageOptions"
@@ -815,7 +815,7 @@
</v-window-item>
<v-window-item value="finalResult">
<h4 class="text-h4 mb-1">{{ tt('Data Import Completed') }}</h4>
<p class="my-5">{{ tt('format.misc.importTransactionResult', { count: importedCount }) }}</p>
<p class="my-5">{{ tt('format.misc.importTransactionResult', { count: getDisplayCount(importedCount || 0) }) }}</p>
</v-window-item>
</v-window>
@@ -906,8 +906,8 @@ import { useTransactionsStore } from '@/stores/transaction.ts';
import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.ts';
import type { NameValue, TypeAndDisplayName } from '@/core/base.ts';
import { KnownAmountFormat } from '@/core/numeral.ts';
import type { NameValue, NameNumeralValue, TypeAndDisplayName } from '@/core/base.ts';
import { type NumeralSystem, KnownAmountFormat } from '@/core/numeral.ts';
import { KnownDateTimeFormat } from '@/core/datetime.ts';
import { KnownDateTimezoneFormat } from '@/core/timezone.ts';
import { CategoryType } from '@/core/category.ts';
@@ -992,11 +992,6 @@ interface ImportTransactionDialogFilter {
description: string | null; // null for 'All Description'
}
interface ImportTransactionsDialogTablePageOption {
value: number;
title: string;
}
defineProps<{
persistent?: boolean;
}>();
@@ -1005,6 +1000,7 @@ const {
tt,
getAllImportTransactionColumnTypes,
getAllSupportedImportFileCagtegoryAndTypes,
getCurrentNumeralSystemType,
formatUnixTimeToLongDateTime,
formatAmountToLocalizedNumeralsWithCurrency,
formatNumberToLocalizedNumerals,
@@ -1063,6 +1059,7 @@ const submitting = ref<boolean>(false);
let resolveFunc: (() => void) | null = null;
let rejectFunc: ((reason?: unknown) => void) | null = null;
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
@@ -1252,7 +1249,7 @@ const parsedFileLinesHeaders = computed<object[]>(() => {
return headers;
});
const parsedFileLinesTablePageOptions = computed<ImportTransactionsDialogTablePageOption[]>(() => getTablePageOptions(parsedFileLines.value?.length));
const parsedFileLinesTablePageOptions = computed<NameNumeralValue[]>(() => getTablePageOptions(parsedFileLines.value?.length));
const parsedFileAllTransactionTypes = computed<string[]>(() => parsedFileDataColumnMapping.value.parseFileAllTransactionTypes(parsedFileData.value));
const parsedFileValidMappedTransactionTypes = computed<Record<string, TransactionType>>(() => parsedFileDataColumnMapping.value.parseFileValidMappedTransactionTypes(parsedFileData.value));
@@ -1282,7 +1279,7 @@ const importTransactionHeaders = computed<object[]>(() => {
];
});
const importTransactionsTablePageOptions = computed<ImportTransactionsDialogTablePageOption[]>(() => getTablePageOptions(importTransactions.value?.length));
const importTransactionsTablePageOptions = computed<NameNumeralValue[]>(() => getTablePageOptions(importTransactions.value?.length));
const totalPageCount = computed<number>(() => {
if (!importTransactions.value || importTransactions.value.length < 1) {
@@ -1490,11 +1487,15 @@ const displayFilterCustomDateRange = computed<string>(() => {
return `${minDisplayTime} - ${maxDisplayTime}`
});
function getTablePageOptions(linesCount?: number): ImportTransactionsDialogTablePageOption[] {
const pageOptions: ImportTransactionsDialogTablePageOption[] = [];
function getDisplayCount(count: number): string {
return numeralSystem.value.formatNumber(count);
}
function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const pageOptions: NameNumeralValue[] = [];
if (!linesCount || linesCount < 1) {
pageOptions.push({ value: -1, title: tt('All') });
pageOptions.push({ value: -1, name: tt('All') });
return pageOptions;
}
@@ -1507,10 +1508,10 @@ function getTablePageOptions(linesCount?: number): ImportTransactionsDialogTable
break;
}
pageOptions.push({ value: count, title: count.toString() });
pageOptions.push({ value: count, name: getDisplayCount(count) });
}
pageOptions.push({ value: -1, title: tt('All') });
pageOptions.push({ value: -1, name: tt('All') });
return pageOptions;
}
@@ -2110,7 +2111,7 @@ function submit(): void {
}
confirmDialog.value?.open('format.misc.confirmImportTransactions', {
count: transactions.length
count: getDisplayCount(transactions.length)
}).then(() => {
editingTransaction.value = null;
editingTags.value = [];
@@ -2379,7 +2380,7 @@ function showBatchReplaceDialog(type: BatchReplaceDialogDataType): void {
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: updatedCount
count: getDisplayCount(updatedCount)
});
}
});
@@ -2463,7 +2464,7 @@ function showReplaceInvalidItemDialog(type: BatchReplaceDialogDataType, invalidI
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: updatedCount
count: getDisplayCount(updatedCount)
});
}
});
@@ -2535,7 +2536,7 @@ function showReplaceAllTypesDialog(): void {
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: updatedCount
count: getDisplayCount(updatedCount)
});
}
});
@@ -2607,7 +2608,7 @@ function showBatchCreateInvalidItemDialog(type: BatchCreateDialogDataType, inval
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: updatedCount
count: getDisplayCount(updatedCount)
});
}
});
+3 -1
View File
@@ -553,6 +553,7 @@ const {
geoLocationStatus,
setGeoLocationByClickMap,
transaction,
numeralSystem,
currentTimezoneOffsetMinutes,
defaultCurrency,
defaultAccountId,
@@ -662,7 +663,8 @@ const transactionDisplayTime = computed<string>(() => {
return formatUnixTimeToLongTime(getActualUnixTimeForStore(transaction.value.time, getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()));
}
return `${formatUnixTimeToLongTime(getActualUnixTimeForStore(transaction.value.time, transaction.value.utcOffset, getBrowserTimezoneOffsetMinutes()))} (UTC${getTimezoneOffset(settingsStore.appSettings.timeZone)})`;
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(settingsStore.appSettings.timeZone));
return `${formatUnixTimeToLongTime(getActualUnixTimeForStore(transaction.value.time, transaction.value.utcOffset, getBrowserTimezoneOffsetMinutes()))} (UTC${utcOffset})`;
});
const transactionDisplayTimezoneName = computed<string>(() => {