@@ -470,6 +470,99 @@ class SourceGeneratorTests: XCTestCase {
470470 try expect ( exceptions. contains ( " c.swift " ) ) == true
471471 }
472472
473+ $0. it ( " uses /Localized: prefix for lproj membership exceptions " ) {
474+ let directories = """
475+ Sources:
476+ - a.swift
477+ - Resources:
478+ - de.lproj:
479+ - Localizable.strings
480+ - AppShortcuts.strings
481+ - fr.lproj:
482+ - Localizable.strings
483+ - AppShortcuts.strings
484+ """
485+ try createDirectories ( directories)
486+
487+ let source = TargetSource ( path: " Sources " , includes: [ " a.swift " ] , type: . syncedFolder)
488+ let target = Target ( name: " Test " , type: . application, platform: . iOS, sources: [ source] )
489+ let project = Project ( basePath: directoryPath, name: " Test " , targets: [ target] )
490+
491+ let pbxProj = try project. generatePbxProj ( )
492+ let syncedFolders = try pbxProj. getMainGroup ( ) . children. compactMap { $0 as? PBXFileSystemSynchronizedRootGroup }
493+ let syncedFolder = try unwrap ( syncedFolders. first)
494+
495+ let exceptionSet = try unwrap ( syncedFolder. exceptions? . first as? PBXFileSystemSynchronizedBuildFileExceptionSet )
496+ let exceptions = try unwrap ( exceptionSet. membershipExceptions)
497+
498+ try expect ( exceptions. contains ( " /Localized: Resources/Localizable.strings " ) ) == true
499+ try expect ( exceptions. contains ( " /Localized: Resources/AppShortcuts.strings " ) ) == true
500+ try expect ( exceptions. contains ( " Resources/de.lproj/Localizable.strings " ) ) == false
501+ try expect ( exceptions. contains ( " Resources/fr.lproj/Localizable.strings " ) ) == false
502+ try expect ( exceptions. contains ( " a.swift " ) ) == false
503+ // de + fr variants deduplicate into one /Localized: entry per file
504+ let localizedCount = exceptions. filter { $0. hasPrefix ( " /Localized: " ) } . count
505+ try expect ( localizedCount) == 2
506+ }
507+
508+ $0. it ( " preserves non-localized exceptions alongside /Localized: entries " ) {
509+ let directories = """
510+ Sources:
511+ - a.swift
512+ - b.swift
513+ - Resources:
514+ - de.lproj:
515+ - Localizable.strings
516+ - fr.lproj:
517+ - Localizable.strings
518+ """
519+ try createDirectories ( directories)
520+
521+ let source = TargetSource ( path: " Sources " , includes: [ " a.swift " ] , type: . syncedFolder)
522+ let target = Target ( name: " Test " , type: . application, platform: . iOS, sources: [ source] )
523+ let project = Project ( basePath: directoryPath, name: " Test " , targets: [ target] )
524+
525+ let pbxProj = try project. generatePbxProj ( )
526+ let syncedFolders = try pbxProj. getMainGroup ( ) . children. compactMap { $0 as? PBXFileSystemSynchronizedRootGroup }
527+ let syncedFolder = try unwrap ( syncedFolders. first)
528+
529+ let exceptionSet = try unwrap ( syncedFolder. exceptions? . first as? PBXFileSystemSynchronizedBuildFileExceptionSet )
530+ let exceptions = try unwrap ( exceptionSet. membershipExceptions)
531+
532+ try expect ( exceptions. contains ( " b.swift " ) ) == true
533+ try expect ( exceptions. contains ( " /Localized: Resources/Localizable.strings " ) ) == true
534+ try expect ( exceptions. contains ( " a.swift " ) ) == false
535+ }
536+
537+ $0. it ( " uses /Localized: prefix for lproj files in excludes " ) {
538+ let directories = """
539+ Sources:
540+ - a.swift
541+ - Resources:
542+ - de.lproj:
543+ - Localizable.strings
544+ - AppShortcuts.strings
545+ - fr.lproj:
546+ - Localizable.strings
547+ - AppShortcuts.strings
548+ """
549+ try createDirectories ( directories)
550+
551+ let source = TargetSource ( path: " Sources " , excludes: [ " Resources/*.lproj/AppShortcuts.strings " ] , type: . syncedFolder)
552+ let target = Target ( name: " Test " , type: . application, platform: . iOS, sources: [ source] )
553+ let project = Project ( basePath: directoryPath, name: " Test " , targets: [ target] )
554+
555+ let pbxProj = try project. generatePbxProj ( )
556+ let syncedFolders = try pbxProj. getMainGroup ( ) . children. compactMap { $0 as? PBXFileSystemSynchronizedRootGroup }
557+ let syncedFolder = try unwrap ( syncedFolders. first)
558+
559+ let exceptionSet = try unwrap ( syncedFolder. exceptions? . first as? PBXFileSystemSynchronizedBuildFileExceptionSet )
560+ let exceptions = try unwrap ( exceptionSet. membershipExceptions)
561+
562+ try expect ( exceptions. contains ( " /Localized: Resources/AppShortcuts.strings " ) ) == true
563+ try expect ( exceptions. contains ( " /Localized: Resources/Localizable.strings " ) ) == false
564+ }
565+
473566 $0. it ( " deduplicates synced folders and both targets reference the same group object " ) {
474567 let directories = """
475568 Sources:
0 commit comments