# How to Internationalize and Localize Palmier Pro

> Learn to internationalize and localize Palmier Pro using SwiftUI. Replace hard-coded strings with localization keys and manage languages with `.lproj` directories for global reach.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: how-to-guide
- Published: 2026-06-21

---

**To internationalize Palmier Pro, replace hard-coded UI strings with localization keys in SwiftUI, create `.lproj` directories containing `Localizable.strings` files for each target language, and leverage the existing `Locale` handling in `CaptionTab` for caption language support.**

Palmier Pro is an open-source video editing application that currently ships with hard-coded English strings in its SwiftUI interface. While the captioning pipeline already supports multiple languages via `Transcription.supportedLocales()`, the user interface itself requires systematic externalization of strings to support a global audience. This guide walks you through the complete localization process based on the actual source code architecture in the `palmier-io/palmier-pro` repository.

## Understanding the Current Localization Architecture

Before adding new languages, examine the existing internationalization foundations already present in the codebase.

### Existing Locale Support in CaptionTab

The [`CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/CaptionTab.swift) file at [`Sources/PalmierPro/MediaPanel/CaptionsTab/CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/CaptionsTab/CaptionTab.swift) already implements language-aware captioning. It stores the selected locale in a state variable named `locale` and passes this to the caption generation pipeline. The view model uses this value when constructing `CaptionRequest` objects in `EditorViewModel+Captions.swift`.

Additionally, the [`Transcription.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Transcription.swift) file provides `supportedLocales()` to list available caption languages, and uses `Locale.current.localizedString(forIdentifier:)` to display human-readable language names. This infrastructure handles backend localization, but the UI layer remains hard-coded.

### Package.swift Resource Configuration

The [`Package.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Package.swift) file already includes the `Resources` folder in its target resources array. This means any `Localization` subdirectories you create will be automatically bundled into the application without modifying the build configuration.

## Step-by-Step Internationalization Implementation

Follow these steps to convert the English-only interface into a fully localized application.

### Step 1: Create Localization Directory Structure

Create the base directory structure for your source language and any target languages:

```bash
mkdir -p Sources/PalmierPro/Resources/Localization/en.lproj
mkdir -p Sources/PalmierPro/Resources/Localization/es.lproj
touch Sources/PalmierPro/Resources/Localization/en.lproj/Localizable.strings
touch Sources/PalmierPro/Resources/Localization/es.lproj/Localizable.strings

```

Commit the English `Localizable.strings` file as your source of truth. This file uses key-value pairs where the key is a stable identifier and the value is the English text.

### Step 2: Replace Hard-Coded Strings with Localization Keys

In [`CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/CaptionTab.swift) and other SwiftUI views, replace string literals with localization keys. SwiftUI automatically treats string literals in `Text` initializers as `LocalizedStringKey`.

Convert buttons and labels from hard-coded strings:

```swift
// Before
Button(action: generate) {
    Text("Generate Captions")
}

// After
Button(action: generate) {
    Text("generate_captions_btn")
}

```

Then add the corresponding entry to `en.lproj/Localizable.strings`:

```text
"generate_captions_btn" = "Generate Captions";

```

Apply this pattern to all user-facing strings, including alert messages, navigation titles, and `Label` components throughout the codebase.

### Step 3: Add Language-Specific Strings Files

For each additional language, create a matching `.lproj` directory with a `Localizable.strings` file. For example, add Spanish translations in `es.lproj/Localizable.strings`:

```text
"generate_captions_btn" = "Generar subtítulos";
"my_projects_title" = "Mis proyectos";
"error_captions_failed" = "Error al generar subtítulos";

```

For pluralization or complex formatting rules, create a `Localizable.stringsdict` file in the same directory alongside your `Localizable.strings` file.

### Step 4: Handle Non-SwiftUI Components

For error messages or strings used outside SwiftUI views (such as in [`Transcription.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Transcription.swift) or view models), create a helper extension to wrap `NSLocalizedString`:

```swift
extension String {
    /// Returns a localized version of the string using the key itself.
    var localized: String {
        NSLocalizedString(self, comment: "")
    }
}

```

