add digit grouping symbol when formatting numbers

This commit is contained in:
MaysWind
2026-04-21 00:20:19 +08:00
parent 53e515fb92
commit 629dbeeaa4
10 changed files with 38 additions and 71 deletions
+3 -10
View File
@@ -13,7 +13,7 @@
@click="currentPage = parseInt(page)"
v-if="page !== '...'"
>
<span>{{ getDisplayPage(page) }}</span>
<span>{{ formatNumberToLocalizedNumerals(parseInt(page)) }}</span>
</v-btn>
<v-btn variant="text"
color="default"
@@ -53,7 +53,6 @@ import { ref, computed } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { type NameNumeralValue, keys } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import type { ComponentDensity } from '@/lib/ui/desktop.ts';
const props = defineProps<{
@@ -68,21 +67,15 @@ const emit = defineEmits<{
(e: 'update:modelValue', value: number): void;
}>();
const { tt, getCurrentNumeralSystemType } = useI18n();
const { tt, formatNumberToLocalizedNumerals } = useI18n();
const showMenus = ref<Record<string, boolean>>({});
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
function getDisplayPage(page: number | string): string {
return numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(page.toString());
}
const allPages = computed<NameNumeralValue[]>(() => {
const pages: NameNumeralValue[] = [];
for (let i = 1; i <= props.totalPageCount; i++) {
pages.push({ value: i, name: getDisplayPage(i) });
pages.push({ value: i, name: formatNumberToLocalizedNumerals(i) });
}
return pages;
@@ -25,7 +25,8 @@ export function useExplorerDataTablePageBase() {
tt,
getCurrentNumeralSystemType,
formatDateTimeToLongDateTime,
formatAmountToLocalizedNumeralsWithCurrency
formatAmountToLocalizedNumeralsWithCurrency,
formatNumberToLocalizedNumerals
} = useI18n();
const settingsStore = useSettingsStore();
@@ -71,7 +72,7 @@ export function useExplorerDataTablePageBase() {
const availableCountPerPage: number[] = [ 5, 10, 15, 20, 25, 30, 50 ];
for (const count of availableCountPerPage) {
pageCounts.push({ value: count, name: numeralSystem.value.formatNumber(count) });
pageCounts.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
pageCounts.push({ value: -1, name: tt('All') });
+2 -4
View File
@@ -202,7 +202,6 @@ import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.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 {
@@ -232,7 +231,7 @@ type SnackBarType = InstanceType<typeof SnackBar>;
const router = useRouter();
const theme = useTheme();
const { tt, getCurrentNumeralSystemType } = useI18n();
const { tt, formatNumberToLocalizedNumerals } = useI18n();
const {
showAmountInHomePage,
allAccounts,
@@ -254,9 +253,8 @@ 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);
const displayAccountCount = computed<string>(() => formatNumberToLocalizedNumerals(allAccounts.value?.length ?? 0));
function clickMonthlyIncomeOrExpense(e: MonthlyIncomeAndExpenseCardClickEvent): void {
const minTime = e.monthStartTime;
@@ -297,7 +297,6 @@ 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 { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import { TransactionType } from '@/core/transaction.ts';
import { AccountBalanceTrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
@@ -341,7 +340,10 @@ const emit = defineEmits<{
(e: 'error', message: string): void;
}>();
const { tt, getCurrentNumeralSystemType, formatNumberToLocalizedNumerals } = useI18n();
const {
tt,
formatNumberToLocalizedNumerals
} = useI18n();
const {
accountId,
@@ -416,7 +418,6 @@ const chartType = ref<number>(AccountBalanceTrendChartType.Default.type);
let rejectFunc: ((reason?: unknown) => void) | null = null;
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const reconciliationStatementsTablePageOptions = computed<NameNumeralValue[]>(() => getTablePageOptions(reconciliationStatements.value?.transactions.length));
const totalPageCount = computed<number>(() => {
@@ -466,7 +467,7 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
break;
}
pageOptions.push({ value: count, name: numeralSystem.value.formatNumber(count) });
pageOptions.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
pageOptions.push({ value: -1, name: tt('All') });
@@ -314,7 +314,6 @@ const {
getMonthdayShortName,
getWeekdayLongName,
getQuarterName,
getCurrentNumeralSystemType,
getCurrencyName,
formatDateTimeToShortDateTime,
formatDateTimeToShortDate,
@@ -325,6 +324,7 @@ const {
formatGregorianYearToGregorianLikeFiscalYear,
formatAmountToLocalizedNumerals,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatNumberToLocalizedNumerals,
formatPercentToLocalizedNumerals
} = useI18n();
@@ -334,7 +334,6 @@ const explorersStore = useExplorersStore();
const axisChart = useTemplateRef<AxisChartType>('axisChart');
const heatmapChart = useTemplateRef<HeatMapChartType>('heatmapChart');
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const allTransactionExplorerDataDimensions = computed<NameValue[]>(() => getAllTransactionExplorerDataDimensions());
@@ -350,7 +349,7 @@ const allAmountRangeCounts = computed<NameNumeralValue[]>(() => {
const pageCounts: NameNumeralValue[] = [];
for (let i = 3; i <= 20; i++) {
pageCounts.push({ value: i, name: numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(i.toString()) });
pageCounts.push({ value: i, name: formatNumberToLocalizedNumerals(i) });
}
return pageCounts;
+3 -4
View File
@@ -684,7 +684,7 @@ import {
DateRangeScene,
DateRange
} from '@/core/datetime.ts';
import { type NumeralSystem, AmountFilterType } from '@/core/numeral.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { ThemeType } from '@/core/theme.ts';
import { TransactionType } from '@/core/transaction.ts';
import { TemplateType } from '@/core/template.ts';
@@ -775,7 +775,7 @@ const {
tt,
getAllRecentMonthDateRanges,
getWeekdayLongName,
getCurrentNumeralSystemType
formatNumberToLocalizedNumerals
} = useI18n();
const {
@@ -873,14 +873,13 @@ 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 (const count of availableCountPerPage) {
pageCounts.push({ value: count, name: numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(count.toString()) });
pageCounts.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
return pageCounts;
@@ -240,7 +240,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: getDisplayCount(importedCount || 0) }) }}</p>
<p class="my-5">{{ tt('format.misc.importTransactionResult', { count: formatNumberToLocalizedNumerals(importedCount || 0) }) }}</p>
</v-window-item>
</v-window>
</v-card-text>
@@ -298,7 +298,6 @@ import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.ts';
import { type KeyAndName, itemAndIndex } from '@/core/base.ts';
import { type NumeralSystem } from '@/core/numeral.ts';
import { TransactionType } from '@/core/transaction.ts';
import {
type ImportFileTypeSupportedAdditionalOptions,
@@ -346,7 +345,6 @@ defineProps<{
const {
tt,
joinMultiText,
getCurrentNumeralSystemType,
getAllSupportedImportFileCagtegoryAndTypes,
formatNumberToLocalizedNumerals,
getLocalizedFileEncodingName
@@ -414,8 +412,6 @@ const submitting = ref<boolean>(false);
let resolveFunc: (() => void) | null = null;
let rejectFunc: ((reason?: unknown) => void) | null = null;
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const allSupportedImportFileCategoryAndTypes = computed<LocalizedImportFileCategoryAndTypes[]>(() => getAllSupportedImportFileCagtegoryAndTypes());
const allFileSubTypes = computed<LocalizedImportFileTypeSubType[] | undefined>(() => allSupportedImportFileTypesMap.value[fileType.value]?.subTypes);
const allSupportedEncodings = computed<LocalizedImportFileTypeSupportedEncodings[] | undefined>(() => {
@@ -556,10 +552,6 @@ const exportFileGuideDocumentLanguageName = computed<string | undefined>(() => a
const fileName = computed<string>(() => importFile.value?.name || '');
function getDisplayCount(count: number): string {
return numeralSystem.value.formatNumber(count);
}
function loadInitFileTypeFromSettings(): void {
if (!settingsStore.appSettings.lastSelectedFileTypeInImportTransactionDialog) {
return;
@@ -925,7 +917,7 @@ function submit(): void {
}
confirmDialog.value?.open('format.misc.confirmImportTransactions', {
count: getDisplayCount(transactions.length)
count: formatNumberToLocalizedNumerals(transactions.length)
}).then(() => {
submitting.value = true;
@@ -310,7 +310,7 @@
<template #bottom>
<div class="title-and-toolbar d-flex align-center text-no-wrap mt-2" v-if="importTransactions">
<span :class="{ 'text-error': selectedInvalidTransactionCount > 0 }">
{{ tt('format.misc.selectedCount', { count: getDisplayCount(selectedImportTransactionCount), totalCount: getDisplayCount(importTransactions.length) }) }}
{{ tt('format.misc.selectedCount', { count: formatNumberToLocalizedNumerals(selectedImportTransactionCount), totalCount: formatNumberToLocalizedNumerals(importTransactions.length) }) }}
</span>
<v-spacer v-if="importTransactions.length > 10"/>
<span v-if="importTransactions.length > 10">{{ tt('Transactions Per Page') }}</span>
@@ -416,7 +416,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type NameValue, type NameNumeralValue, itemAndIndex, reversed, keys } from '@/core/base.ts';
import { type NumeralSystem, AmountFilterType } from '@/core/numeral.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { CategoryType } from '@/core/category.ts';
import { TransactionType } from '@/core/transaction.ts';
import { KnownFileType } from '@/core/file.ts';
@@ -509,11 +509,11 @@ const props = defineProps<{
const {
tt,
getCurrentNumeralSystemType,
formatDateTimeToLongDateTime,
formatDateTimeToGregorianDefaultDateTime,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatAmountToLocalizedNumeralsWithCurrency,
formatNumberToLocalizedNumerals,
getCategorizedAccountsWithDisplayBalance
} = useI18n();
@@ -553,7 +553,6 @@ const currentAmountFilterValue1 = ref<number>(0);
const currentAmountFilterValue2 = ref<number>(0);
const currentDescriptionFilterValue = ref<string | null>(null);
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.showAccountBalance);
const customAccountCategoryOrder = computed<string>(() => settingsStore.appSettings.accountCategoryOrders);
@@ -1205,10 +1204,6 @@ const displayFilterCustomDateRange = computed<string>(() => {
return `${minDisplayTime} - ${maxDisplayTime}`
});
function getDisplayCount(count: number): string {
return numeralSystem.value.formatNumber(count);
}
function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const pageOptions: NameNumeralValue[] = [];
@@ -1222,7 +1217,7 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
break;
}
pageOptions.push({ value: count, name: getDisplayCount(count) });
pageOptions.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
pageOptions.push({ value: -1, name: tt('All') });
@@ -1777,7 +1772,7 @@ function showBatchReplaceDialog(type: BatchReplaceDialogDataType, allSourceTagIt
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: getDisplayCount(updatedCount)
count: formatNumberToLocalizedNumerals(updatedCount)
});
}
});
@@ -1840,7 +1835,7 @@ function showBatchAddDialog(type: BatchReplaceDialogDataType): void {
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: getDisplayCount(updatedCount)
count: formatNumberToLocalizedNumerals(updatedCount)
});
}
});
@@ -1940,7 +1935,7 @@ function showReplaceInvalidItemDialog(type: BatchReplaceDialogDataType, invalidI
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: getDisplayCount(updatedCount)
count: formatNumberToLocalizedNumerals(updatedCount)
});
}
});
@@ -2017,7 +2012,7 @@ function showReplaceAllTypesDialog(): void {
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: getDisplayCount(updatedCount)
count: formatNumberToLocalizedNumerals(updatedCount)
});
}
});
@@ -2087,7 +2082,7 @@ function showBatchCreateInvalidItemDialog(type: BatchCreateDialogDataType, inval
if (updatedCount > 0) {
snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', {
count: getDisplayCount(updatedCount)
count: formatNumberToLocalizedNumerals(updatedCount)
});
}
});
@@ -46,7 +46,7 @@
<v-btn class="ms-2" color="secondary" density="compact" variant="outlined"
:disabled="!parsedFileDataColumnMapping || !parsedFileDataColumnMapping.isColumnMappingSet(ImportTransactionColumnType.TransactionType) || !parsedFileAllTransactionTypes">
<span>{{ tt('Transaction Type Mapping') }}</span>
<span class="ms-1" v-if="parsedFileDataColumnMapping && parsedFileDataColumnMapping.isColumnMappingSet(ImportTransactionColumnType.TransactionType) && parsedFileAllTransactionTypes">({{ getObjectOwnFieldCount(parsedFileValidMappedTransactionTypes) || tt('None') }})</span>
<span class="ms-1" v-if="parsedFileDataColumnMapping && parsedFileDataColumnMapping.isColumnMappingSet(ImportTransactionColumnType.TransactionType) && parsedFileAllTransactionTypes">({{ formatNumberToLocalizedNumerals(getObjectOwnFieldCount(parsedFileValidMappedTransactionTypes)) || tt('None') }})</span>
<v-menu eager activator="parent" location="bottom" max-height="500"
:close-on-content-click="false">
<v-list class="pa-0">
@@ -229,7 +229,7 @@ import { ref, computed, useTemplateRef, watch } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
import { type NameValue, type NameNumeralValue, type TypeAndDisplayName, itemAndIndex, keys, entries } from '@/core/base.ts';
import { type NumeralSystem, KnownAmountFormat } from '@/core/numeral.ts';
import { KnownAmountFormat } from '@/core/numeral.ts';
import { type DateFormatOrder, KnownDateTimeFormat } from '@/core/datetime.ts';
import { KnownDateTimezoneFormat } from '@/core/timezone.ts';
import { TransactionType } from '@/core/transaction.ts';
@@ -286,10 +286,10 @@ const props = defineProps<{
const {
tt,
ti,
getCurrentNumeralSystemType,
getLongDateFormatOrder,
getShortDateFormatOrder,
getAllImportTransactionColumnTypes
getAllImportTransactionColumnTypes,
formatNumberToLocalizedNumerals
} = useI18n();
const snackbar = useTemplateRef<SnackBarType>('snackbar');
@@ -298,7 +298,6 @@ const currentPage = ref<number>(1);
const countPerPage = ref<number>(10);
const parsedFileDataColumnMapping = ref<ImportTransactionDataMapping>(ImportTransactionDataMapping.createEmpty());
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const longDateFormatOrder = computed<DateFormatOrder>(() => getLongDateFormatOrder());
const shortDateFormatOrder = computed<DateFormatOrder>(() => getShortDateFormatOrder());
const allImportTransactionColumnTypes = computed<TypeAndDisplayName[]>(() => getAllImportTransactionColumnTypes());
@@ -453,10 +452,6 @@ const displayFileAutoDetectedAmountFormat = computed<string>(() => {
return tt('Unknown');
});
function getDisplayCount(count: number): string {
return numeralSystem.value.formatNumber(count);
}
function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const pageOptions: NameNumeralValue[] = [];
@@ -470,7 +465,7 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
break;
}
pageOptions.push({ value: count, name: getDisplayCount(count) });
pageOptions.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
pageOptions.push({ value: -1, name: tt('All') });
@@ -19,7 +19,7 @@
<div class="d-flex w-100 mb-2">
<v-btn density="compact" color="default" variant="text"
:disabled="disabled || !sandboxLoaded || executingScript || !previewResult">
<span>{{ tt('format.misc.previewCount', { count: previewCount > 0 ? getDisplayCount(previewCount) : tt('All') }) }}</span>
<span>{{ tt('format.misc.previewCount', { count: previewCount > 0 ? formatNumberToLocalizedNumerals(previewCount) : tt('All') }) }}</span>
<v-menu activator="parent">
<v-list>
<v-list-item :key="count.value" :title="count.name"
@@ -50,7 +50,6 @@ import { useI18n } from '@/locales/helpers.ts';
import { useSettingsStore } from '@/stores/setting.ts';
import type { NameNumeralValue } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import { KnownDateTimeFormat } from '@/core/datetime.ts';
import { KnownFileType } from '@/core/file.ts';
@@ -107,8 +106,8 @@ const props = defineProps<{
const {
tt,
getCurrentNumeralSystemType,
formatDateTimeToGregorianDefaultDateTime
formatDateTimeToGregorianDefaultDateTime,
formatNumberToLocalizedNumerals
} = useI18n();
const settingsStore = useSettingsStore();
@@ -124,7 +123,6 @@ const executionError = ref<string>('');
const previewCount = ref<number>(10);
const currentTimezoneName = computed<string>(() => settingsStore.appSettings.timeZone || getBrowserTimezoneName());
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const previewCounts = computed<NameNumeralValue[]>(() => getTablePageOptions(previewResult.value?.length));
const sampleScript = computed<string>(() => `// ${tt('sample.importTransactionCustomScript.headerComment')}
@@ -195,10 +193,6 @@ const menus = computed<ImportTransactionDefineColumnMenu[]>(() => [
}
]);
function getDisplayCount(count: number): string {
return numeralSystem.value.formatNumber(count);
}
function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
const pageOptions: NameNumeralValue[] = [];
@@ -211,7 +205,7 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
break;
}
pageOptions.push({ value: count, name: getDisplayCount(count) });
pageOptions.push({ value: count, name: formatNumberToLocalizedNumerals(count) });
}
pageOptions.push({ value: -1, name: tt('All') });