diff --git a/lang/es.json b/lang/es.json
index 190d454e..ddd75008 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -446,6 +446,7 @@
"Delete Label": "Eliminar Etiqueta",
"Delete Transaction": "Eliminar Transacción",
"Delete Transactions": "Eliminar Transacciones",
+ "Delete :count Transactions": "Borrar :count transacciones",
"Delete account": "Eliminar cuenta",
"Delete accounts": "Eliminar cuentas",
"Delete balance": "Eliminar balance",
diff --git a/resources/js/components/categories/create-category-dialog.tsx b/resources/js/components/categories/create-category-dialog.tsx
index e845abed..3306540e 100644
--- a/resources/js/components/categories/create-category-dialog.tsx
+++ b/resources/js/components/categories/create-category-dialog.tsx
@@ -26,6 +26,7 @@ import {
CATEGORY_ICONS,
CATEGORY_TYPES,
getCategoryColorClasses,
+ getCategoryTypeLabel,
} from '@/types/category';
import { __ } from '@/utils/i18n';
import { Form } from '@inertiajs/react';
@@ -166,8 +167,7 @@ export function CreateCategoryDialog({
{CATEGORY_TYPES.map((type) => (
- {type.charAt(0).toUpperCase() +
- type.slice(1)}
+ {getCategoryTypeLabel(type)}
))}
@@ -209,7 +209,9 @@ export function CreateCategoryDialog({
{__('Cancel')}
>
diff --git a/resources/js/components/categories/edit-category-dialog.tsx b/resources/js/components/categories/edit-category-dialog.tsx
index d38387bd..4411faf1 100644
--- a/resources/js/components/categories/edit-category-dialog.tsx
+++ b/resources/js/components/categories/edit-category-dialog.tsx
@@ -24,6 +24,7 @@ import {
CATEGORY_ICONS,
CATEGORY_TYPES,
getCategoryColorClasses,
+ getCategoryTypeLabel,
type Category,
} from '@/types/category';
import { __ } from '@/utils/i18n';
@@ -177,8 +178,7 @@ export function EditCategoryDialog({
{CATEGORY_TYPES.map((type) => (
- {type.charAt(0).toUpperCase() +
- type.slice(1)}
+ {getCategoryTypeLabel(type)}
))}
diff --git a/resources/js/lib/transaction-delete-confirmation.test.ts b/resources/js/lib/transaction-delete-confirmation.test.ts
new file mode 100644
index 00000000..b9c68a0b
--- /dev/null
+++ b/resources/js/lib/transaction-delete-confirmation.test.ts
@@ -0,0 +1,25 @@
+import { setTranslations } from '@/utils/i18n';
+import { afterEach, describe, expect, it } from 'vitest';
+import { getBulkDeleteConfirmationText } from './transaction-delete-confirmation';
+
+describe('getBulkDeleteConfirmationText', () => {
+ afterEach(() => {
+ setTranslations({});
+ });
+
+ it('returns translated bulk delete confirmation text', () => {
+ setTranslations({
+ 'Delete :count Transactions': 'Borrar :count transacciones',
+ });
+
+ expect(getBulkDeleteConfirmationText(12)).toBe(
+ 'Borrar 12 transacciones',
+ );
+ });
+
+ it('falls back to English confirmation text', () => {
+ expect(getBulkDeleteConfirmationText(12)).toBe(
+ 'Delete 12 Transactions',
+ );
+ });
+});
diff --git a/resources/js/lib/transaction-delete-confirmation.ts b/resources/js/lib/transaction-delete-confirmation.ts
new file mode 100644
index 00000000..a1d7d799
--- /dev/null
+++ b/resources/js/lib/transaction-delete-confirmation.ts
@@ -0,0 +1,5 @@
+import { __ } from '@/utils/i18n';
+
+export function getBulkDeleteConfirmationText(count: number): string {
+ return __('Delete :count Transactions', { count });
+}
diff --git a/resources/js/pages/transactions/index.tsx b/resources/js/pages/transactions/index.tsx
index 357a1231..0bee2d88 100644
--- a/resources/js/pages/transactions/index.tsx
+++ b/resources/js/pages/transactions/index.tsx
@@ -79,6 +79,7 @@ import {
} from '@/lib/cursor-pagination';
import { consoleDebug } from '@/lib/debug';
import { captureEvent } from '@/lib/posthog';
+import { getBulkDeleteConfirmationText } from '@/lib/transaction-delete-confirmation';
import { mergeReEvaluatedTransaction } from '@/lib/transaction-re-evaluation';
import { cn } from '@/lib/utils';
import { transactionSyncService } from '@/services/transaction-sync';
@@ -941,6 +942,11 @@ export default function Transactions({
const selectedCount = useMemo(() => selectedIds.length, [selectedIds]);
+ const bulkDeleteConfirmationText = useMemo(
+ () => getBulkDeleteConfirmationText(selectedCount),
+ [selectedCount],
+ );
+
function handleBulkDeleteClick() {
if (selectedIds.length === 0) {
return;
@@ -1298,7 +1304,7 @@ export default function Transactions({
'This action cannot be undone. To confirm, type',
)}{' '}
- delete {selectedCount} transactions
+ {bulkDeleteConfirmationText}
@@ -1307,7 +1313,7 @@ export default function Transactions({
onChange={(e) =>
setBulkDeleteConfirmation(e.target.value)
}
- placeholder={`delete ${selectedCount} transactions`}
+ placeholder={bulkDeleteConfirmationText}
disabled={isBulkDeleting}
autoFocus
/>
@@ -1329,7 +1335,7 @@ export default function Transactions({
disabled={
isBulkDeleting ||
bulkDeleteConfirmation !==
- `delete ${selectedCount} transactions`
+ bulkDeleteConfirmationText
}
>
{isBulkDeleting ? __('Deleting...') : __('Delete')}
diff --git a/resources/js/types/category.test.ts b/resources/js/types/category.test.ts
new file mode 100644
index 00000000..50a7682c
--- /dev/null
+++ b/resources/js/types/category.test.ts
@@ -0,0 +1,27 @@
+import { setTranslations } from '@/utils/i18n';
+import { afterEach, describe, expect, it } from 'vitest';
+import { getCategoryTypeLabel } from './category';
+
+describe('getCategoryTypeLabel', () => {
+ afterEach(() => {
+ setTranslations({});
+ });
+
+ it('returns translated category type labels', () => {
+ setTranslations({
+ Income: 'Ingresos',
+ Expense: 'Gasto',
+ Transfer: 'Transferencia',
+ });
+
+ expect(getCategoryTypeLabel('income')).toBe('Ingresos');
+ expect(getCategoryTypeLabel('expense')).toBe('Gasto');
+ expect(getCategoryTypeLabel('transfer')).toBe('Transferencia');
+ });
+
+ it('falls back to English labels without translations', () => {
+ expect(getCategoryTypeLabel('income')).toBe('Income');
+ expect(getCategoryTypeLabel('expense')).toBe('Expense');
+ expect(getCategoryTypeLabel('transfer')).toBe('Transfer');
+ });
+});
diff --git a/resources/js/types/category.ts b/resources/js/types/category.ts
index 1d7da62a..3e0eba93 100644
--- a/resources/js/types/category.ts
+++ b/resources/js/types/category.ts
@@ -1,3 +1,5 @@
+import { __ } from '@/utils/i18n';
+
import { UUID } from './uuid';
export const CATEGORY_ICONS = [
@@ -107,6 +109,16 @@ export const CATEGORY_TYPES = ['income', 'expense', 'transfer'] as const;
export type CategoryType = (typeof CATEGORY_TYPES)[number];
+const CATEGORY_TYPE_LABELS: Record = {
+ income: 'Income',
+ expense: 'Expense',
+ transfer: 'Transfer',
+};
+
+export function getCategoryTypeLabel(type: CategoryType): string {
+ return __(CATEGORY_TYPE_LABELS[type]);
+}
+
export const CATEGORY_CASHFLOW_DIRECTIONS = [
'hidden',
'inflow',