@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,369 +1,254 @@
1
- # String Catalogs (.xcstrings) -- Detailed Reference
1
+ # String Catalogs in Depth
2
2
 
3
3
  ## Contents
4
4
 
5
- - [What is a String Catalog?](#what-is-a-string-catalog)
6
- - [Creating a String Catalog](#creating-a-string-catalog)
7
- - [Automatic String Extraction](#automatic-string-extraction)
8
- - [Manual Key Management](#manual-key-management)
9
- - [Handling Strings in Non-SwiftUI Code](#handling-strings-in-non-swiftui-code)
10
- - [Bundle Access Patterns](#bundle-access-patterns)
11
- - [Multi-Module / SPM Localization](#multi-module-spm-localization)
12
- - [Pluralization in String Catalogs](#pluralization-in-string-catalogs)
13
- - [Device Variations](#device-variations)
14
- - [Exporting for Translators (XLIFF / xcloc)](#exporting-for-translators-xliff-xcloc)
15
- - [String Catalog JSON Structure](#string-catalog-json-structure)
16
- - [Generated Localizable Symbols (Xcode 26+)](#generated-localizable-symbols-xcode-26)
17
- - [Testing Strategies](#testing-strategies)
18
- - [Migration from .strings / .stringsdict](#migration-from-strings-stringsdict)
19
- - [Best Practices](#best-practices)
20
-
21
- ## What is a String Catalog?
22
-
23
- A String Catalog is a single Xcode-managed `.xcstrings` file (JSON-based) that holds localizable strings in a target, along with translations, plural forms, and device variations. In Xcode 15 and later, String Catalogs are the recommended workflow for new localization work because they replace much of the manual synchronization previously required across `.strings` and `.stringsdict` files.
24
-
25
- **Availability:** Xcode 15+, all Apple platforms. String Catalogs are the recommended Xcode 15+ workflow for app localization. Xcode 26 adds generated localizable symbols on top of String Catalogs; do not describe catalogs themselves as requiring Xcode 26 or iOS 17.
26
-
27
- ## Creating a String Catalog
28
-
29
- 1. File > New > File > String Catalog
30
- 2. Name it `Localizable.xcstrings` (the default table name, matching the legacy `Localizable.strings`)
31
- 3. Place it in the target's source directory
32
- 4. Add target languages in Project > Info > Localizations
33
-
34
- For a non-default table name (e.g., `Onboarding.xcstrings`), reference it explicitly:
5
+ 1. [What a catalog is](#what-a-catalog-is)
6
+ 2. [Creating one](#creating-one)
7
+ 3. [What extraction picks up](#what-extraction-picks-up)
8
+ 4. [Managing keys by hand](#managing-keys-by-hand)
9
+ 5. [Strings outside SwiftUI](#strings-outside-swiftui)
10
+ 6. [Bundles](#bundles)
11
+ 7. [Swift packages and multiple modules](#swift-packages-and-multiple-modules)
12
+ 8. [Plurals](#plurals)
13
+ 9. [Device variants](#device-variants)
14
+ 10. [Working with translators](#working-with-translators)
15
+ 11. [The JSON format](#the-json-format)
16
+ 12. [Generated symbols (Xcode 26)](#generated-symbols-xcode-26)
17
+ 13. [Testing](#testing)
18
+ 14. [Migrating from .strings and .stringsdict](#migrating-from-strings-and-stringsdict)
19
+ 15. [Practices that scale](#practices-that-scale)
20
+
21
+ ## What a catalog is
22
+
23
+ One `.xcstrings` file per target, stored as JSON, holds the source strings,
24
+ their translations, plural forms and device variants. Catalogs arrived in
25
+ Xcode 15 and work on every platform Xcode targets. Xcode 26 adds generated Swift
26
+ symbols as an extra layer; the catalog itself does not need Xcode 26.
27
+
28
+ ## Creating one
29
+
30
+ 1. File > New > File, choose String Catalog.
31
+ 2. Call it `Localizable.xcstrings`. That name is the default table, the same
32
+ role `Localizable.strings` used to play.
33
+ 3. Put it in the target's source folder.
34
+ 4. Add languages under Project > Info > Localizations.
35
+
36
+ Any other name is a separate table. A file named `Help.xcstrings` is read with
37
+ `String(localized: "faq.title", table: "Help")`.
38
+
39
+ ## What extraction picks up
40
+
41
+ The compiler finds localizable strings on every build by looking at known
42
+ initializers and parameter types.
35
43
 
36
44
  ```swift
37
- String(localized: "welcome.title", table: "Onboarding")
38
- ```
39
-
40
- ## Automatic String Extraction
41
-
42
- On every build, Xcode scans source files and extracts strings from known localizable initializers. Extraction is compiler-driven -- it recognizes these patterns:
43
-
44
- ### SwiftUI (LocalizedStringKey)
45
- ```swift
46
- Text("Hello, world") // extracted
47
- Label("Settings", systemImage: "gear") // extracted
48
- Button("Save") { } // extracted
49
- Toggle("Enable notifications", isOn: $on) // extracted
50
- .navigationTitle("Home") // extracted
51
- Section("Account") { } // extracted
52
-
53
- // NOT extracted -- computed or variable strings
54
- Text(viewModel.title) // not extracted (runtime value)
55
- Text(verbatim: "v1.2.3") // not extracted (verbatim skips localization)
56
- ```
57
-
58
- ### Foundation (String(localized:))
59
- ```swift
60
- String(localized: "No results found") // extracted
61
- String(localized: "error.title",
62
- defaultValue: "Something went wrong",
63
- comment: "Generic error alert title") // extracted with default + comment
64
- ```
65
-
66
- ### LocalizedStringResource
67
- ```swift
68
- LocalizedStringResource("Order placed") // extracted
69
- static var title: LocalizedStringResource = "Title" // extracted
70
- ```
45
+ // Picked up
46
+ Text("Welcome aboard")
47
+ Label("Downloads", systemImage: "arrow.down.circle")
48
+ Button("Retry") { }
49
+ Toggle("Offline mode", isOn: $offline)
50
+ Section("Account") { }
51
+ someView.navigationTitle("Library")
52
+
53
+ String(localized: "sync.failed", defaultValue: "Sync failed", comment: "Toast after a failed sync")
54
+ LocalizedStringResource("Open in Maps")
55
+
56
+ enum Copy {
57
+ static let emptyInbox: LocalizedStringResource = "Nothing new today"
58
+ }
71
59
 
72
- ### What is NOT extracted
73
- ```swift
74
- let x: String = "Not localized" // plain String assignment
75
- print("debug info") // not user-facing
76
- NSLocalizedString("legacy", comment: "") // legacy API; Xcode can export literal keys
60
+ // Not picked up
61
+ Text(viewModel.headline) // value known only at runtime
62
+ Text(verbatim: "v2.4.1") // opts out of localization
63
+ let screenName = "Library" // plain String
64
+ print("Library opened") // logging
77
65
  ```
78
66
 
79
- Prefer `String(localized:)`, SwiftUI localizable literals, or `LocalizedStringResource` in new Swift code so String Catalog syncing and generated-symbol workflows stay straightforward. If automatic extraction misses a string, add it manually in the String Catalog editor.
80
-
81
- ## Manual Key Management
67
+ `NSLocalizedString` is legacy, but Xcode can still export its literal keys.
68
+ If extraction misses something, add the key in the catalog editor.
82
69
 
83
- Open the `.xcstrings` file in Xcode to use the visual editor:
70
+ ## Managing keys by hand
84
71
 
85
- - **Add key**: Click + at the bottom of the key list
86
- - **Remove key**: Select key, press Delete (marks as Stale, removed on next build if no code reference)
87
- - **Edit comment**: Select key, edit the Comment field (provides translator context)
88
- - **Mark state**: Right-click a translation to set Needs Review / Reviewed
89
- - **Vary by plural**: Select a key, click Vary > Plural to add plural categories
90
- - **Vary by device**: Select a key, click Vary > Device to add iPhone/iPad/Mac variants
72
+ In the editor:
91
73
 
92
- ### Key naming conventions
74
+ - (+) adds a key.
75
+ - Delete marks a key Stale; if no code references it, the next build drops it.
76
+ - The Comment field gives translators context they cannot see in the UI.
77
+ - Right-click to mark an entry Needs Review or Reviewed.
78
+ - Vary > Plural and Vary > Device add variants.
93
79
 
94
- For manually-managed strings, use stable symbol-style keys rather than English text as the key. This prevents silent localization breaks when UI copy changes (a typo or rewording just creates a new key and stales the old one - no compiler error). With Xcode 26's generated symbols, stable keys also produce readable, predictable Swift accessors.
80
+ Name keys like stable identifiers, grouped with dots:
95
81
 
96
- ```text
97
- onboarding.welcome.title -> "Welcome"
98
- onboarding.welcome.subtitle -> "Get started in minutes"
99
- settings.notifications.toggle -> "Enable Notifications"
100
- error.network.title -> "Connection Error"
101
- error.network.message -> "Check your internet and try again"
102
82
  ```
103
-
104
- Use `String(localized:defaultValue:)` when you want a structured key that differs from the English text:
105
-
106
- ```swift
107
- let title = String(localized: "error.network.title",
108
- defaultValue: "Connection Error",
109
- comment: "Title for network error alert")
83
+ checkout.summary.title
84
+ checkout.summary.total
85
+ error.offline.title
86
+ error.offline.message
110
87
  ```
111
88
 
112
- For SwiftUI auto-extracted strings, the literal text IS the key by default. This is fine for simple views. For any string you manage manually - shared keys, keys referenced across modules, or keys where copy changes frequently - use a stable key instead.
89
+ With Xcode 26 symbols these keys also become readable, predictable accessors.
90
+ For simple SwiftUI screens it is fine to let the literal be the key. Strings
91
+ that are shared, used across modules, or reworded often should get a stable key.
113
92
 
114
- ## Handling Strings in Non-SwiftUI Code
115
-
116
- ### View models, services, and utilities
93
+ ## Strings outside SwiftUI
117
94
 
118
95
  ```swift
119
- class OrderService {
120
- func statusMessage(for order: Order) -> String {
121
- switch order.status {
122
- case .shipped:
123
- return String(localized: "order.status.shipped",
124
- defaultValue: "Your order has shipped!",
125
- comment: "Order status when item is in transit")
96
+ struct DeliveryStatusText {
97
+ func text(for status: DeliveryStatus, eta: Date) -> String {
98
+ switch status {
99
+ case .preparing:
100
+ String(localized: "delivery.preparing",
101
+ defaultValue: "The kitchen is preparing your order",
102
+ comment: "Order tracking, first step")
103
+ case .onTheWay:
104
+ String(localized: "delivery.on_the_way",
105
+ defaultValue: "Arriving \(eta, format: .dateTime.month().day())",
106
+ comment: "Order tracking with the expected day")
126
107
  case .delivered:
127
- return String(localized: "order.status.delivered",
128
- defaultValue: "Delivered on \(order.deliveryDate!, format: .dateTime.month().day())",
129
- comment: "Order status with delivery date")
130
- case .processing:
131
- return String(localized: "order.status.processing",
132
- defaultValue: "Processing your order...",
133
- comment: "Order status while being prepared")
108
+ String(localized: "delivery.done",
109
+ defaultValue: "Delivered",
110
+ comment: "Order tracking, final step")
134
111
  }
135
112
  }
136
113
  }
137
- ```
138
-
139
- ### Specifying table and bundle
140
114
 
141
- ```swift
142
- // From a specific table
143
- String(localized: "greeting",
144
- table: "Onboarding",
145
- comment: "First-launch greeting")
146
-
147
- // From a specific bundle (framework or Swift package)
148
- String(localized: "button.save",
149
- table: "SharedUI",
150
- bundle: .module,
151
- comment: "Save button in shared component")
115
+ let help = String(localized: "faq.title", table: "Help")
116
+ let packaged = String(localized: "player.skip",
117
+ table: "Player",
118
+ bundle: .module,
119
+ comment: "Skips 15 seconds forward")
152
120
  ```
153
121
 
154
- ## Bundle Access Patterns
122
+ ## Bundles
155
123
 
156
- ### Main app
157
- ```swift
158
- // Uses Bundle.main by default -- no bundle argument needed
159
- String(localized: "Hello")
160
- ```
124
+ - App target: `Bundle.main` is implied, so pass nothing.
125
+ - Swift package: `.module` is the package's resource bundle. Use
126
+ `String(localized: "...", bundle: .module)`, and in SwiftUI pass it
127
+ explicitly, `Text("...", bundle: .module)`. `Text` does not pick up the
128
+ package bundle on its own.
129
+ - Framework: find the bundle through a class that lives in it.
161
130
 
162
- ### Swift Package (SPM)
163
131
  ```swift
164
- // .module refers to the package's resource bundle
165
- String(localized: "Hello", bundle: .module)
132
+ final class ChartsBundleToken {}
166
133
 
167
- // In SwiftUI, pass the package bundle explicitly for package resources
168
- Text("Hello", bundle: .module)
134
+ let chartsBundle = Bundle(for: ChartsBundleToken.self)
135
+ let axisLabel = String(localized: "axis.time", bundle: chartsBundle)
169
136
  ```
170
137
 
171
- ### Framework
172
- ```swift
173
- // Reference the framework's bundle
174
- let frameworkBundle = Bundle(for: MyFrameworkClass.self)
175
- String(localized: "Hello",
176
- bundle: .init(frameworkBundle.bundleURL))
177
- ```
138
+ Any code that is not in the main bundle has to name its bundle: `.module` in a
139
+ package, `Bundle(for:)` in a framework, or the current-target bundle macro
140
+ where the toolchain provides it.
178
141
 
179
- ## Multi-Module / SPM Localization
142
+ ## Swift packages and multiple modules
180
143
 
181
- Each Swift package target that contains user-facing strings needs its own String Catalog.
144
+ Every package target that shows text needs its own catalog.
182
145
 
183
- ### Package.swift setup
184
146
  ```swift
147
+ // swift-tools-version: 6.0
148
+ import PackageDescription
149
+
185
150
  let package = Package(
186
- name: "SharedUI",
151
+ name: "ProfileKit",
187
152
  defaultLocalization: "en",
188
153
  targets: [
189
- .target(
190
- name: "SharedUI",
191
- dependencies: [],
192
- resources: [
193
- .process("Resources") // Localizable.xcstrings goes here
194
- ]
195
- )
154
+ .target(name: "ProfileKit", resources: [.process("Resources")])
196
155
  ]
197
156
  )
157
+ // Catalog path: Sources/ProfileKit/Resources/Localizable.xcstrings
198
158
  ```
199
159
 
200
- ### Directory structure
201
- ```text
202
- Sources/
203
- SharedUI/
204
- Resources/
205
- Localizable.xcstrings <- String Catalog for this module
206
- Views/
207
- ButtonStyles.swift
208
- ```
209
-
210
- ### Accessing strings from the package
211
160
  ```swift
212
- // Inside the package -- bundle: .module resolves package-owned resources
213
- public struct SaveButton: View {
161
+ public struct SignOutButton: View {
162
+ let action: () -> Void
214
163
  public var body: some View {
215
- Button(String(localized: "Save", bundle: .module)) { }
164
+ Button(String(localized: "Sign out", bundle: .module), action: action)
216
165
  }
217
166
  }
218
167
  ```
219
168
 
220
- **Important:** Code outside the main app bundle needs an explicit bundle. Use `bundle: .module` in Swift packages, `Bundle(for:)` in frameworks, or the current-target bundle macro when available.
221
-
222
- For Swift package localization failures, answer with this explicit resource checklist before bundle debugging:
223
- 1. `Package.swift` declares `defaultLocalization`.
224
- 2. The target `resources` list processes the catalog location, such as `.process("Resources")`.
225
- 3. `Localizable.xcstrings` is actually inside that processed target-resource path.
226
- Only after those pass, debug lookup with `bundle: .module` or `Text(..., bundle: .module)`.
227
-
228
- ## Pluralization in String Catalogs
229
-
230
- ### Setup
169
+ When a package keeps falling back to the development language, check setup
170
+ before lookup:
231
171
 
232
- 1. Write code with integer interpolation:
233
- ```swift
234
- Text("\(itemCount) items in your cart")
235
- ```
236
- 2. Build the project -- Xcode adds the key to the String Catalog
237
- 3. Open the String Catalog, select the key
238
- 4. Click "Vary by Plural" in the inspector
239
- 5. Fill in plural forms for each language
172
+ 1. `defaultLocalization` is set in `Package.swift`.
173
+ 2. The target's `resources` processes the catalog's folder, for example
174
+ `.process("Resources")`.
175
+ 3. The catalog file is actually inside that folder.
240
176
 
241
- ### English plural forms
242
- ```text
243
- one: "%1$(itemCount)lld item in your cart"
244
- other: "%1$(itemCount)lld items in your cart"
245
- ```
246
-
247
- ### Arabic plural forms (all six categories)
248
- ```text
249
- zero: "لا توجد عناصر في سلتك"
250
- one: "عنصر واحد في سلتك"
251
- two: "عنصران في سلتك"
252
- few: "%lld عناصر في سلتك" (3-10)
253
- many: "%lld عنصرًا في سلتك" (11-99)
254
- other: "%lld عنصر في سلتك" (100+)
255
- ```
177
+ ## Plurals
256
178
 
257
- ### Multiple plural variables
179
+ 1. Write the string with an integer interpolation.
180
+ 2. Build.
181
+ 3. Select the key in the catalog.
182
+ 4. Choose Vary by Plural in the inspector.
183
+ 5. Fill each form every language needs.
258
184
 
259
- When a string has two integer interpolations, the String Catalog shows a matrix of plural combinations:
185
+ English, with a named positional placeholder:
260
186
 
261
- ```swift
262
- Text("\(photoCount) photos in \(albumCount) albums")
263
- // English needs: one/one, one/other, other/one, other/other
264
- ```
187
+ | Category | Value |
188
+ |---|---|
189
+ | one | `%1$(songCount)lld song` |
190
+ | other | `%1$(songCount)lld songs` |
265
191
 
266
- ## Device Variations
192
+ Arabic fills all six categories: zero, one, two, few (`%lld` ...), many
193
+ (`%lld` ...) and other (`%lld` ...), each with its own wording.
267
194
 
268
- Enable "Vary by Device" for a key to provide different text on iPhone, iPad, Apple Watch, Mac, Apple TV, and Apple Vision Pro.
195
+ Two integer interpolations in one string create a matrix. For
196
+ `"\(photos) photos in \(albums) albums"` English needs one/one, one/other,
197
+ other/one and other/other.
269
198
 
270
- ```swift
271
- // Code is the same everywhere:
272
- Text("Tap to continue")
273
-
274
- // String Catalog provides:
275
- // iPhone: "Tap to continue"
276
- // iPad: "Tap or click to continue"
277
- // Mac: "Click to continue"
278
- // Vision: "Look and tap to continue"
279
- ```
199
+ ## Device variants
280
200
 
281
- ## Exporting for Translators (XLIFF / xcloc)
201
+ Vary by Device lets a key read differently on iPhone, iPad, Apple Watch, Mac,
202
+ Apple TV and Apple Vision Pro. The Swift call site does not change.
282
203
 
283
- ### Export
204
+ ## Working with translators
284
205
 
285
- 1. Product > Export Localizations... (or `xcodebuild -exportLocalizations`)
286
- 2. Select target languages
287
- 3. Xcode creates `.xcloc` bundles (one per language)
288
- 4. Send `.xcloc` files to translators (they contain XLIFF 1.2 inside)
206
+ Export with Product > Export Localizations... or on the command line. The
207
+ result is one `.xcloc` bundle per language, with XLIFF 1.2 inside.
289
208
 
290
- ### Command-line export
291
209
  ```bash
292
210
  xcodebuild -exportLocalizations \
293
- -project MyApp.xcodeproj \
294
- -localizationPath ./Localizations \
295
- -exportLanguage de -exportLanguage ja -exportLanguage ar
211
+ -project Journal.xcodeproj \
212
+ -localizationPath ./l10n-out \
213
+ -exportLanguage fr \
214
+ -exportLanguage ko
296
215
  ```
297
216
 
298
- ### Import
299
-
300
- 1. Product > Import Localizations...
301
- 2. Select the completed `.xcloc` file
302
- 3. Xcode merges translations into the String Catalog
303
- 4. Review changes in the diff viewer
217
+ Bring translations back with Product > Import Localizations...; Xcode merges
218
+ them into the catalog, and the diff viewer shows what changed.
304
219
 
305
- ### Command-line import
306
220
  ```bash
307
221
  xcodebuild -importLocalizations \
308
- -project MyApp.xcodeproj \
309
- -localizationPath ./Localizations/de.xcloc
222
+ -project Journal.xcodeproj \
223
+ -localizationPath ./l10n-in/fr.xcloc
310
224
  ```
311
225
 
312
- ## String Catalog JSON Structure
226
+ ## The JSON format
313
227
 
314
- The `.xcstrings` file is Xcode-managed JSON. Understanding the observed structure can help with parser-backed validation or careful batch updates, but prefer Xcode's editor/export/import workflows for normal localization changes and validate any automated edit before committing.
228
+ Edit through the Xcode editor or the export/import round trip where possible.
229
+ Knowing the format helps when a parser-based check or a careful bulk edit is
230
+ needed; validate any scripted change before committing it.
315
231
 
316
232
  ```json
317
233
  {
318
- "sourceLanguage": "en",
319
- "version": "1.0",
320
- "strings": {
321
- "Welcome, %@!": {
322
- "comment": "Greeting shown on home screen with user name",
323
- "localizations": {
324
- "en": {
325
- "stringUnit": {
326
- "state": "translated",
327
- "value": "Welcome, %@!"
328
- }
329
- },
330
- "de": {
331
- "stringUnit": {
332
- "state": "translated",
333
- "value": "Willkommen, %@!"
334
- }
335
- }
336
- }
337
- },
338
- "item_available": {
339
- "comment": "Button label on product search results",
340
- "extractionState": "manual",
341
- "localizations": {
342
- "en": {
343
- "stringUnit": {
344
- "state": "translated",
345
- "value": "Add this item"
346
- }
347
- }
234
+ "sourceLanguage" : "en",
235
+ "version" : "1.1",
236
+ "strings" : {
237
+ "cart_empty" : {
238
+ "comment" : "Shown when the cart has no items",
239
+ "extractionState" : "manual",
240
+ "localizations" : {
241
+ "en" : { "stringUnit" : { "state" : "translated", "value" : "Your cart is empty" } },
242
+ "de" : { "stringUnit" : { "state" : "translated", "value" : "Dein Warenkorb ist leer" } }
348
243
  }
349
244
  },
350
- "%1$(count)lld items": {
351
- "localizations": {
352
- "en": {
353
- "variations": {
354
- "plural": {
355
- "one": {
356
- "stringUnit": {
357
- "state": "translated",
358
- "value": "%1$(count)lld item"
359
- }
360
- },
361
- "other": {
362
- "stringUnit": {
363
- "state": "translated",
364
- "value": "%1$(count)lld items"
365
- }
366
- }
245
+ "reviews_count" : {
246
+ "localizations" : {
247
+ "en" : {
248
+ "variations" : {
249
+ "plural" : {
250
+ "one" : { "stringUnit" : { "state" : "translated", "value" : "%lld review" } },
251
+ "other" : { "stringUnit" : { "state" : "translated", "value" : "%lld reviews" } }
367
252
  }
368
253
  }
369
254
  }
@@ -373,199 +258,187 @@ The `.xcstrings` file is Xcode-managed JSON. Understanding the observed structur
373
258
  }
374
259
  ```
375
260
 
376
- Note the `"item_available"` key above: it uses `"extractionState": "manual"` and a stable symbol-style key with the English text in `"value"`, not in the key itself. Use stable manual keys for generated-symbol strings. Avoid source-copy-derived keys for API-facing strings because wording edits can rename generated identifiers and churn call sites.
261
+ The top level has `sourceLanguage`, `version` and `strings`. Each key may hold
262
+ `comment`, `extractionState` and `localizations`, where every language has a
263
+ `stringUnit` with `state` and `value`. Plurals nest under
264
+ `localizations.<lang>.variations.plural.<category>.stringUnit`. Note that
265
+ `cart_empty` is a manual key: the English copy lives in `value`, not in the key.
377
266
 
378
- ### Translation states
379
- - `"new"` -- Xcode extracted the key but no translation exists
380
- - `"translated"` -- Translation provided
381
- - `"needs_review"` -- Marked for review (source string changed or manual flag)
382
- - `"stale"` -- Key no longer found in code (removed on next clean build)
267
+ Translation `state`:
383
268
 
384
- ### Extraction states
269
+ | State | Meaning |
270
+ |---|---|
271
+ | `new` | Not translated yet |
272
+ | `translated` | Done |
273
+ | `needs_review` | Source text changed or someone flagged it |
274
+ | `stale` | The key is gone from code; a clean build removes it |
385
275
 
386
- The `extractionState` field (separate from translation `state`) tracks how a key entered the catalog:
276
+ `extractionState`:
387
277
 
388
- | Value | Meaning |
389
- |-------|---------|
390
- | `extracted_with_value` | Xcode found the string in source code and extracted it automatically |
391
- | `manual` | Added by hand via the (+) button - not discovered from code. Xcode will never update or remove manual keys during build sync |
392
- | `stale` | Previously extracted from code, but Xcode can no longer find it. Orphaned translations still exist |
393
- | `migrated` | Converted from a legacy `.strings` or `.stringsdict` file |
278
+ | State | Meaning |
279
+ |---|---|
280
+ | `extracted_with_value` | Found in source by the build |
281
+ | `manual` | Added by hand; build sync never changes or deletes it |
282
+ | `stale` | No longer found; its translations are orphaned |
283
+ | `migrated` | Came from `.strings` or `.stringsdict` |
394
284
 
395
- The `manual` state is significant: manual keys have the **Generate Swift Symbol** checkbox enabled by default, so they automatically produce compiler-checked `LocalizedStringResource` accessors when the build setting is on. Auto-extracted keys can also generate symbols - enable the checkbox per-key or use Refactor > Convert Strings to Symbols.
285
+ Manual keys have Generate Swift Symbol on by default and, with the build
286
+ setting on, turn into compiler-checked `LocalizedStringResource` accessors.
287
+ Extracted keys opt in one at a time or through Convert Strings to Symbols.
396
288
 
397
- ## Generated Localizable Symbols (Xcode 26+)
289
+ ## Generated symbols (Xcode 26)
398
290
 
399
- For generated-symbol or migration answers, start by stating: "String Catalogs are the recommended Xcode 15+ localization workflow. Xcode 26 generated symbols are a separate typed-access layer on top of String Catalogs." Then explain generated symbols, plurals, or migration details. Do not describe catalogs themselves as requiring Xcode 26 or iOS 17.
291
+ Frame answers the same way as in the main skill: catalogs are the Xcode 15+
292
+ workflow; generated symbols are Xcode 26's typed layer on top. Never state that
293
+ catalogs need Xcode 26 or iOS 17.
400
294
 
401
- ### Enabling symbol generation
295
+ Xcode 26 writes format version `"1.1"` into the file as soon as symbol metadata
296
+ exists.
402
297
 
403
- 1. Build Settings > Localization > **Generate String Catalog Symbols** → `Yes` (on by default in new Xcode 26 projects)
404
- 2. The catalog must use format version `"1.1"` - Xcode 26 writes this automatically when symbol generation metadata is present
405
- 3. Each key has a **Generate Swift Symbol** checkbox in the String Catalog editor. Manual keys (added via the (+) button) have this enabled by default. Auto-extracted keys can opt in via Refactor > Convert Strings to Symbols, which enables the checkbox
298
+ Naming: the key is camelCased and its first segment lowercased.
406
299
 
407
- ### How Xcode derives symbol names
300
+ | Key | Symbol |
301
+ |---|---|
302
+ | `cart_empty` | `.cartEmpty` |
303
+ | `profile.privacy.header` | `.profilePrivacyHeader` |
304
+ | `DONE` | `.done` |
408
305
 
409
- Xcode camelCases the key name, lowercasing the first segment:
306
+ Keys with format specifiers turn into functions. A named positional placeholder
307
+ such as `%1$(nights)lld` gives a readable label; a bare `%lld` gives a generic
308
+ one.
410
309
 
411
- | Catalog key | Generated symbol |
412
- |-------------|-----------------|
413
- | `item_available` | `.itemAvailable` |
414
- | `settings.notifications.toggle` | `.settingsNotificationsToggle` |
415
- | `TITLE` | `.title` |
310
+ | Key and value | Symbol |
311
+ |---|---|
312
+ | `stay_length` = `%1$(nights)lld nights` | `.stayLength(nights: Int)` |
313
+ | `welcome_user` = `Hi %@` | `.welcomeUser(_ arg1: String)` |
416
314
 
417
- Keys with format specifiers become functions. Use positional named placeholders such as `%1$(name)lld` for descriptive argument labels; bare `%lld` produces generic labels:
418
-
419
- | Catalog key | Format | Generated symbol |
420
- |-------------|--------|-----------------|
421
- | `products_count` | `%1$(count)lld` | `.productsCount(count: Int)` |
422
- | `greeting` | `%@` | `.greeting(_ param1: String)` |
423
-
424
- You can rename parameters during refactoring for more descriptive signatures.
425
-
426
- ### Using generated symbols
315
+ Parameters can be renamed while refactoring.
427
316
 
428
317
  ```swift
429
- // Simple key - static property
430
- Text(.itemAvailable)
431
-
432
- // Parameterized key - function
433
- Text(.productsCount(count: 42))
318
+ Text(.cartEmpty)
319
+ Text(.stayLength(nights: 4))
434
320
 
435
- // Non-default table (Checkout.xcstrings)
436
- Text(.Checkout.confirmOrderCta)
437
-
438
- // In non-SwiftUI code
439
- let title = String(localized: .itemAvailable)
440
- let attributed = AttributedString(localized: .greeting(userName))
321
+ let plain = String(localized: .cartEmpty)
322
+ let styled = AttributedString(localized: .welcomeUser(member.firstName))
441
323
  ```
442
324
 
443
- Code completion supports generated symbols - type `.` and choose from the menu.
444
-
445
- ### Refactoring existing strings to symbols
446
-
447
- Select one or more keys in the String Catalog editor, Control-click, and choose **Refactor > Convert Strings to Symbols**. Xcode replaces string literal usage in code with the generated symbol. This is reversible via **Convert Symbols to Strings**.
325
+ Code completion lists the symbols after you type `.`.
448
326
 
449
- ### Cross-module limitations
327
+ Converting existing literals: select the keys, Control-click, Refactor > Convert
328
+ Strings to Symbols. Xcode rewrites the literals at their call sites. Convert
329
+ Symbols to Strings goes the other way.
450
330
 
451
- Generated symbols are declared `internal`. Code in other modules cannot access them directly. Default to a public wrapper; reach for `xcstrings-tool` if the wrapper becomes unwieldy across many modules:
331
+ Across modules: symbols are `internal`. The usual fix is a public extension on
332
+ `LocalizedStringResource` that forwards to them:
452
333
 
453
- - **Public wrapper** (default): Create a public extension on `LocalizedStringResource` that delegates to the internal symbols
454
- - **[xcstrings-tool](https://github.com/liamnichols/xcstrings-tool)**: A Swift Package Plugin that generates public constants from `.xcstrings` files - use this for heavier multi-module setups where maintaining manual wrappers becomes tedious
455
-
456
- For Swift Packages, the generated symbols use the `.module` bundle automatically. The `internal` visibility means only code within the same package target can reference them.
334
+ ```swift
335
+ public extension LocalizedStringResource {
336
+ static var sharedRetry: LocalizedStringResource { .retryButton }
337
+ }
338
+ ```
457
339
 
458
- ## Testing Strategies
340
+ When those wrappers become tedious, `xcstrings-tool`, an open-source Swift
341
+ package plugin, generates public constants for you.
459
342
 
460
- ### Scheme language override
343
+ Inside a Swift package, generated symbols read from the `.module` bundle
344
+ automatically, and they are only visible within the same package target.
461
345
 
462
- Edit Scheme > Run > Options > App Language. Choose any added language to launch the app in that locale without changing the device/simulator system language.
346
+ ## Testing
463
347
 
464
- ### Pseudolocalization options
348
+ Scheme override: Edit Scheme > Run > Options > App Language starts the app in
349
+ another language without touching the system setting.
465
350
 
466
- Xcode provides built-in pseudolocalization modes (Edit Scheme > Run > Options > App Language):
351
+ Pseudolanguages from the same menu:
467
352
 
468
- | Option | Effect | Catches |
469
- |--------|--------|---------|
470
- | Accented Pseudolanguage | Adds accents: "Hello" -> "[Hellо]" | Hardcoded strings (unlocalized text is obvious) |
471
- | Right-to-Left Pseudolanguage | Forces RTL layout | Layout mirroring bugs |
472
- | Double-Length Pseudolanguage | Doubles all strings | Truncation and overflow |
473
- | Bounded String Pseudolanguage | Wraps strings in brackets | Missing localizations |
353
+ | Pseudolanguage | Finds |
354
+ |---|---|
355
+ | Accented | Hard-coded strings that bypass lookup |
356
+ | Right-to-Left | Mirroring bugs |
357
+ | Double-Length | Truncation and overflow |
358
+ | Bounded String | Missing localizations (strings are wrapped in brackets) |
474
359
 
475
- ### UI tests with locale override
360
+ UI test in a specific locale:
476
361
 
477
362
  ```swift
478
- func testGermanLayout() {
479
- let app = XCUIApplication()
480
- app.launchArguments += ["-AppleLanguages", "(de)"]
481
- app.launchArguments += ["-AppleLocale", "de_DE"]
482
- app.launch()
483
-
484
- // Verify no truncation on key screens
485
- let saveButton = app.buttons["Speichern"]
486
- XCTAssertTrue(saveButton.exists)
487
- XCTAssertTrue(saveButton.isHittable)
488
- }
489
- ```
490
-
491
- ### Snapshot testing per locale
492
-
493
- Use a snapshot testing library to capture screenshots in multiple locales and compare them for layout regressions:
494
-
495
- ```swift
496
- let locales = ["en_US", "de_DE", "ar_SA", "ja_JP"]
497
- for locale in locales {
498
- app.launchArguments = ["-AppleLanguages", "(\(locale.prefix(2)))"]
499
- app.launch()
500
- // Capture and compare snapshot
363
+ import XCTest
364
+
365
+ final class GermanCheckoutUITests: XCTestCase {
366
+ @MainActor
367
+ func testPayButtonIsLocalized() {
368
+ let app = XCUIApplication()
369
+ app.launchArguments += ["-AppleLanguages", "(de)", "-AppleLocale", "de_DE"]
370
+ app.launch()
371
+
372
+ let pay = app.buttons["Jetzt bezahlen"]
373
+ XCTAssertTrue(pay.exists)
374
+ XCTAssertTrue(pay.isHittable)
375
+ }
501
376
  }
502
377
  ```
503
378
 
504
- ### Translation coverage validation
379
+ Screenshot comparison per locale: loop over `en_US`, `de_DE`, `ar_SA` and
380
+ `ja_JP`, set `-AppleLanguages` for each, launch, capture, compare against the
381
+ stored image.
505
382
 
506
- Check that all keys are translated before release:
383
+ Translation coverage in CI: parse the catalog and fail when any language entry
384
+ is untranslated or empty.
507
385
 
508
- ```bash
509
- # Parse the .xcstrings JSON and check for "new" or empty states
510
- python3 -c "
386
+ ```python
387
+ #!/usr/bin/env python3
511
388
  import json, sys
512
- with open('Localizable.xcstrings') as f:
513
- data = json.load(f)
514
- missing = []
515
- for key, info in data['strings'].items():
516
- for lang, loc in info.get('localizations', {}).items():
517
- unit = loc.get('stringUnit', {})
518
- if unit.get('state') in ('new', None) or not unit.get('value'):
519
- missing.append(f'{lang}: {key}')
520
- if missing:
521
- print('Missing translations:')
522
- for m in missing: print(f' {m}')
523
- sys.exit(1)
524
- print('All translations complete.')
525
- "
526
- ```
527
-
528
- ## Migration from .strings / .stringsdict
529
389
 
530
- ### Automatic migration
531
-
532
- 1. Select the `.strings` file in the project navigator
533
- 2. Right-click > Migrate to String Catalog...
534
- 3. Xcode creates a `.xcstrings` file with all existing keys and translations
535
- 4. Verify in the String Catalog editor
536
- 5. Remove the old `.strings` / `.stringsdict` files from the target
390
+ catalog = json.load(open(sys.argv[1], encoding="utf-8"))
391
+ gaps = []
392
+ for key, entry in catalog.get("strings", {}).items():
393
+ for lang, loc in entry.get("localizations", {}).items():
394
+ units = [loc["stringUnit"]] if "stringUnit" in loc else [
395
+ v["stringUnit"]
396
+ for group in loc.get("variations", {}).values()
397
+ for v in group.values() if "stringUnit" in v
398
+ ]
399
+ for unit in units:
400
+ if unit.get("state", "new") == "new" or not unit.get("value"):
401
+ gaps.append(f"{lang}: {key}")
402
+
403
+ print("\n".join(gaps) or "all strings translated")
404
+ sys.exit(1 if gaps else 0)
405
+ ```
537
406
 
538
- ### Manual migration
407
+ ## Migrating from .strings and .stringsdict
539
408
 
540
- If automatic migration fails (complex bundle setups, CocoaPods):
409
+ Automatic: right-click the `.strings` file, choose Migrate to String Catalog...,
410
+ check the result, then remove the old files from the target.
541
411
 
542
- 1. Create a new `Localizable.xcstrings`
543
- 2. Build to extract keys from code
544
- 3. Copy translations from old `.strings` files into the String Catalog editor
545
- 4. Copy plural rules from `.stringsdict` into plural variants
546
- 5. Remove old files
412
+ By hand, when a bundle setup is unusual or files come from CocoaPods:
547
413
 
548
- ### Migration checklist
414
+ 1. Create a new catalog.
415
+ 2. Build so extraction fills it.
416
+ 3. Copy translations across from the old files.
417
+ 4. Rebuild `.stringsdict` rules as plural variants.
418
+ 5. Remove the legacy files.
549
419
 
550
- - [ ] All `.strings` keys present in the new String Catalog
551
- - [ ] All `.stringsdict` plural rules converted to String Catalog plural variants
552
- - [ ] Bundle references updated (if custom bundle was used)
553
- - [ ] Build succeeds with no missing-localization warnings
554
- - [ ] Test every language the app supports
555
- - [ ] Remove old `.strings` and `.stringsdict` files from the target
556
- - [ ] Commit the `.xcstrings` file (it is JSON, diffs well in version control)
420
+ Before calling it done:
557
421
 
558
- ### Coexistence
422
+ - [ ] Every key made it across
423
+ - [ ] Plurals are variants now
424
+ - [ ] Custom bundle references point to the right place
425
+ - [ ] The build shows no missing-localization warnings
426
+ - [ ] Every language was run
427
+ - [ ] Legacy files are gone
428
+ - [ ] `.xcstrings` is committed (it diffs cleanly as JSON)
559
429
 
560
- String Catalogs and `.strings` files can coexist in the same target during migration. Xcode resolves keys from the String Catalog first, then falls back to `.strings`. Remove legacy files after verifying the migration.
430
+ During the transition both formats work: lookup tries the catalog first, then
431
+ the `.strings` file. Delete the legacy file once you have verified the catalog.
561
432
 
562
- ## Best Practices
433
+ ## Practices that scale
563
434
 
564
- 1. **One String Catalog per target** -- keep `Localizable.xcstrings` as the single source of truth for each target.
565
- 2. **Use comments** -- provide context for every ambiguous key. Translators cannot see your UI.
566
- 3. **Review extraction on every build** -- new keys appear with state "new". Translate them promptly.
567
- 4. **Version control the .xcstrings file** -- it is JSON and diffs clearly. Review translation changes in PRs.
568
- 5. **Automate coverage checks** -- integrate translation-coverage validation in CI to catch missing translations before release.
569
- 6. **Export regularly** -- send updated `.xcloc` bundles to translators after each sprint or feature merge.
570
- 7. **Test with pseudolocalizations in CI** -- run UI tests with double-length and RTL pseudo-languages to catch layout issues early.
571
- 8. **Prefer stable keys with generated symbols** -- for manually-managed strings, use symbol-style keys and enable Generate String Catalog Symbols to get compile-time safety and autocompletion.
435
+ 1. One catalog per target as the source of truth.
436
+ 2. A comment on every ambiguous key; translators never see the screen.
437
+ 3. After each build, look for keys in state `new` and get them translated.
438
+ 4. Keep `.xcstrings` in version control and review translation diffs in pull
439
+ requests.
440
+ 5. Run a translation coverage check in CI.
441
+ 6. Send `.xcloc` exports to translators at every sprint or feature merge.
442
+ 7. Run UI tests under the double-length and RTL pseudolanguages in CI.
443
+ 8. Prefer stable keys with generated symbols for compile-time checking and
444
+ autocompletion.