Localizing iOS Strings in Xcode

by - 8/23/2025 08:05:00 PM


#NoteToForget 
— Written by someone who’s shipped 4+ localized apps… 
(Still need this post again later 😅)


🧩 The Essentials

Let’s be honest.
We’ve all hardcoded strings in Swift like this:
let message = "This field cannot be left empty”;
Text(message)

At a glance, they look harmless — just strings.
But they’re not just any strings — they’re UI text your users will read, and they’re locked to one language.

Tempting? Absolutely.
Practical? Sure — until your PM casually drops:
“Can we support Indonesian 🇮🇩, German 🇩🇪, and Klingon by next sprint?” 🫠


❌ Why It Doesn’t Cut It

⦿ Scattered Strings – Text is all over the place, making updates and translations a mess.
⦿ No Tooling Support – You miss out on Xcode’s built-in localization tools.
⦿ Hard to Scale – Good luck adding languages or managing translations later.


✅ The Better Way

Use NSLocalizedString() and .strings files like a civilized iOS developer. 

It keeps your code clean, makes your app translatable, and lets Apple do what it does best: hide complexity with keywords. 


🛠️ Environment

◼ Xcode: 16.2
◼ Swift: 5.10


🚀 Workflow That Just Works™


1. Add Localizations

1.1 Add Localizations to Your Project
☞ Go to project navigator 〉 Project 〉Info 〉Localization
☞ Click the ➕ 〉Add: Indonesian, German

1.2 Create Localizable.strings Files
☞ Right-click your project root 〉 New File 〉Resource 〉Strings File 〉 Name it: Localizable.strings
☞ Click Localizable.string 〉File Inspector 〉Localization 〉Check all languages: German and Indonesian


2. Add Translations

▪️Localizable (English)
"alert_empty_field" = "This field cannot be left empty”;

▪️Localizable (Indonesian)
"alert_empty_field" = "Bagian ini tidak boleh kosong”;

▪️Localizable (German)
"alert_empty_field" = "Dieses Feld darf nicht leer sein”;


3. Implement Localization in Code

3.1 Simple Version
let message = NSLocalizedString("alert_empty_field", comment: "”)
Text(message)

3.2 Cleaner Syntax with helper
extension String {
    var localized: String {
        NSLocalizedString(self, comment: "")
    }
}

Usage:
let message = "alert_empty_field".localized
Text(message)

3.3 Modular Approach
The modular version using `Bundle(identifier:)` is generally preferred for multi-module apps, as it allows you to specify which localization bundle to look in rather than relying on the main app bundle.

extension String {
    public func localized(identifier: String -> String {
        let bundle = Bundle(identifier: identifier) ?? .main
        return bundle.localizedString(forKey: self, value: nil, table: nil)
    }
}

Usage:
let message = "alert_empty_field".localized(identifier: “com.enjelhutasoit.App.ModuleName")
Text(message)


🧪 Testing Your Setup

On Simulator

☞ Go to Product 〉Scheme 〉 Edit Scheme
☞ Open Run 〉Options
☞ Set App Language and App Region to test (e.g., Indonesian, German)
☞ Hit Run — your app will launch in that locale.  


On Device

☞ Open Settings 〉 General 〉 Language & Region
☞ Change device language to your target language
☞ Relaunch the app to see live localization


If Changes Don't Appear

▪️Clean your build (Cmd+Shift+K)
▪️Restart Xcode
▪️Double-check you localized the .strings file


📌 Key Takeaways


✅ Localization is easier when organized early
✅ App feels pro and scalable
✅ Fallbacks to English are automatic, no trauma needed
✅ Your future self will love you (again).


🧠 Final Note

Yes, you’ve done this before.
Yes, you forgot the steps.

That’s why this blog post exists: not to teach you something new — just to save your future self from Googling it again.

You’re welcome.
— #NoteToForget

You May Also Like

0 comments