swiftxcodelocalizationswift-package-managerstring-catalog

Sharing String Catalog translations across Swift Packages


I am working with two Swift packages and using string catalogs .xcstrings to manage localizations.

Each package has its own specific localization keys, but I also need to reuse some common keys, such as ok_button_title.

Problem

I want to avoid duplicating identical translation entries in each package. Ideally, I would like to have a single source of truth for these shared translations.

I attempted the following code to reference a translation key from the main app’s bundle:

String(
  localized: "ok_button_title",
  table: "Localizable",
  bundle: .main,
  comment: "Ok button title"
)

This retrieves the translations from the main bundle, but it doesn’t automatically create the keys in the string catalog for the Swift package.

Question

Is it possible to reuse translations from the main bundle directly in Swift packages?

Alternatively, is there a way to automatically generate keys in the string catalog for Swift packages? Or is this behavior expected and not a bug?


Solution

  • To manage localizations in a Swift Package using string catalogs .xcstrings, you need to ensure the following:

    1. Bundle Configuration: Use the .module bundle for your Swift Package. This ensures the package-specific translations are loaded correctly.
    2. Swift Tools Version: Your Package.swift file must specify // swift-tools-version: 6.0 or later to support String(localized:table:bundle:comment) strings within a package. Otherwise, use NSLocalizedString(_:tableName:module:comment:)

    Steps:

    Here’s how you can set up a reusable string catalog for a Swift Package:

    Implementation Example:

    Define a localization enum for cleaner and easier retrieval of localized strings:

    enum L10n {
    
      static let okButtonTitle = String(
        localized: "ok_button_title",
        table: "Shared", // Matches the name of your .xcstrings file.
        bundle: .module, // Uses the Swift Package's module bundle.
        comment: "Ok button title"
      )
    }
    

    Usage:

    To retrieve the localized value in your app:

    import YourTranslationsPackageName
    
    let buttonTitle = L10n.okButtonTitle