xcodebuild -exportLocalizations Fails Due to Cross-Platform Dependencies

I'm working on a large multi-platform iOS project (iOS, iPadOS, watchOS, tvOS, visionOS) and have successfully migrated from legacy .strings files to modern String Catalogs (.xcstrings). However, I'm unable to export localizations using xcodebuild -exportLocalizations due to cross-platform framework dependency issues. (Note: I did have AI help me write this question, so apologies in advance for any errors)

Project Structure

  • Main iOS/iPad app with multiple extensions
  • watchOS companion app
  • tvOS app
  • visionOS app
  • 49 .xcstrings files successfully migrated across all targets
  • Uses Swift Package Manager for modularization

The Problem

When attempting to export localizations using xcodebuild -exportLocalizations, the build fails because it tries to build all targets across all platforms, including watchOS targets that depend on third-party xcframeworks that don't include watchOS slices:

xcodebuild -exportLocalizations \
  -project MyProject.xcodeproj \
  -scheme MyApp \
  -localizationPath ./export \
  -configuration Debug

Error:

error: While building for watchOS, no library for this platform was found in 
'Frameworks/<incompatible>.xcframework'. (in target 'Target')

These frameworks cannot be modified to add watchOS support (third-party/legacy dependencies).

What Works vs. What Doesn't

Works: Building the iOS app through Xcode GUI
Fails: Exporting localizations through Xcode GUI (Product → Export Localizations...)
Fails: xcodebuild -exportLocalizations with any combination of flags

Attempted Solutions (All Failed)

  1. Platform-specific destination:
xcodebuild -exportLocalizations -destination "generic/platform=iOS" ...
  1. SDK constraint:
xcodebuild -exportLocalizations -sdk iphoneos ...
  1. Excluding architectures:
xcodebuild -exportLocalizations EXCLUDED_ARCHS="armv7k arm64_32" ...
  1. Build first, then export:
xcodebuild build -scheme MyApp -sdk iphoneos && \
xcodebuild -exportLocalizations ...

All approaches still attempt to build watchOS targets despite platform constraints.

Observations

  • The -exportLocalizations flag appears to ignore -destination and -sdk flags
  • It seems to scan and build ALL schemes/targets in the project regardless of constraints
  • Regular builds (xcodebuild build) work fine with platform constraints

Current Workaround

I created a Python script that parses .xcstrings JSON files directly and generates XLIFF output, which works but feels like it's bypassing Apple's intended workflow.

Questions for Apple

  1. Is there a way to limit xcodebuild -exportLocalizations to specific platforms? The documentation doesn't mention any flags for this, and -destination/-sdk appear to be ignored.

  2. Why does -exportLocalizations require building ALL targets across ALL platforms? Both the Xcode GUI (Product → Export Localizations) and xcodebuild -exportLocalizations fail with identical build errors, suggesting this is by design. Is there a reason localization export can't be limited to buildable targets?

  3. Is the intended workflow to have ALL targets buildable across ALL platforms before exporting localizations? This seems impractical for multi-platform projects with platform-specific dependencies.

  4. Are there any build settings or configuration options that can exclude specific targets/platforms from the localization export scan?

  5. Is directly parsing .xcstrings files and generating XLIFF an acceptable alternative, or does this miss important metadata that -exportLocalizations would include?

Environment

  • Xcode 16.x / 26.x (reproduces on both)
  • macOS Tahoe
  • Project uses String Catalogs (.xcstrings) format
  • Mixed SPM packages and traditional target structure

Any guidance on the correct approach for multi-platform localization export would be greatly appreciated. Is this a known limitation, or is there a recommended pattern I'm missing?

Answered by Developer Tools Engineer in 861089022

Thank you for the info!

This doesn't seem to affect our "normal" build because the relevant watch packages don't depend on the libraries that aren't compatible. But for some reason when -exportLocalization flag is added, it attempts to build ALL targets for watch since that's declared as a platform at the top.

This makes sense to me now. Xcode does indeed attempt to build each target in the package for all platforms listed in that package.

The reason changing those build settings didn't work for you is because they would need to be set on the relevant package targets themselves (not the dependencies), but packages do not allow setting arbitrary build settings.

Please file a Feedback report requesting that the Export feature avoid building package targets for platforms that their dependencies do not support. A sample project is helpful but not required since we now understand what the problem is.

Hello,

Could you tell me more about these watchOS targets? My primary curiosity is how they are able to build successfully even during a normal build, if their dependencies do not support watchOS.

To more directly address your questions, Localization Export and Import are intended to cover all localizable content in the sources of the entire project or workspace. This way, a single xcloc/XLIFF file can be used for the entire project.

Is directly parsing .xcstrings files and generating XLIFF an acceptable alternative, or does this miss important metadata that -exportLocalizations would include?

