Mastering Swift and SwiftUI

Insights, Tips, and Tutorials for iOS Developers

Introducing the #Localize Macro for Swift

Published on Sep 9, 2024

Get a quick glimpse of how Tiny Currency simplifies currency conversion with up to date rates, multi-currency support, and easy-to-use widgets. Perfect for on-the-go use, our app ensures you're always prepared, no matter where your travels take you.

Rationale

While localization in SwiftUI is pretty straightforward, things get tricky when working across multiple modules, especially with Swift packages. The built-in localization system tends to target the main app bundle, which isn’t ideal when your project includes modules or packages that need to handle their own localized resources.

👉 Start by reading my post on How to Localize Text in SwiftUI.

💻 Take a look at the #Localize package on GitHub.

Using the macro

Being able to reduce boilerplate is pretty nice, and it's really easy to do so by creating small and simple macros.

The #Localize macro is really easy to start using:

// Assign to a variable
let localizedString = #Localize("This is a localized string")

// Use directly within SwiftUI
Text(#Localize("This is a localized text"))

The macro will expand like so:

let localizedString = #Localize("This is a localized string")
{
    #if SWIFT_PACKAGE
    LocalizedStringResource("This is a localized string", bundle: .atURL(Bundle.module.bundleURL))
    #else
    LocalizedStringResource("This is a localized string")
    #endif
}()

Caveats

✅ If you are in the context of an app target, the above code should work just fine.

⚠️ If you are in the context of a Swift package, you have to do a couple things first.


  1. Make sure that your Swift package has a default localization defined.
  2. Create a String catalog file inside your Swift package Resources folder (or whichever folder you've defined to contain your resources).

Here is an example Package manifest:

let package = Package(
    name: "MyLibrary",
    defaultLocalization: "en", // Make sure to define a default localization here
    platforms: [.iOS(.v16)],
    products: [
        .library(name: "MyLibrary", targets: ["MyLibrary"]),
    ],
    dependencies: [
        .package(url: "https://github.com/Mackarous/Localize.git", from: "1.0.0")
    ],
    targets: [
        .target(name: "MyLibrary", dependencies: ["Localize"]),
        .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]),
    ]
)