DataTable Internationalization Usage¶
This guide explains how to use the internationalization features in the DataTable component.
Important: Use the useIntl Hook¶
Always prefer the useIntl hook over direct imports from @/utils/intl. The hook automatically uses the user's locale and currency settings, providing a consistent experience across the application.
// ✅ GOOD - Uses user's settings automatically
import { useIntl } from '@/hooks/useIntl';
// ❌ AVOID - Requires manual locale/currency handling
import { formatCurrency, formatDate } from '@/utils/intl';
Basic Usage with useIntl¶
The useIntl hook provides all formatting functions with automatic locale and currency detection:
import { DataTable } from '@/components/ui/DataTable';
import { useIntl } from '@/hooks/useIntl';
function MyComponent() {
const { formatCurrency, formatDate, formatNumber } = useIntl();
const columns: ColumnDef<Transaction>[] = [
{
accessorKey: 'date',
header: 'Date',
cell: ({ getValue }) => {
const date = getValue<string>();
// Automatically uses user's locale
return formatDate(date, 'relative'); // Shows "Today", "Yesterday", or date
},
},
{
accessorKey: 'amount',
header: 'Amount',
cell: ({ getValue, row }) => {
const amount = getValue<number>();
const currencyCode = row.original.currency_code;
// Automatically uses user's locale for formatting
return formatCurrency(amount, currencyCode);
},
},
];
return <DataTable columns={columns} data={data} />;
}
Enhanced Date Formatting¶
The formatDate function from useIntl now supports automatic "Today" and "Yesterday" formatting:
Format Options¶
'relative'- Shows "Today", "Yesterday", or the localized date'relative-time'- Shows "Today, 3:45 PM", "Yesterday, 10:30 AM", or date with time- Standard formats - All date-fns formats ('P', 'Pp', 'p', etc.) still work
Examples¶
function MyDataTableComponent() {
const { formatDate } = useIntl();
const columns: ColumnDef<Activity>[] = [
{
accessorKey: 'created_at',
header: 'Created',
cell: ({ getValue }) => {
const date = getValue<string>();
// Different formatting options:
return formatDate(date, 'relative'); // "Today" / "Yesterday" / "Dec 7, 2024"
// OR
return formatDate(date, 'relative-time'); // "Today, 3:45 PM" / "Yesterday, 10:30 AM"
// OR
return formatDate(date, 'P'); // "12/14/2024" (localized)
// OR
return formatDate(date, 'Pp'); // "12/14/2024, 3:45 PM" (localized)
},
},
];
return <DataTable columns={columns} data={data} />;
}
Complete Example with All Formatting¶
import { useIntl } from '@/hooks/useIntl';
import { DataTable } from '@/components/ui/DataTable';
import type { ColumnDef } from '@tanstack/react-table';
interface Transaction {
id: string;
amount: number;
currency_code: string;
transaction_date: string;
updated_at: string;
quantity: number;
percentage: number;
description: string;
}
function TransactionsTable({ data }: { data: Transaction[] }) {
const { formatCurrency, formatDate, formatNumber, formatPercentage } =
useIntl();
const columns: ColumnDef<Transaction>[] = [
{
accessorKey: 'transaction_date',
header: 'Date',
cell: ({ getValue }) => {
// Shows "Today", "Yesterday", or the date
return formatDate(getValue<string>(), 'relative');
},
},
{
accessorKey: 'updated_at',
header: 'Last Updated',
cell: ({ getValue }) => {
// Shows with time: "Today, 3:45 PM"
return formatDate(getValue<string>(), 'relative-time');
},
},
{
accessorKey: 'amount',
header: 'Amount',
cell: ({ getValue, row }) => {
const amount = getValue<number>();
const currency = row.original.currency_code;
// Formats with user's locale (e.g., "$1,234.56" or "₹1,234.56")
return formatCurrency(amount, currency);
},
},
{
accessorKey: 'quantity',
header: 'Quantity',
cell: ({ getValue }) => {
// Formats number with user's locale (e.g., "1,234.56")
return formatNumber(getValue<number>());
},
},
{
accessorKey: 'percentage',
header: 'Rate',
cell: ({ getValue }) => {
// Formats as percentage (e.g., "15.5%")
return formatPercentage(getValue<number>());
},
},
{
accessorKey: 'description',
header: 'Description',
},
];
return <DataTable columns={columns} data={data} />;
}
Fallback for Server Components¶
If you're working with a Server Component that cannot use hooks, you can pass locale and currency as props:
// Server Component
import { formatCurrency, formatDate } from '@/utils/intl';
export default async function ServerTable({ locale, currency }: Props) {
const data = await fetchData();
// Manual formatting with passed locale/currency
const formattedData = data.map((item) => ({
...item,
formattedDate: formatDate(item.date, locale, 'P'),
formattedAmount: formatCurrency(item.amount, currency, locale),
}));
return <DataTable data={formattedData} />;
}
However, always prefer Client Components with the useIntl hook when possible for consistency.
Date Filtering with Locale¶
The DataTable's date filter automatically uses the user's locale when you use the table with proper meta configuration:
const columns: ColumnDef<Transaction>[] = [
{
accessorKey: 'date',
header: 'Date',
meta: {
dataType: 'date', // Enables locale-aware date picker
},
cell: ({ getValue }) => {
const { formatDate } = useIntl();
return formatDate(getValue<string>(), 'relative');
},
},
];
Best Practices¶
- Always use
useIntlhook when in Client Components for automatic locale/currency detection - Store raw data: Keep numbers for currency and ISO strings for dates in your database
- Format only in the UI: Apply formatting only in render functions, not in data fetching
- Use relative dates for better UX: Prefer 'relative' or 'relative-time' for recent dates
- Be consistent: Use the same date format throughout similar contexts
Migration Guide¶
Old Pattern (Manual Locale Handling)¶
import { formatDate, formatCurrency } from '@/utils/intl';
import { useUser } from '@/hooks/useUser';
function OldComponent() {
const { user } = useUser();
const locale = user?.user_setting?.locale || 'en-US';
const currency = user?.user_setting?.currency || 'USD';
// Manual checks for Today/Yesterday
const formatTransactionDate = (date: string) => {
const dateObj = new Date(date);
const today = new Date();
if (dateObj.toDateString() === today.toDateString()) {
return 'Today';
}
// ... more manual checks
return formatDate(dateObj, locale, 'P');
};
return (
<div>
{formatTransactionDate(transaction.date)}
{formatCurrency(transaction.amount, currency, locale)}
</div>
);
}
New Pattern (Automatic with useIntl)¶
import { useIntl } from '@/hooks/useIntl';
function NewComponent() {
const { formatDate, formatCurrency } = useIntl();
return (
<div>
{/* Automatic Today/Yesterday handling */}
{formatDate(transaction.date, 'relative')}
{/* Automatic locale detection */}
{formatCurrency(transaction.amount, transaction.currency_code)}
</div>
);
}
TypeScript Support¶
The column meta types are already configured in the codebase:
import '@tanstack/react-table';
declare module '@tanstack/react-table' {
interface ColumnMeta<TData extends RowData, TValue> {
locale?: string;
currency?: string;
dataType?: 'text' | 'number' | 'date' | 'boolean' | 'select';
facetedValues?: Array<{ label: string; value: string }>;
}
}
This provides full IntelliSense support for column meta properties.