iOS Internationalization and Localization Guide + Demo App

Learn how to prepare your iOS app for localization, translate it with AI, and add translations back into Xcode, all using a SwiftUI demo app.

iOS localization is the process of adapting your app’s text, formatting, and assets to support multiple languages and regions. 

This guide uses a demo app to walk you through the full process, from preparations in Xcode to creating and integrating translations into your project. Our demo app, Bookshelf, is a simple book tracking app that covers the localization scenarios you’re most likely to run into: UI strings, pluralization, and testing locales. 

We’ll be working with SwiftUI and Xcode 15+, using String Catalogs as the primary localization format

Part 1: Understanding iOS Localization

Before jumping into Xcode, it’s worth understanding what localization actually involves and what makes it different from internationalization.

Internationalization vs. Localization in iOS — What’s the Difference?

Internationalization (i18n) and localization (l10n) are two separate stages, and they need to happen in that order.

Internationalization is the technical groundwork. It means structuring your code so that text, images, and formatting can vary by locale without requiring code changes. You do this once, ideally before your first release.

Localization is the ongoing work that follows: writing translations, adjusting layouts, and supplying locale-specific assets for each language you want to support.

Internationalization (i18n)Localization (l10n)
What it isPreparing your code for localizationAdapting your app for a specific locale
WhenBefore your first releaseOngoing, per language
WhoDevelopersDevelopers and translators
ExamplesExtracting strings, using locale-aware formattersTranslating strings, localizing screenshots

The most common mistake is treating localization as a post-launch task, only to find the codebase isn’t ready for it. Going back to fix hardcoded strings, fixed-direction layouts, and non-locale-aware formatters across an existing app takes much longer than building with localization in mind from the start.

Part 2: Setting Up Your Xcode Project

We’ll be working with Bookshelf, a simple demo app that allows users to track how many books they’ve read. It’s built with SwiftUI and minimal by design.

Demo iOS app

By the end of this guide, BookShelf will run in English, Spanish, and Arabic, handle plural strings correctly across all three languages, and mirror its layout automatically for Arabic readers. 

Step 1

Enable Localization

Open BookShelf in Xcode and select the project file in the Navigator. Under the Info tab, scroll to the Localizations section. English is already listed as the base language. Click the + button to add your first language. We’ll add Spanish and Arabic for this demo.

Adding languages in Xcode

Step 2

Create a String Catalog

Next, add a String Catalog. 

  1. Right-click on your project and select New File from Template.
  2. Search for String Catalog and add it. The default name will be Localizable.xcstrings. No need to change it.
  3. Build the project once with Cmd+B. Xcode will scan your code, find every localizable string, and populate the catalog automatically. 

Step 3

 Mark Strings for Localization

After building the project, open Localizable.xcstrings and you’ll see Xcode has already extracted every string literal from your SwiftUI views and added them to the catalog with their English values filled in. For most strings, that’s all you need to do.

Building the project

There are a couple of patterns where Xcode can’t do this automatically, and both fail silently, with the app just displaying the untranslated string with no warning.

Tip 1: Avoid Passing Variables to Text

When you pass a variable to a Text view instead of a string literal, SwiftUI treats it as a plain string and skips the catalog lookup entirely.

// NOT localized
let title = "welcome_title"
Text(title)

// Localized correctly
Text(LocalizedStringKey(title))

Tip 2: Use String(localized:) Outside of Views

For strings you need to localize in a view model, helper function, or anywhere outside a SwiftUI view, use String(localized:) rather than a plain string.

let errorMessage = String(localized: "error_generic")

Step 4

Add Plural and Device Variants

Strings sometimes need different versions depending on context. This includes plural forms that change with a number, or text that differs by device. You can manage both directly in the String Catalog.

Pluralization

BookShelf, our demo app, shows a count of books on the user’s shelf. In English that’s simple: “1 book” vs “3 books”. But plural rules vary across languages, and getting this wrong produces unnatural text in other locales.

Start with the string in your SwiftUI view:

Text("\(bookCount) books on your shelf")

Open the String Catalog, right-click the key, and choose Vary by Plural. Xcode generates the plural categories automatically and pre-fills them with the source string. 

For English, you’ll see One and Other. Just correct the One field to the singular form: “%lld book on your shelf”. The Other form is already right as-is.

Xcode marks both as Needs Review until you confirm them. Once you’ve corrected the One form, you can mark them as reviewed.

You’ll also see Arabic and Spanish listed in the sidebar at 0%. You don’t need to do anything for those languages now. Later, when you export to PTC for translation, the plural structure travels with the file. For Arabic, PTC will generate translations for all six plural categories (zero, one, two, few, many, and other) because Arabic grammar requires all six. For Spanish, it’s two, same as English.

Device Variations

Some text should differ by device, such as “Tap to continue” on iPhone vs “Click to continue” on Mac. To set this up, right-click the key in the catalog and choose Vary by Device. Add the devices you want to customize and enter the appropriate string for each. At runtime, iOS serves whichever version matches the current device.

Device variations are less common than plural variations, but useful for apps that run on both iOS and macOS.

Part 3: Translating Your iOS Localization Files with PTC

Your String Catalog is set up and your strings are ready. Now it’s time to add translations.

For a small project, you could do this manually by opening each language file and filling in translations directly. But as your app grows, that quickly becomes unmanageable across hundreds of keys and dozens of languages.

This is where PTC comes in — an AI translation tool that handles uploading, translating, and syncing your localization files, with options to integrate into your repo or CI/CD pipeline.

🔗 Learn more: AI-powered mobile app localization with PTC — how PTC handles translations end-to-end for iOS and Android apps.

Below, we’ll walk you through getting started.

1

Export your String Catalog from Xcode

Go to Product → Export Localizations in the Xcode menu bar. Xcode packages your String Catalog into an .xcloc file for each target language.

For this guide, we only need the .xcstrings file inside the .xcloc package. To get to it, right-click the exported .xcloc file in Finder and select Show Package Contents. You’ll find Localizable.xcstrings inside.

💡Do you see an “Unable to build project for localization string extraction”notification?
 
This happens when your project uses iOS-only APIs that Xcode can’t compile against its internal macOS SDK during string extraction. To fix it, select the project target under TARGETS, go to Build Settings, search for “Use Compiler to Extract Swift Strings“, and set it to No. Then try exporting again.

2

Sign up for PTC

Sign up for a free PTC trial — no credit card required. The free trial lets you translate 20,000 words into two languages, which in most cases, is enough to localize an app. 

Adding more languages later is easy. PTC uses a Pay-As-You-Go model with no monthly subscription fees. You only pay for what you translate.

After signing up, the project setup will open automatically.

3

 Set Up Your Project and Translate

  1. Drag and drop your Localizable.xcstrings file into PTC. Once added, you’ll see an output file name field. Leave it as Localizable.xcstrings. Xcode expects this exact name when resolving localized strings.
Uploading a file
  1. Select your target languages. The free trial supports two languages. For our demo app, we’re selecting Spanish and Arabic.
Adding target languages in PTC
  1. Describe what your app does and who it’s for. This is what allows PTC to produce context-aware translations that use the right tone, voice, and terminology for your audience.
Adding project context in PTC
  1. Add terms to your glossary. PTC automatically adds your app name to it. You can also add any brand-specific terminology that should be translated in a specific way, or not translated at all.

After you click Start Translation, PTC will take a few minutes to process your file. 

4

Review and Download iOS App Translations

Once translation is complete, go to the Translations tab. You’ll see a table listing each source string alongside its translation. You or any team member you add to the project can edit translations manually directly in this view.

If something looks off, you can report a problem with a specific translation and request a free AI retranslation. PTC learns from the feedback you provide and applies it to future strings in the same project.

Reporting issues in PTC

If any translated string exceeds its length limit, it will be highlighted in the table. PTC sets these limits automatically based on the characteristics of each target language. You have three options:

  • Accept the longer translation if your UI can accommodate it
  • Request a retranslation that fits within the current limit
  • Adjust the limit in Settings → Translation lengths
Long translations flagged in PTC

Part 4: Integrating Translations Into Your Xcode Project

With your translations ready in PTC, the last step is getting them into your Xcode project. You have three options.

Manually Download Files from PTC

Go to the Resource Files tab in PTC and download the zip file. It contains a single Localizable.xcstrings file with your English source strings and all translations included.

