Swift
iOS Development
Localization
Programming
Language Code

How to get current language code with Swift?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Reading the current language code in Swift is a common localization task, but the correct API depends on what you really mean by "current." Sometimes you want the user's preferred app language order, and other times you want the device's active locale settings for formatting dates, numbers, and text.

Get the User's Preferred Language List

If your goal is to know which languages the user prefers for content selection, start with Locale.preferredLanguages. The first entry is usually the highest-priority language configured in iOS settings.

swift
1import Foundation
2
3let preferred = Locale.preferredLanguages
4print(preferred)
5
6if let firstLanguage = preferred.first {
7    print("Top preferred language: \(firstLanguage)")
8}

This often returns identifiers such as en-CA, fr-CA, or es-US. These values are more specific than a bare language code because they can include a region component.

Extract Just the Language Code

If you need only the language portion, parse the identifier through Locale rather than splitting strings by hand.

swift
1import Foundation
2
3if let identifier = Locale.preferredLanguages.first {
4    let locale = Locale(identifier: identifier)
5    print("Language code: \(locale.language.languageCode?.identifier ?? "unknown")")
6}

On newer Swift and Foundation APIs, the language property provides a structured way to access the code. This is cleaner than relying on ad hoc string operations.

Compare With Locale.current

Locale.current is related but not identical. It describes the user's active locale preferences for formatting and cultural conventions on the current device. That can matter for currency, decimal separators, calendars, and region settings.

swift
1import Foundation
2
3let current = Locale.current
4print("Locale identifier: \(current.identifier)")
5print("Language code: \(current.language.languageCode?.identifier ?? "unknown")")
6print("Region code: \(current.region?.identifier ?? "unknown")")

Use this when the question is "how should I format data for this user?" rather than "which localized bundle should my app prefer first?"

Use the Result in Localization Logic

In most apps, you should not manually load strings by language code unless you have a specific need. Apple's localization system already picks the best matching .lproj bundle when your project is configured correctly.

Still, there are valid cases for checking the preferred code yourself, such as custom server-side content negotiation or analytics.

swift
1import Foundation
2
3func apiLanguageHeader() -> String {
4    guard let preferred = Locale.preferredLanguages.first else {
5        return "en"
6    }
7
8    let locale = Locale(identifier: preferred)
9    return locale.language.languageCode?.identifier ?? "en"
10}
11
12print(apiLanguageHeader())

That example sends only the language code. If your backend needs a more specific locale such as en-CA, send the full preferred identifier instead.

Choose Stable Behavior in Tests

Locale-sensitive code is easy to test incorrectly because it depends on device settings. A safer approach is to isolate the lookup behind a small function or protocol and inject a known language identifier in tests.

swift
1import Foundation
2
3protocol LanguageProviding {
4    var preferredLanguages: [String] { get }
5}
6
7struct SystemLanguageProvider: LanguageProviding {
8    var preferredLanguages: [String] { Locale.preferredLanguages }
9}

With that boundary in place, unit tests can provide a fake implementation and verify your app logic without depending on whatever simulator language happens to be active.

Common Pitfalls

  • Treating Locale.current and Locale.preferredLanguages.first as if they answer the exact same question.
  • Splitting locale identifiers manually instead of asking Locale for structured components.
  • Forcing custom bundle selection when the built-in iOS localization system already does the job.
  • Assuming the returned value is always a bare code such as en rather than a locale identifier such as en-CA.
  • Writing tests that rely on the simulator or device language instead of injecting a stable value.

Summary

  • Use Locale.preferredLanguages.first to inspect the user's preferred app language order.
  • Use Locale.current when you need formatting and locale conventions.
  • Parse identifiers through Locale to extract language codes safely.
  • Prefer the built-in Apple localization system unless you have a clear reason to customize.
  • Isolate locale lookup in tests so language-dependent behavior stays deterministic.

Course illustration
Course illustration

All Rights Reserved.