This could work for your use case, but it is not a recommended flow and could miss a lot of things that Export would give you. Also, the xcstrings format is not guaranteed to remain stable from version to version. When you Export with Xcode (GUI or CLI), Xcode does the following:

  1. Includes strings from existing .xcstrings, .strings, and .stringsdict files in your project.
  2. Extracts localizable strings from source code and other source files, merging them with existing .strings or .xcstrings files. If those files don't exist, it generates new files with those strings and Import will add them to your project.
    • All targets are built for all platforms in order to give the Swift compiler a chance to discover localizable strings in all source code. (For example, any string literal that resolves to a LocalizedStringResource is considered localizable.)
    • xcstringstool extract is run on source code in order to discover usages of NSLocalizedString(…) and similar macros.
    • Known-localizable Info.plist keys are extracted. This includes keys from a literal Info.plist file as well as relevant build settings that would be merged into the Info.plist at build time. Those would end up getting merged to or generated in something like an InfoPlist.xcstrings or InfoPlist.strings file.
    • Localizable strings are extracted from Interface Builder files (storyboards and xibs) and .intentdefinition files.
  3. Includes any other files that have target membership, are marked localized in the File Inspector, and exist in an lproj directory on disk. Even if these are file types such as images, which can't be represented in XLIFF, they will be included in the Localization Catalog.
  4. Language-specific Asset Catalog slices are included in the Localization Catalog just in case the localizer would like to swap out any of those images.

That list should not be considered exhaustive and could expand or otherwise change from version to version.

Are there any build settings or configuration options that can exclude specific targets/platforms from the localization export scan?

There are a few limited configuration options available today.

  1. If you have a workspace with multiple projects, you can limit an Export or Import to a particular project. Therefore, one solution could be to put the watchOS targets in a different Xcode project. When in a workspace, the Product > Export Localizations menu will allow you to choose the project you'd like to export. On the command-line, use the -project option.
  2. The build setting SWIFT_EMIT_LOC_STRINGS can be set to NO on a target if you'd like to avoid building and using the compiler to extract strings from that target during export. However, that also will prevent those strings from syncing to String Catalogs in that target after your own builds.
  3. The LOCALIZATION_EXPORT_SUPPORTED build setting can similarly be set to NO to avoid all forms of extraction from source code, but again this also prevents those strings from being automatically extracted to a String Catalog after manual builds.

Please feel free to file a Feedback to request more granular control of what gets exported by this feature, being specific about use cases that it would enable.

Hi - thanks for the quick response. I'll try to answer as best as I can.

Could you tell me more about these watchOS targets? My primary curiosity is how they are able to build successfully even during a normal build, if their dependencies do not support watchOS.

I mentioned at the bottom of my original post that our app is "[a mixture of] SPM packages and traditional target structure". This is mostly because SPM was introduced after our app was already published and created. We've slowly been migrating old features to SPM, and new features get added to SPM. The reason we love SPM is it introduces modularity for us, and enables greater code sharing.

The way we decided to structure SPM within the context of all of our targets is one shared Package.swift file. This is because so many of our targets share the same code, it seemed easier at the time to keep all our various "libraries" within one SPM package (I hope that makes sense).

So our one Package.swift declares all platforms like this:

platforms: [
    .iOS("17.0"),
    .watchOS("10.0"),
    .tvOS("17.0"),
    .visionOS("1.0"),
]

This doesn't seem to affect our "normal" build because the relevant watch packages don't depend on the libraries that aren't compatible. But for some reason when -exportLocalization flag is added, it attempts to build ALL targets for watch since that's declared as a platform at the top.


The build setting SWIFT_EMIT_LOC_STRINGS can be set to NO on a target if you'd like to avoid building and using the compiler to extract strings from that target during export. However, that also will prevent those strings from syncing to String Catalogs in that target after your own builds.

I believe I tried this earlier, but let me check again to confirm that it didn't seem to have an effect. I don't believe I've tried LOCALIZATION_EXPORT_SUPPORTED so let me check that too.

Thanks in advance for all your help. I'll look into adding a feedback, but getting a sample project might be tricky since this seems like a pretty narrow edge case. I'll see what I can do.

Just want to confirm those build settings did not change anything. It seems like xcodebuild with the -exportLocalization flag runs every single target, for every platform listed, regardless of whether that target is actually using the target.

Accepted Answer

Thank you for the info!

This doesn't seem to affect our "normal" build because the relevant watch packages don't depend on the libraries that aren't compatible. But for some reason when -exportLocalization flag is added, it attempts to build ALL targets for watch since that's declared as a platform at the top.

This makes sense to me now. Xcode does indeed attempt to build each target in the package for all platforms listed in that package.

The reason changing those build settings didn't work for you is because they would need to be set on the relevant package targets themselves (not the dependencies), but packages do not allow setting arbitrary build settings.

Please file a Feedback report requesting that the Export feature avoid building package targets for platforms that their dependencies do not support. A sample project is helpful but not required since we now understand what the problem is.

Thanks for your response. I have submitted feedback: FB20504717

xcodebuild -exportLocalizations Fails Due to Cross-Platform Dependencies
 
 
Q