Laravel localization in Polish Polski
Everything you need to ship Polish in a Laravel app: the right locale codes,
the exact plural forms trans_choice() expects,
real localized Carbon output and Latin-script considerations.
Every value on this page was generated by running ICU, CLDR and Carbon — not copied from another article.
ISO 639-1
pl
Script / Direction
Latin · LTR
Plural forms (Laravel)
3
Text vs English
Expands
Locale codes
Set the base locale in config/app.php. For regional variants,
Polish commonly uses:
pl_PL
// config/app.php
'locale' => 'pl',
'fallback_locale' => 'en',
// Or switch at runtime
App::setLocale('pl');
Plural rules: what Polish actually needs
CLDR defines 4 cardinal categories for Polish. The sample numbers below were computed by ICU for this exact locale:
| CLDR category | Numbers that select it |
|---|---|
| one | 1 |
| few | 2–4, 22–24, 32–34, 42–44, 52–54, 62–64, … |
| many | 0, 5–21, 25–31, 35–41, 45–51, 55–61, … |
| other | 1.5 |
Laravel's trans_choice() maps numbers to
3 pipe-separated
forms for this locale:
| Form index | Numbers that select it |
|---|---|
| 0 | 1 |
| 1 | 2–4, 22–24, 32–34, 42–44, 52–54, 62–64, … |
| 2 | 0, 5–21, 25–31, 35–41, 45–51, 55–61, … |
// lang/pl/messages.php
'items' => ':count item|:count items'
// Usage
trans_choice('messages.items', $count, ['count' => $count]);
This language uses 3 plural forms. Laravel's built-in trans_choice only resolves two, so for grammatically correct output use an ICU MessageFormat package or handle the extra forms explicitly against the CLDR categories above.
Try any number live in the pluralization tester.
Localized dates with Carbon
Real output for Polish (pl locale),
generated by Carbon for March 21, 2026:
$date = now()->locale('pl');
$date->translatedFormat('l, j F Y');
// "sobota, 21 marca 2026"
$date->isoFormat('LLLL');
// "sobota, 21 marca 2026 14:30"
$date->isoFormat('L');
// "21.03.2026"
$date->subDays(3)->diffForHumans();
// "3 miesiące temu"
What to watch out for in Polish
- Seven grammatical cases: noun forms change inside sentences, so avoid raw placeholder insertion.
- Complex plural rules (one/few/many/other): 2-4 and 5+ take different forms, and 12-14 behave differently again.
- Three grammatical genders with adjective and past-tense verb agreement; ty/Pan-Pani formal distinction.
- Decimal comma with space as thousands separator (1 234,56).
Three plural forms, and the pattern that repeats
Polish uses four CLDR categories, and the selection rule is unlike anything in Western European languages: it depends on the last digit and the last two digits together, so the forms cycle rather than simply increasing with the count. A translation supplying only a singular and a plural will be grammatically wrong across most of the number range, and it will be wrong silently.
| Category | Selected by | Example |
|---|---|---|
| one | 1 | 1 plik |
| few | 2–4, 22–24, 32–34… | 3 pliki |
| many | 0, 5–21, 25–31… | 5 plików |
| other | decimals | 1,5 pliku |
The cycle is what catches people out. Twenty-two takes the few form because it ends in two, while twelve takes many because the teens are exceptions. So the sequence runs one, few, few, few, many … many, few, few, few, many, and repeats every hundred with the teens excluded.
Four forms in CLDR order
// lang/pl/messages.php
// one|few|many|other
'files' => ':count plik|:count pliki|:count plików|:count pliku',
trans_choice('messages.files', $count, ['count' => $count]);
Note that zero takes the many form rather than a form of its own, which is different from English convention but handled correctly by Laravel once the locale is set. The other category appears only for fractional counts, so it is easy to fill in wrongly by copying whichever form seemed closest.
Verify with real numbers rather than by inspection. The values worth testing are 1, 2, 5, 12, 22 and 1.5 — six checks that between them exercise every branch of the rule and catch the mis-ordering that is otherwise invisible to anyone who does not read Polish.
Seven cases and five plural genders
Polish nouns inflect for seven cases, and every noun carries a gender that determines which endings apply. In the singular there are three genders; in the plural Polish splits further into virile (groups including men) and non-virile (everything else), which effectively gives five agreement patterns.
| Case | Role | "file" (plik) |
|---|---|---|
| Nominative | subject | plik |
| Genitive | of / negation | pliku |
| Dative | to / for | plikowi |
| Accusative | direct object | plik |
| Instrumental | by means of | plikiem |
| Locative | about / in | pliku |
| Vocative | addressing | pliku |
A placeholder holding a noun therefore cannot be reused across sentences. Usuń plik (delete the file) takes the accusative, while Kopia pliku (copy of the file) needs the genitive, and a single stored value will be wrong in one of them. This is the same structural problem as in Czech, with two more genders to get wrong.
Negation adds a rule that surprises developers: a negated verb takes the genitive rather than the accusative. Mam plik becomes Nie mam pliku, so the noun changes form purely because the sentence turned negative. Error and empty-state messages are full of negation, which is exactly where interface copy tends to be assembled from parts.
Personal names decline too. Piotr Nowak becomes Piotra Nowaka in the genitive and Piotrze in the vocative, which is the form used when addressing someone directly. Polish users accept the nominative in interfaces, but a greeting that reads Cześć, Piotr rather than Cześć, Piotrze is noticeably stilted.
Pan and Pani: formality that is also gendered
Polish formal address does not use a pronoun equivalent to German Sie or French vous. It uses the honorific nouns Pan (to a man) and Pani (to a woman), with third-person verb forms. That means formal Polish copy has to know the reader's gender, which informal copy largely avoids.
| English | Informal (ty) | Formal to a man | Formal to a woman |
|---|---|---|---|
| Your account | twoje konto | Pana konto | Pani konto |
| Do you want to continue? | Chcesz kontynuować? | Czy chce Pan kontynuować? | Czy chce Pani kontynuować? |
| You saved | zapisałeś / zapisałaś | zapisał Pan | zapisała Pani |
Even the informal form is gendered in the past tense: a man saved is zapisałeś and a woman saved is zapisałaś. So Polish shares the Hebrew and Hindi problem of second-person verbs committing to a gender, in every past-tense sentence addressed to the user.
Most Polish software solves this the way Hebrew interfaces do: by avoiding direct address. Impersonal constructions and verbal nouns carry no gender — Zapisano (it has been saved) rather than Zapisałeś (you saved) — and this is standard, natural Polish rather than an awkward workaround. Buttons use infinitives: Zapisz, Anuluj, Usuń.
Consumer software generally uses informal ty with impersonal past forms. Banking, insurance, government and formal B2B use Pan and Pani, which means those products genuinely need the user's gender or must restructure every formal sentence to avoid it.
Diacritics, ł, and sorting
Polish uses nine letters with diacritics: ą, ć, ę, ł, ń, ó, ś, ź and ż. They are distinct letters of the alphabet rather than decorated vowels, and they are meaning-bearing — los (fate) and łoś (elk) are unrelated words.
The letter ł is the one most often damaged in transit. It is a stroked L rather than an accented character, so it does not decompose into a base letter plus a combining mark, and normalisation routines that strip accents by decomposing will leave it untouched while removing everything else — producing text that is half-normalised and matches nothing.
Sorting Polish correctly
<?php
// Wrong: byte order puts every diacritic after z
sort($words);
// Right: Polish collation interleaves them
$collator = new Collator('pl_PL');
$collator->sort($words);
// Correct order: ... l, ł, m ... s, ś, t ... z, ź, ż
Polish sorts each accented letter immediately after its base letter, so ł follows l and ż follows ź which follows z. A byte-order sort places all of them after the entire Latin alphabet, which produces a list Polish users read as unsorted.
Search should fold diacritics for matching while preserving them for display. Polish keyboards make the characters easy to type, but users on phones or foreign layouts frequently omit them, and requiring an exact match turns a working search into a frustrating one.
Layout and formatting
Polish expands roughly twenty to thirty per cent over English. It has no articles, which saves some space, but case endings and longer word stems more than compensate, and consonant clusters make words look longer than their character count suggests.
| English | Polish | Growth |
|---|---|---|
| Save | Zapisz | +50% |
| Settings | Ustawienia | +25% |
| Cancel | Anuluj | 0% |
| Sign in | Zaloguj się | +57% |
| Search | Szukaj | 0% |
| Forgot password? | Nie pamiętasz hasła? | +18% |
| Polish convention | |
|---|---|
| Thousands | 1 234 567 (non-breaking space) |
| Decimal | 1234,56 |
| Currency | 1 234,56 zł (after the amount) |
| Short date | 21.03.2026 |
| Long date | 21 marca 2026 |
| First day of week | Monday |
Long dates put the month in the genitive — marca rather than the nominative marzec — and month names are lowercase. Both come free from Carbon with the locale set and are wrong in any formatter that looks month names up from a list.
Poland uses the złoty rather than the euro despite being in the European Union, which billing code written for a generic European market regularly gets wrong. The decimal comma creates the usual numeric-input hazard: floatval('1234,56') returns 1234 and discards the grosze.
Writing source strings Polish can absorb
Most Polish defects trace back to decisions made in the English source, before a translator ever sees the string. Fixing them in Polish is impossible; fixing them in English is cheap, and it improves every other inflected locale at the same time.
Write one key per complete message. Where English would use a template with a noun placeholder, write the variants out. Seven cases, three singular genders and the virile split mean a template has too many correct outputs for any runtime rule to choose between, and the negation rule adds another dimension on top.
Where a variable is genuinely unavoidable — a project name, a filename — quote it and let the grammar attach to a fixed noun you control. Usunięto plik „raport.pdf” puts the case ending on plik and leaves the variable in its base form, which Polish readers accept as a citation.
Prefer impersonal constructions in the source. An English string written as "Changes saved" translates cleanly into Zapisano zmiany; one written as "You saved your changes" forces the translator into a gendered past tense with no way to know the reader. The impersonal form is better English too, so this costs nothing.
Give translators the count values that will actually occur. A string that only ever displays 1 or 2 needs different care from one that can show any number, and a translator told nothing will sometimes leave the other decimal form as a copy of another category — harmless if fractions never appear, wrong the moment they do.
What ships broken most often
- Two plural forms instead of four. Wrong for most counts, and the cyclical rule means the errors recur every hundred.
- Nouns interpolated into sentences. Seven cases plus negation-driven case changes make templates unfixable.
- Gendered past tense with no gender known. Zapisałeś shown to every user regardless.
- Sorting that dumps diacritics after z. A byte sort rather than a Polish collator.
- ł surviving a normalisation that stripped everything else. Half-folded text that matches nothing.
- Nominative months in long dates. marzec instead of marca.
- Euro assumed for a Polish user. Poland uses the złoty.
The impersonal construction is the single most useful thing to learn about Polish interface copy. Adopting it removes the gender problem, reads as natural Polish rather than as a compromise, and costs nothing — but only if translators are told to use it, because a translator working from an English second-person source will faithfully reproduce the second person.
Install the Laravel-Lang Polish files for framework strings. Validation messages require correct four-form plurals and case agreement across dozens of rules, and reproducing that by hand is substantial linguistic work already done and reviewed by native speakers.
Framework strings already translated
Laravel's own validation, auth and pagination strings are maintained in Polish by the open-source Laravel-Lang project (MIT). Install them, then manage your app's own strings live:
composer require laravel-lang/common --dev
php artisan lang:add pl
php artisan lang:update
Translate your app into Polish today
Import your lang files, translate every key into Polish with one AI click, and publish changes live — no deploy. Set up in 5 minutes.