Laravel localization in Korean 한국어
Everything you need to ship Korean in a Laravel app: the right locale codes,
the exact plural forms trans_choice() expects,
real localized Carbon output and Hangul-script considerations.
Every value on this page was generated by running ICU, CLDR and Carbon — not copied from another article.
ISO 639-1
ko
Script / Direction
Hangul · LTR
Plural forms (Laravel)
1
Text vs English
Contracts
Locale codes
Set the base locale in config/app.php. For regional variants,
Korean commonly uses:
ko_KR
// config/app.php
'locale' => 'ko',
'fallback_locale' => 'en',
// Or switch at runtime
App::setLocale('ko');
Plural rules: what Korean actually needs
CLDR defines 1 cardinal category for Korean. The sample numbers below were computed by ICU for this exact locale:
| CLDR category | Numbers that select it |
|---|---|
| other | 0–130, 200, 1000, 1000000, 1.5 |
Laravel's trans_choice() maps numbers to
1 pipe-separated
form for this locale:
| Form index | Numbers that select it |
|---|---|
| 0 | 0–130, 200, 1000 |
// lang/ko/messages.php
'items' => ':count'
// Usage
trans_choice('messages.items', $count, ['count' => $count]);
This language has no grammatical plural, so a single form covers every number.
Try any number live in the pluralization tester.
Localized dates with Carbon
Real output for Korean (ko locale),
generated by Carbon for March 21, 2026:
$date = now()->locale('ko');
$date->translatedFormat('l, j F Y');
// "토요일, 21 3월 2026"
$date->isoFormat('LLLL');
// "2026년 3월 21일 토요일 오후 2:30"
$date->isoFormat('L');
// "2026.03.21."
$date->subDays(3)->diffForHumans();
// "3개월 전"
What to watch out for in Korean
- Honorific speech levels are grammatical; the polite -요/-습니다 styles are standard for UI copy.
- Particles change form depending on whether the preceding word ends in a consonant or vowel (은/는, 이/가), so appending them to placeholders breaks grammar.
- Subject-object-verb word order; no grammatical gender or plural agreement.
- Dates are written year-first (2026년 3월 1일).
Particles change with the preceding syllable
Korean marks the grammatical role of a noun with a particle attached to it. Several of these particles have two forms, and which one applies depends on whether the preceding syllable ends in a consonant — the batchim, or final consonant. This is the single most important thing to understand before putting a placeholder anywhere near Korean text.
| Role | After a consonant | After a vowel |
|---|---|---|
| Topic | 은 (책은) | 는 (파일는 → 파일은*) |
| Subject | 이 (책이) | 가 (파일이 → 파일가*) |
| Object | 을 (책을) | 를 (파일를 → 파일을*) |
| And / with | 과 (책과) | 와 (파일와) |
| To | 으로 (책으로) | 로 (파일로) |
So a template that appends 를 to a variable produces correct Korean when the value ends in a vowel and incorrect Korean when it ends in a consonant. Roughly half of all values will be wrong, and to a Korean reader the error is as obvious as writing "a apple" in English.
Why the particle cannot be baked into a template
// English: 'Delete :name'
// Korean needs the object particle to match
// the last syllable of the name:
//
// 파일 (ends in vowel) -> 파일을
// 프로젝트 (ends in vowel) -> 프로젝트를
// 문서 (ends in vowel) -> 문서를
// 앨범 (ends in consonant) -> 앨범을
//
// ':name를 삭제' is wrong for half the values.
The particle can be computed, because Hangul is algorithmically decomposable: a syllable block's final consonant is derivable from its Unicode code point. If you must interpolate nouns, calculate the particle rather than hardcoding it.
Deriving the particle from the last syllable
<?php
function hasBatchim(string $word): bool
{
$last = mb_substr($word, -1);
$code = mb_ord($last, 'UTF-8');
// Hangul syllables occupy U+AC00–U+D7A3
if ($code < 0xAC00 || $code > 0xD7A3) {
return false;
}
return (($code - 0xAC00) % 28) !== 0;
}
$particle = hasBatchim($name) ? '을' : '를';
That works for native Korean words. It fails for Latin names, numbers and acronyms, where the particle follows the pronunciation rather than the spelling, and pronunciation is not derivable from the characters. The safer approach remains a complete sentence per key, with the variable quoted so no particle attaches to it directly.
Speech levels are the register decision
Korean encodes politeness in verb endings, with several distinct speech levels. Software has settled on two of them, which makes the choice simpler than the full grammatical picture suggests.
| Level | Ending | Used for |
|---|---|---|
| 합쇼체 (formal) | -습니다 / -ㅂ니다 | Notices, errors, formal messages |
| 해요체 (polite) | -어요 / -아요 | Conversational interfaces, consumer apps |
| 해라체 (plain) | -다 | Headings, labels, documentation |
| 반말 (casual) | -어 / -아 | Never in software |
Most Korean software mixes deliberately: the formal -습니다 for system messages and errors, and the plain declarative or a bare noun for buttons and headings. Buttons are conventionally nouns — 저장 (save), 삭제 (delete), 취소 (cancel) — which avoids the question entirely for short labels, exactly as in Japanese.
Korean also avoids second-person pronouns in interfaces. 당신 (you) is grammatically correct and sounds distant or confrontational in an application; natural Korean omits the subject or uses the person's name with an honorific. A literal translation of "You have 3 messages" that includes 당신 immediately reads as translated text.
Honorific verb forms exist for referring respectfully to the user's own actions, marked with the infix -시-. These appear in customer-facing messages from a service to a user, so a translator will use them in places an English source gives no hint about.
No plurals, but counters everywhere
Korean has no obligatory grammatical plural. CLDR gives it a single category, so trans_choice() takes one form that serves every number. A plural marker 들 exists but is optional and sounds unnatural when a number is already present.
One form for every count
// lang/ko/messages.php
'files' => '파일 :count개',
// 0 -> 파일 0개
// 1 -> 파일 1개
// 42 -> 파일 42개
As in Japanese, the complication moves to counters. Korean requires a classifier between the number and the noun, chosen by what is being counted, so a single generic counting string cannot be reused across contexts.
| Counter | Used for | Example |
|---|---|---|
| 개 | Generic objects, items | 파일 3개 |
| 명 | People | 사용자 3명 |
| 장 | Flat things: pages, images | 이미지 3장 |
| 건 | Records, cases, transactions | 주문 3건 |
| 번 | Occurrences, attempts | 시도 3번 |
| 대 | Machines, vehicles | 기기 3대 |
Korean also has two number systems — native Korean and Sino-Korean — and which one is spoken depends on the counter. This does not change the written digits, so it rarely affects an interface, but it matters for any voice output built on the same strings.
Hangul, spacing and line breaking
Hangul is an alphabet arranged into syllable blocks: each block encodes two or three letters and occupies one square cell. This makes Korean visually dense like Chinese or Japanese while being alphabetic underneath, which has consequences for both layout and text processing.
Korean uses spaces between words, unlike Japanese and Chinese, and the spacing rules (띄어쓰기) are genuinely difficult — even native speakers disagree on some cases. Do not attempt to normalise or insert spacing programmatically; treat the translator's spacing as authoritative.
Line breaking has a subtlety worth setting explicitly. Because Korean is syllabic, browsers may break a line between any two syllable blocks rather than at word boundaries, which is technically permitted and looks careless. Declaring word-based breaking produces noticeably better typography.
Prefer word boundaries for Korean
<p lang="ko" class="[word-break:keep-all] [overflow-wrap:break-word]">
사용자 계정 설정이 저장되었습니다.
</p>
/* keep-all stops the browser breaking mid-word
between syllable blocks; overflow-wrap still
rescues genuinely over-long tokens. */
Korean text runs shorter than English in character count but each character is full-width, so rendered width lands close to the English original. Overflow is rare. As with Japanese, dense glyphs need more line height and suffer badly at small font sizes.
Text entry goes through an input method that composes syllable blocks as the user types. Any JavaScript reacting to every keystroke will fire on incomplete blocks, so live search and validation must respect compositionstart and compositionend rather than the raw input event.
Names, dates and formatting
Korean names are written family name first, with no space in the traditional form: 김민준 has the surname 김. Names are typically three syllables, and a form designed around a long given name and a separate surname field can feel oddly shaped. Store the parts separately and let the locale decide display order.
Surnames are drawn from a small pool — Kim, Lee and Park together account for close to half the population — so any logic treating a surname as distinguishing will collide constantly. Deduplication, search ranking and display disambiguation all need to account for that.
| Korean convention | |
|---|---|
| Date | 2026년 3월 21일 |
| Numeric date | 2026. 3. 21. |
| Weekday | 토요일 (Saturday) |
| Thousands | 1,234,567 |
| Decimal | 1234.56 |
| Currency | ₩1,234 (no decimals) |
| First day of week | Sunday |
Dates run largest unit first with the year, month and day markers 년, 월, 일. Numbers follow English conventions, so there is no decimal-comma hazard. The won has no subunit in circulation, so amounts carry no decimal places — formatting them with two is an immediate sign of code written for dollars, and amounts are large enough that currency fields need room for more digits than a euro design assumes.
Korean addresses have been officially road-based since 2014, but the older lot-based system is still in common use, and address forms are ordered largest unit first: province, city, district, street, building. An address form laid out in Western order will confuse users even when every field is translated.
Getting Korean into the application
Korean exercises input handling, typography and string architecture at once, and the wiring around the translations causes as many visible defects as the translations themselves.
Start with the input method, because it affects every text field in the product. Any behaviour bound to keystrokes — live search, character counters, inline validation, autosave — must wait for the composition to finish. A counter that counts partial syllable blocks reports wrong numbers, and validation that runs mid-composition rejects text the user is still in the middle of typing. Bind to compositionend and treat input as authoritative only when no composition is active.
Storage needs utf8mb4 throughout. Hangul syllables sit inside the Basic Multilingual Plane and are safe in three-byte encodings, but Korean text routinely carries emoji and occasionally rare Hanja that are not, and MySQL's utf8 will either reject the insert or truncate the field at the offending character.
Sorting requires a locale-aware collator. Korean orders by the alphabet underlying the syllable blocks rather than by code point, and while the two happen to coincide for much of the range, mixed text containing Hanja or Latin will not sort acceptably without it. Search should also normalise fullwidth Latin characters, which Korean keyboards can produce, using NFKC.
Finally, write the string architecture for particles from the beginning. Deciding later that variables must be quoted and messages must be complete means revisiting every interpolated string in the product, and it is the one Korean problem that cannot be fixed by retranslation.
What ships broken most often
- Hardcoded particles. 를 or 을 baked into a template, wrong for roughly half of all interpolated values.
- Live search firing during IME composition. Queries sent for half-formed syllable blocks.
-
Mid-word line breaks. Missing
word-break: keep-all, so text breaks between syllables. - A shared counter across contexts. 개 used for people, or 명 used for files.
- 당신 in interface copy. A literal "you" that natural Korean omits.
- Won shown with decimals. ₩1,234.00 rather than ₩1,234.
- Name order reversed. Display names assembled given-first, or address forms in Western order.
The particle problem is the one that distinguishes competent Korean localisation from the rest. It cannot be solved by better translation, only by string architecture: complete messages per key, and variables quoted so no particle attaches to them. Teams that get this right ship Korean that reads as written rather than as assembled.
Install the Laravel-Lang Korean files for framework strings rather than translating validation and authentication messages yourself. They already apply the correct speech level consistently and handle particles and counters across every rule in the framework, which is a considerable amount of detail to reproduce by hand.
Korea also has an unusually demanding audience for software quality. English proficiency is lower than in northern Europe, so untranslated strings genuinely block users rather than merely irritating them, and domestic products set a high bar for polish. A partially translated Korean interface reads worse there than the equivalent gap would in the Netherlands or Scandinavia.
Framework strings already translated
Laravel's own validation, auth and pagination strings are maintained in Korean 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 ko
php artisan lang:update
Translate your app into Korean today
Import your lang files, translate every key into Korean with one AI click, and publish changes live — no deploy. Set up in 5 minutes.