Locale-Aware Formatting
Format numbers, dates, and currencies per locale.
Locale-Aware Formatting is a free Swift Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Numbers Are Not Universal
The number one million two hundred thousand reads as 1,200,000.50 in the US, 1.200.000,50 in Germany, and 12,00,000.50 in India. Hardcoding separators or formats breaks for most of the world. Swift's FormatStyle API handles this correctly per locale.
import Foundation
let value = 1_200_000.5
print(value.formatted()) // uses current localeThe formatted() Entry Point
Most standard types — numbers, dates, measurements, lists — have a formatted() method. With no arguments it uses sensible locale-aware defaults; pass a style to customize.
import Foundation
let n = 1234.567
print(n.formatted()) // default
print(n.formatted(.number.precision(.fractionLength(2))))Number Styles
.number is the workhorse. You can configure grouping, fraction length, rounding, and sign display fluently. The locale still controls the actual separator characters.
import Foundation
let x = 1234.5
print(x.formatted(
.number
.grouping(.automatic)
.precision(.fractionLength(0...2))))Currency Formatting
For money, .currency(code:) places the symbol, grouping, and decimal places correctly for the locale. The same amount renders as $1,200.00 or 1.200,00 €€ depending on the user's region — never build currency strings by hand.
import Foundation
let price = 1200.0
print(price.formatted(.currency(code: "USD")))
print(price.formatted(.currency(code: "EUR")))
print(price.formatted(.currency(code: "JPY")))Percent Formatting
.percent multiplies by 100 and appends the locale's percent sign, handling the spacing rules some languages require between number and symbol.
import Foundation
let ratio = 0.875
print(ratio.formatted(.percent))
print(ratio.formatted(.percent.precision(.fractionLength(1))))Overriding the Locale
By default formatting uses Locale.current. To force a specific locale — for testing, or to show a value in a fixed region — chain .locale(_:) onto any style.
import Foundation
let value = 1234567.89
let german = Locale(identifier: "de_DE")
print(value.formatted(.number.locale(german)))
// 1.234.567,89Date Formatting
Dates have their own styles. .dateTime lets you compose the fields you want (year, month, day, hour) and the system orders them per locale — month-day-year in the US, day-month-year in much of Europe.
import Foundation
let now = Date()
print(now.formatted(
.dateTime.year().month().day()))
print(now.formatted(date: .long, time: .shortened))Relative Dates
RelativeDateTimeFormatter and the .relative style produce phrases like 2 hours ago or in 3 days, fully translated. Great for feeds and timestamps.
import Foundation
let past = Date().addingTimeInterval(-3600)
let text = past.formatted(
.relative(presentation: .named))
print(text) // e.g. "1 hour ago"Measurements and Units
Measurement formats physical quantities and can convert units. The locale decides whether to show kilometers or miles, and the style localizes the unit name itself.
import Foundation
let distance = Measurement(value: 5, unit: UnitLength.kilometers)
print(distance.formatted())
print(distance.formatted(
.measurement(width: .wide)))Lists and Names
Even joining items respects language. .list(type:) produces apples, oranges, and pears in English and the correct conjunction and separators elsewhere — avoid manually inserting commas and the word and.
import Foundation
let fruits = ["apples", "oranges", "pears"]
print(fruits.formatted(.list(type: .and)))
print(fruits.formatted(.list(type: .or)))Parsing Back
FormatStyles are reversible. A style's parseStrategy (or initializing a value from a string with the style) converts localized text back into a number or date, honoring the same locale rules.
import Foundation
let style = Decimal.FormatStyle.Currency(code: "USD")
let amount = try? Decimal("$1,234.50", format: style)
print(amount ?? 0)Quick Check
Recall the right tool for money.
Recap
You learned locale-aware formatting via FormatStyle:
formatted()gives locale-correct defaults; pass a style to customize..number,.currency(code:),.percent,.dateTime,.relative,.measurement, and.listcover most needs.- Chain
.locale(_:)to override the region; styles can also parse text back. - Never hand-build separators, currency symbols, or date orders.
Frequently asked questions
Is the “Locale-Aware Formatting” lesson free?
Yes — the full text of “Locale-Aware Formatting” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Locale-Aware Formatting”?
Format numbers, dates, and currencies per locale. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Locale-Aware Formatting” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.