How to Internationalize and Localize Palmier Pro
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 file at 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 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 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:
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 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:
// 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:
"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:
"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 or view models), create a helper extension to wrap NSLocalizedString:
extension String {
/// Returns a localized version of the string using the key itself.
var localized: String {
NSLocalizedString(self, comment: "")
}
}
Usage in non-UI code:
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 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:
- Opening the project in Xcode
- Selecting the project file
- Ensuring the localization languages appear under the "Localizations" section
- Checking that the
Localizable.stringsfiles 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– Contains thelocalestate variable and thelanguageName()helper function that usesLocale.current.localizedString(forIdentifier:). This file requires the most UI string replacements.Sources/PalmierPro/Transcription/Transcription.swift– ProvidessupportedLocales()and manages language display names for the captioning pipeline.Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Captions.swift– Passes the selectedLocaleto the caption generation request.Package.swift– Declares resource bundles, ensuring localization files are packaged with the app.
Testing Your Localization
Verify your implementation using Xcode's scheme settings:
- Select "Product" → "Scheme" → "Edit Scheme"
- Choose "Options"
- Set "Application Language" to your target language (e.g., Spanish)
- Run the application
Alternatively, launch the app from the command line with the -AppleLanguages argument:
./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
LocaleinCaptionTab.swiftandTranscription.swift. - Externalize strings by replacing hard-coded literals with keys in
Text()views and using aString.localizedextension for non-SwiftUI code. - Create
.lprojdirectories for each language underSources/PalmierPro/Resources/Localization/. - Maintain
Localizable.stringsfiles for each language, addingLocalizable.stringsdictfor 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →