| name | resources |
| description | Manages localization and shared resources. Use when adding localized strings, working with String extensions, adding translations, or configuring the Resources module. |
Skill: Resources
Guide for the Resources module: localization and shared resources.
When to use this skill
- Work with localized strings
- Add new translations
- Understand the localization system
- Add support for a new language
Module Overview
The Resources module provides app-specific resources used across features:
- Localization: Centralized strings with
String.localized() extension
- Bundle: Manual
Bundle.module accessor for resources
Location: Shared/Resources/
Note: Shared modules are app-specific (not reusable across apps), unlike Libraries which are generic and reusable.
Supported Languages
| Language | Code | Status |
|---|
| English | en | Source language |
| Spanish | es | Fully translated |
The app uses .xcstrings format (Apple's modern localization format for iOS 16+).
Structure:
Shared/Resources/
├── Package.swift
├── Sources/
│ ├── Extensions/
│ │ └── String+Localized.swift # localized() extension
│ └── Resources/
│ └── Localizable.xcstrings
└── Tests/
Localization
All localized strings are centralized in the Resources module.
Location: Shared/Resources/Sources/Resources/Localizable.xcstrings
String Extension
The localized() extension converts string keys to localized values:
public extension String {
func localized() -> String {
Bundle.module.localizedString(forKey: self, value: nil, table: nil)
}
func localized(_ arguments: CVarArg...) -> String {
String(format: localized(), arguments: arguments)
}
}
Why this pattern? It allows type-safe, reusable localization without repeating bundle references. Translations are managed manually in .xcstrings files.
Usage in Views
Each View defines a private LocalizedStrings enum that uses localized():
import {AppName}Resources
struct MyView: View {
var body: some View {
Text(LocalizedStrings.title)
}
}
private enum LocalizedStrings {
static var title: String { "myView.title".localized() }
static var subtitle: String { "myView.subtitle".localized() }
static func itemCount(_ count: Int) -> String {
"myView.itemCount %lld".localized(count)
}
}
Adding New Strings
- Add the key to
Shared/Resources/Sources/Resources/Localizable.xcstrings
- Provide translations for all supported languages (en, es)
- Add the string to the View's private
LocalizedStrings enum
String Key Naming Convention
| Pattern | Example |
|---|
{screen}.{element} | home.title |
{screen}.{section}.{element} | characterList.empty.title |
common.{element} | common.tryAgain |
Bundle.module
SPM automatically generates Bundle.module for targets that declare resources in their Package.swift. No manual Bundle+Module.swift is needed.
Used by: String.localized() to access Localizable.xcstrings.
Project Configuration
The main app must declare supported languages in Project.swift via CFBundleLocalizations:
let appInfoPlist: [String: Plist.Value] = [
"CFBundleLocalizations": ["en", "es"],
]
Important: iOS does not load localizations from embedded frameworks unless the main app declares supported languages in CFBundleLocalizations. Without this configuration, the app will always display the development language (English) regardless of device settings.
Adding a New Language
- Open
Localizable.xcstrings in Xcode
- Click the "+" button to add a new language
- Translate all strings to the new language
- Update
CFBundleLocalizations in Project.swift:
"CFBundleLocalizations": ["en", "es", "NEW_LANG_CODE"],
- Regenerate the project:
./Scripts/generate.sh
Checklist
Adding Localized Strings
Adding a New Language