To add the file to your project:

  1. Make sure Xcode is closed
  2. Open your project folder in Finder
  3. Replace the existing Localizable.xcstrings with the one from PTC
  4. Restart Xcode

Your translations will appear in the String Catalog, with a checkmark next to each fully translated language.

Imported translations

Integrate with Git

If your project lives on GitHub, GitLab, or Bitbucket, you can connect PTC directly to your repository for continuous translation. 

In your PTC dashboard, to Settings → Merge Requests and click Add Git Integration. You’ll need to provide your repository URL, grant PTC access, and choose your branch and source files. PTC will send a merge request with the translations, which you can review and accept like any other code change.

Use the API

PTC’s API gives you a way to automatically generate and download localization files as part of your own build or deployment pipeline. This is worth exploring if you have a more complex setup or want full control over when and how translations are pulled into your project.

To get started, go to Settings → Manage API tokens. Click on Add access token to generate a token, then see the API documentation for all endpoints.

Part 5: Testing Your Localized iOS App

Now, it’s time to check that your translations look and work as expected.

Testing with the Scheme Language Setting

The quickest way to test a specific language is through your Xcode scheme. Go to Product → Scheme → Edit Scheme and click the Options tab. Change App Language and App Region to the locale you want to test, then run the app with Cmd+R.

This works well for most languages. You should see the same layout and design as the English version, with all text switched to the selected language.

Testing Arabic and other RTL (Right-to-Left) Languages

For Arabic and other right-to-left languages, the scheme language setting can be unreliable in the Simulator. Use the Simulator’s own language settings instead:

  1. Run the app with Cmd+R to open the Simulator
  2. Press Cmd+Home to go to the home screen
  3. Open Settings → General → Language & Region
  4. Tap Add Language, select Arabic, and set it as the primary language
  5. The Simulator will restart.  Open your app from the home screen

Check that text appears in Arabic and that the layout mirrors correctly, with the navigation title and content aligned to the right.

iOS Localization Best Practices

Check Your UI for Varied Text Length

Claude responded: Languages vary in word length.

Languages vary in word length. German, for example, tends to run longer than English and can easily break a UI that was only designed with English in mind.

To avoid this:

Use SwiftUI’s flexible layout system and let labels grow and wrap naturally
Avoid fixed-width constraints on text elements
Test your UI in a few different languages during development, not just before release

Don’t Skip Pluralization Variants

Languages don’t express quantities the same way. English needs two plural forms (one and other), but many languages need more. Russian has five plural categories, Arabic has six, and Japanese has none at all. If you skip pluralization variants for a target language, your app will display unnatural or grammatically incorrect strings for that locale.

String Catalogs handle this automatically. When you add a language, Xcode generates the correct plural fields for that language’s grammar rules. Make sure all generated fields are filled in before shipping.

Localize Images and Assets

If your app uses images that contain text, or visuals that are culturally specific, those need to be localized too. A translated app that still shows English text inside images breaks the experience for non-English users.

To localize an image in Xcode, open Assets.xcassets, select the image, and in the Attributes Inspector click Localize. Choose the languages you want to provide variants for and replace each with the appropriate version. Xcode serves the correct image automatically based on the user’s locale.

Keep Your Base Language Complete

Your base language (usually English) acts as the reference for all other localizations. If a string is missing a translation for a specific language, iOS falls back to the base language version. This means an incomplete base language can cause unexpected fallbacks even in languages that are otherwise fully translated.

Before each release, check that your String Catalog shows no missing or stale strings in the base language. Xcode flags these automatically during the build.

Localize Your App Store Listing

The App Store listing is as important as the app itself. A localized app with an English-only listing loses users at the point of discovery, before they’ve even downloaded it.

In App Store Connect you can localize your app name, subtitle, description, and keyword field for each territory. Keywords are particularly valuable. Apple indexes keywords from multiple locales per territory, which effectively multiplies your keyword character budget beyond the standard 100 characters.

To translate your App Store listing content, use PTC’s Paste to Translate feature. Paste in your app name, subtitle, description, or keyword field and PTC will translate it into your target languages in minutes.

Frequently Asked Questions

Start localizing your iOS app today

You’ve done the technical work. PTC handles the rest. Sign up for a free trial and translate up to 20,000 words into two languages. No credit card required.

Scroll to Top