Usage in non-UI code:

```swift
let errorMessage = "error_captions_failed".localized

```

This ensures consistency across the entire application, including backend error handling and logging messages.

### Step 5: Configure Build Settings

Since [`Package.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Package.swift) already includes the `Resources` folder in its resources array, the new localization files will be bundled automatically. However, verify that Xcode recognizes your localization by:

1. Opening the project in Xcode
2. Selecting the project file
3. Ensuring the localization languages appear under the "Localizations" section
4. Checking that the `Localizable.strings` files are included in the target membership

## Key Source Files and Their Roles

Understanding these specific files helps you navigate the localization changes:

- **[`Sources/PalmierPro/MediaPanel/CaptionsTab/CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/CaptionsTab/CaptionTab.swift)** – Contains the `locale` state variable and the `languageName()` helper function that uses `Locale.current.localizedString(forIdentifier:)`. This file requires the most UI string replacements.
- **[`Sources/PalmierPro/Transcription/Transcription.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Transcription/Transcription.swift)** – Provides `supportedLocales()` and manages language display names for the captioning pipeline.
- **`Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Captions.swift`** – Passes the selected `Locale` to the caption generation request.
- **[`Package.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Package.swift)** – Declares resource bundles, ensuring localization files are packaged with the app.

## Testing Your Localization

Verify your implementation using Xcode's scheme settings:

1. Select "Product" → "Scheme" → "Edit Scheme"
2. Choose "Options"
3. Set "Application Language" to your target language (e.g., Spanish)
4. Run the application

Alternatively, launch the app from the command line with the `-AppleLanguages` argument:

```bash
./PalmierPro -AppleLanguages "(es)"

```

Check for truncated text, layout issues with longer translations, and ensure that the `CaptionTab` locale selector remains functional and properly localized.

## Summary

- **Palmier Pro** already supports caption language selection via `Locale` in [`CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/CaptionTab.swift) and [`Transcription.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Transcription.swift).
- **Externalize strings** by replacing hard-coded literals with keys in `Text()` views and using a `String.localized` extension for non-SwiftUI code.
- **Create `.lproj` directories** for each language under `Sources/PalmierPro/Resources/Localization/`.
- **Maintain `Localizable.strings`** files for each language, adding `Localizable.stringsdict` for pluralization rules.
- **Test thoroughly** using Xcode's scheme language settings to verify UI layout and functionality across all supported locales.

## Frequently Asked Questions

### How do I add a new language to Palmier Pro?

Create a new language directory following the pattern `Sources/PalmierPro/Resources/Localization/[language-code].lproj/`, where `[language-code]` is a valid BCP 47 identifier (e.g., `fr` for French, `de` for German). Copy the `Localizable.strings` file from `en.lproj`, translate the values while keeping the keys identical, and commit the new directory. The [`Package.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Package.swift) configuration automatically bundles these resources.

### Does Palmier Pro support runtime language switching?

The current architecture uses system locale detection by default. For runtime switching, you must store the user-selected language code in `UserDefaults` and override `Bundle.main.preferredLocalizations` before the UI loads. The `CaptionTab` already stores a `locale` property for caption language, which you can extend to drive the entire app's language selection.

### What is the difference between caption language and UI language?

The **caption language** determines which language is used for generated video captions and subtitles, controlled by the `locale` property in [`CaptionTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/CaptionTab.swift) and passed to `EditorViewModel+Captions.swift`. The **UI language** controls the text displayed in buttons, labels, and menus, which is determined by the `Localizable.strings` files. These can be independent—for example, a user might run the app in English but generate Spanish captions.

### How do I handle pluralization in Palmier Pro localizations?

For strings requiring pluralization (e.g., "1 project" vs "5 projects"), create a `Localizable.stringsdict` file in your `.lproj` directory. This XML-formatted file defines rules for different plural categories (zero, one, two, few, many, other) that iOS evaluates at runtime. Standard `Localizable.strings` entries cannot handle dynamic counts, so use `.stringsdict` for any user-facing strings that include numbers.