Formatera datum, tal och pluralformer per lokal
Använd Intl-API:er för att återge lokalkorrekt datum, valutor och pluraliserade strängar.
Formatera datum, tal och pluralformer per lokal är en gratis lektion i Next.js 15 fullstack (App Router + Server Actions) på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Next.js 15 fullstack (App Router + Server Actions), och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Next.js 15 fullstack (App Router + Server Actions) innehåller totalt 4 lektioner.
Varför språkvariantmedveten formatering är viktig
Ett datum som 06/07/2025 betyder den 7 juni för en amerikan, men den 6 juli för en europé. Ett tal som 1.234 betyder ett tusen två hundra trettiofyra i USA, men ett komma två tre fyra i Tyskland.
Hårdkodad formateringslogik gör att appen slutar fungera korrekt för internationella användare. I stället innehåller både webbläsaren och Node.js namnrymden Intl — en standardbaserad uppsättning API:er som hanterar lokaliserad formatering utan tredjepartsbibliotek.
Intl.DateTimeFormat— formaterar datum och tiderIntl.NumberFormat— formaterar tal, valutor och enheterIntl.PluralRules— väljer korrekt pluralform
I ett Next.js 15-projekt med App Router körs dessa både på servern (i Server Components och Server Actions) och på klienten, så att du får ett konsekvent resultat utan att skicka med extra JavaScript.
Identifiera den aktiva lokalen i App Router
Next.js 15 med App Router lagrar den aktiva lokalen i URL-segmentet. En vanlig konvention är /en/dashboard eller /de/dashboard. Din layout.tsx tar emot en params-prop som innehåller den.
Kodsnutten nedan visar hur du läser params.locale i en asynkron Server Component och skickar den vidare till formateringshjälpfunktioner.
// app/[locale]/layout.tsx
import { ReactNode } from 'react';
interface Props {
children: ReactNode;
params: Promise<{ locale: string }>;
}
export default async function LocaleLayout({ children, params }: Props) {
const { locale } = await params; // e.g. 'en', 'de', 'tr'
return (
<html lang={locale}>
<body>{children}</body>
</html>
);
}Formatera datum med Intl.DateTimeFormat
Intl.DateTimeFormat tar emot en lokalsträng och ett options-objekt. Du kan styra vilka datum- och tidsdelar som ska visas och i vilken stil.
- dateStyle:
'short','medium','long','full' - timeStyle: samma alternativ
- Enskilda fält:
year,month,day,hour,minutemed flera
Anropet .format(date) returnerar en lokalkorrekt sträng. Eftersom Intl är inbyggt i Node.js kan detta köras säkert i en Server Component utan att öka klientens bundle-storlek.
// lib/format-date.ts
export function formatDate(
date: Date,
locale: string,
options: Intl.DateTimeFormatOptions = { dateStyle: 'long' }
): string {
return new Intl.DateTimeFormat(locale, options).format(date);
}
// Usage examples:
// formatDate(new Date(), 'en-US') => 'June 7, 2025'
// formatDate(new Date(), 'de-DE') => '7. Juni 2025'
// formatDate(new Date(), 'tr-TR') => '7 Haziran 2025'
// formatDate(new Date(), 'ja-JP') => '2025年6月7日'Använda formatDate i en Server Component
Eftersom Server Components körs i Node.js kan du anropa hjälpfunktionen formatDate direkt — utan useEffect, utan hydreringsskillnader och utan extra bundle-storlek för klienten.
Lokalen kommer från params och skickas direkt till formateraren. Resultatet är en vanlig sträng som bäddas in i HTML.
// app/[locale]/blog/[slug]/page.tsx
import { formatDate } from '@/lib/format-date';
interface Props {
params: Promise<{ locale: string; slug: string }>;
}
export default async function BlogPost({ params }: Props) {
const { locale, slug } = await params;
// In a real app you would fetch the post from a DB or CMS
const publishedAt = new Date('2025-06-07T09:00:00Z');
return (
<article>
<time dateTime={publishedAt.toISOString()}>
{formatDate(publishedAt, locale, { dateStyle: 'full', timeStyle: 'short' })}
</time>
<h1>Post: {slug}</h1>
</article>
);
}Formatera tal och valutor
Intl.NumberFormat hanterar tre huvudsakliga användningsområden:
- Vanliga tal — decimaltecken och gruppering varierar mellan lokaler (
1,234.56jämfört med1.234,56) - Valutor — symbolens placering, antal decimaler och till och med valutanamnet kan variera
- Enheter — kilogram, miles, byte med mera, formaterade enligt lokala konventioner
Skicka alltid med currency tillsammans med style: 'currency'. Valutakoden (ISO 4217) anger vilken symbol som ska användas, medan lokalen anger var den ska placeras.
// lib/format-number.ts
export function formatCurrency(
amount: number,
currency: string,
locale: string
): string {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(amount);
}
export function formatNumber(
value: number,
locale: string,
options?: Intl.NumberFormatOptions
): string {
return new Intl.NumberFormat(locale, options).format(value);
}
// formatCurrency(1234.5, 'USD', 'en-US') => '$1,234.50'
// formatCurrency(1234.5, 'EUR', 'de-DE') => '1.234,50 €'
// formatCurrency(1234.5, 'TRY', 'tr-TR') => '₺1.234,50'En fristående Intl-demonstration (körbar)
Kodsnutten nedan är ett komplett och fristående TypeScript-program som demonstrerar Intl.DateTimeFormat och Intl.NumberFormat för flera lokaler. Inget ramverk eller externt paket behövs — du kan köra det med ts-node eller klistra in det i en TypeScript-lekplats.
const locales = ['en-US', 'de-DE', 'tr-TR', 'ja-JP', 'ar-SA'];
const date = new Date('2025-06-07T14:30:00Z');
const price = 9999.99;
for (const locale of locales) {
const formattedDate = new Intl.DateTimeFormat(locale, {
dateStyle: 'medium',
timeStyle: 'short',
}).format(date);
const formattedPrice = new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'USD',
}).format(price);
console.log(`[${locale}] date: ${formattedDate} | price: ${formattedPrice}`);
}Pluralregler — den dolda komplexiteten
Engelskan har två pluralformer: 1 item jämfört med 2 items. Arabiskan har däremot sex, ryskan tre och polskan fyra. Om du bygger pluralisering med en enkel kontroll som count === 1 ? 'item' : 'items' blir appen felaktig för större delen av världen.
Intl.PluralRules löser detta genom att returnera rätt CLDR-pluralkategori för ett visst tal och en viss lokal:
- zero
- one
- two
- few
- many
- other
Du kopplar varje kategori till rätt översatta sträng i din meddelandekatalog och låter sedan PluralRules välja rätt nyckel vid körning.
Implementera en pluralize-hjälpfunktion
Hjälpfunktionen nedan tar emot ett antal, en lokal och en karta med strängar för pluralformer. Den använder Intl.PluralRules för att välja rätt form och ersätter sedan platshållaren {{count}} med det faktiska talet.
På så sätt hålls pluraliseringslogiken utanför dina översättningsfiler — filerna behöver bara mallarna för de olika kategorierna, inte villkorskod.
// lib/pluralize.ts
type PluralForms = Partial<Record<Intl.LDMLPluralRule, string>>;
export function pluralize(
count: number,
locale: string,
forms: PluralForms
): string {
const rules = new Intl.PluralRules(locale);
const category = rules.select(count); // 'zero'|'one'|'two'|'few'|'many'|'other'
const template = forms[category] ?? forms['other'] ?? '';
return template.replace('{{count}}', String(count));
}
// English
// pluralize(1, 'en', { one: '{{count}} item', other: '{{count}} items' })
// => '1 item'
// pluralize(5, 'en', { one: '{{count}} item', other: '{{count}} items' })
// => '5 items'
// Arabic (6 forms)
// pluralize(11, 'ar', { zero:'...', one:'...', two:'...', few:'...', many:'{{count}} عنصرًا', other:'...' })
// => '11 عنصرًا'Använda pluralize i en Server Component
Kombinera hjälpfunktionen pluralize med lokaliserad talformatering för en komplett lösning som är redo för produktion. Varukorgssammanfattningen nedan visar både antal artiklar och totalpris, korrekt formaterade för alla lokaler.
// app/[locale]/cart/page.tsx
import { pluralize } from '@/lib/pluralize';
import { formatCurrency } from '@/lib/format-number';
interface Props {
params: Promise<{ locale: string }>;
}
// Minimal translation catalog — in real projects use next-intl or similar
const itemForms: Record<string, Record<string, string>> = {
'en-US': { one: '{{count}} item', other: '{{count}} items' },
'de-DE': { one: '{{count}} Artikel', other: '{{count}} Artikel' },
'tr-TR': { one: '{{count}} ürün', other: '{{count}} ürün' },
};
export default async function CartPage({ params }: Props) {
const { locale } = await params;
const itemCount = 3;
const total = 129.99;
const forms = itemForms[locale] ?? itemForms['en-US'];
return (
<section>
<p>{pluralize(itemCount, locale, forms)}</p>
<p>Total: {formatCurrency(total, 'USD', locale)}</p>
</section>
);
}Relativ tidsformatering med Intl.RelativeTimeFormat
Intl.RelativeTimeFormat formaterar tidsintervall i förhållande till nu — för 3 dagar sedan, om 2 timmar — för alla lokaler och numeriska stilar.
- numeric: 'always' — använder alltid tal: för 1 dag sedan
- numeric: 'auto' — använder naturligt språk när det är möjligt: i går
Hjälpfunktionen nedan beräknar automatiskt den lämpligaste enheten och delegerar strängen till API:et.
// lib/format-relative.ts
export function formatRelative(date: Date, locale: string): string {
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
const diffMs = date.getTime() - Date.now();
const diffSec = Math.round(diffMs / 1000);
const thresholds: [number, Intl.RelativeTimeFormatUnit][] = [
[60, 'second'],
[3600, 'minute'],
[86400, 'hour'],
[2592000, 'day'],
[31536000, 'month'],
];
for (const [limit, unit] of thresholds) {
if (Math.abs(diffSec) < limit) {
const divisor = unit === 'second' ? 1
: unit === 'minute' ? 60
: unit === 'hour' ? 3600
: unit === 'day' ? 86400
: 2592000;
return rtf.format(Math.round(diffSec / divisor), unit);
}
}
return rtf.format(Math.round(diffSec / 31536000), 'year');
}
// formatRelative(new Date(Date.now() - 90000), 'en-US') => '2 minutes ago'
// formatRelative(new Date(Date.now() - 90000), 'de-DE') => 'vor 2 Minuten'Skapa en återanvändbar FormattedDate-klientkomponent
Ibland behöver du formatera datum på klienten — till exempel när datumet ändras efter en användarinteraktion. En tunn Client Component som läser navigator.language undviker hydreringsskillnader genom att låta webbläsaren välja sin egen lokal.
Observera direktivet 'use client'. Komponenten skickar inte med någon Intl-polyfill, eftersom alla moderna webbläsare och Node 18+ har inbyggt stöd för hela Intl-specifikationen.
'use client';
import { useMemo } from 'react';
interface Props {
date: string; // ISO string — safe to serialize from Server to Client
options?: Intl.DateTimeFormatOptions;
}
export function FormattedDate({ date, options = { dateStyle: 'medium' } }: Props) {
// navigator.language gives the browser's locale, e.g. 'en-GB'
const formatted = useMemo(() => {
return new Intl.DateTimeFormat(navigator.language, options).format(
new Date(date)
);
}, [date, options]);
return <time dateTime={date}>{formatted}</time>;
}Kunskapskontroll: pluralformer och Intl.PluralRules
Utifrån det du har lärt dig i den här lektionen ska du besvara följande fråga om Intl.PluralRules och lokaliserad pluralisering.
Sammanfattning: lokaliserad formatering i Next.js 15
I den här lektionen har du lärt dig att använda de inbyggda Intl-API:erna för att korrekt formatera datum, tal, valutor, relativa tider och pluraliserade strängar för alla lokaler — utan tredjepartsbibliotek.
- Intl.DateTimeFormat — formaterar datum och tider; använd
dateStyle/timeStyleför snabb formatering eller enskilda fältalternativ för detaljerad kontroll. - Intl.NumberFormat — hanterar vanliga tal, valutor (
style: 'currency') och enheter; kombinera alltid en valutakod med lokalen. - Intl.RelativeTimeFormat — skapar lokalkorrekta relativa strängar som i går eller vor 2 Minuten.
- Intl.PluralRules — väljer CLDR-pluralkategorin (zero / one / two / few / many / other), så att din översättningskatalog kan tillhandahålla rätt form för varje språk.
- I Next.js 15 App Router kör du dessa formaterare i Server Components för att undvika hydreringsskillnader och bundle-kostnader. Använd en
'use client'-wrapper mednavigator.languageendast när lokalidentifiering på klienten behövs.
Dessa fyra Intl-API:er täcker de allra flesta behoven inom i18n-formatering utan att du behöver ta till ett omfattande bibliotek.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 22
- Lektioner
- 88
Vanliga frågor
Är lektionen ”Formatera datum, tal och pluralformer per lokal” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Next.js 15 fullstack (App Router + Server Actions), inklusive ”Formatera datum, tal och pluralformer per lokal”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Next.js 15 fullstack (App Router + Server Actions) innehåller totalt 4 lektioner.
Vad lär jag mig i ”Formatera datum, tal och pluralformer per lokal”?
Använd Intl-API:er för att återge lokalkorrekt datum, valutor och pluraliserade strängar. Ni övar på Next.js 15 fullstack (App Router + Server Actions) med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Next.js 15 fullstack (App Router + Server Actions)?
Du behöver inga förkunskaper. Utbildningen i Next.js 15 fullstack (App Router + Server Actions) på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Formatera datum, tal och pluralformer per lokal”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Next.js 15 fullstack (App Router + Server Actions)-lektionen?
Ja. Varje Next.js 15 fullstack (App Router + Server Actions)-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Lokalisering och subpath-routing med middleware
- Översättningsladdning på serversidan och meddelandekataloger
- Lokaliserade metadata, webbplatskartor och hreflang
- Formatera datum, tal och pluralformer per lokal