@mmerterden/multi-agent-pipeline 20.6.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 (326) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +328 -329
  5. package/package.json +2 -2
  6. package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
  7. package/pipeline/scripts/_notices.mjs +12 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  9. package/pipeline/skills/.skill-manifest.json +106 -106
  10. package/pipeline/skills/shared/README.md +71 -71
  11. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
  16. package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
  17. package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
  18. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  19. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  20. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  21. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  22. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  23. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  24. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  25. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  26. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  27. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  28. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  29. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  30. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  31. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  32. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  33. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  34. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  35. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  37. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  38. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  39. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  40. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  41. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  42. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  43. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  44. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  45. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  46. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  47. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  48. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  49. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  50. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  51. package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
  52. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  53. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  54. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  55. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
  56. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  57. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  58. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  59. package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
  60. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
  61. package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
  62. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  63. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  64. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  65. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  66. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  67. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  68. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  69. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  70. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  71. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  72. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  73. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  74. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  75. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  76. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  77. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  78. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  79. package/pipeline/skills/shared/external/council/SKILL.md +1 -0
  80. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  81. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  82. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  83. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
  84. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
  85. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  86. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  87. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  88. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  89. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  90. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  91. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  92. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  93. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  94. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  95. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  96. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  97. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  98. package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
  99. package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
  100. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
  101. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  102. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  103. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  104. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  105. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  106. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  107. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
  108. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
  109. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  110. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  111. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  112. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  113. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  114. package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
  115. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  116. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  117. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  118. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  119. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
  120. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  121. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  122. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  123. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  124. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  125. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  126. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  127. package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
  128. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  129. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  130. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  131. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  132. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  133. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  134. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
  135. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
  136. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
  137. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
  138. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
  139. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
  140. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
  141. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
  142. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
  143. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
  144. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
  145. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
  146. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
  147. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
  148. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
  149. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
  150. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  151. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  152. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  153. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  154. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  155. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  156. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  157. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  158. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  159. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  160. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  161. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  162. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  163. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
  164. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  165. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  166. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  167. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  168. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  169. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  170. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  171. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  172. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  173. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  174. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  175. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  176. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  177. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  178. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  179. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  180. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  181. package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  183. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  184. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  185. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  186. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
  187. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
  188. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  189. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  190. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  191. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
  192. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
  193. package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
  194. package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
  195. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  196. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  197. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  198. package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
  199. package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
  200. package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
  201. package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
  202. package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
  203. package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
  204. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
  205. package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
  206. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  207. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  208. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  209. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  210. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  211. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  212. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  213. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  214. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  215. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  216. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  217. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  218. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  219. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  220. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  221. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  222. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  223. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  224. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  225. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  226. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  227. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  228. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  229. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  230. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  231. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  232. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  233. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  234. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  235. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  236. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  237. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  238. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  239. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  240. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  241. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  242. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  243. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  244. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  245. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  246. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  247. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  248. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  249. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  250. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  251. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  252. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  253. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  254. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  255. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  256. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  257. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  258. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  259. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  260. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  261. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  262. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  263. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  264. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  265. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  266. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  267. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  268. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  269. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  270. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  271. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  272. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  273. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  274. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  275. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  276. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  277. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  278. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  279. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  280. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  281. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  282. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  283. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  284. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  285. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  286. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  287. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  288. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  289. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  290. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  291. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  292. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  293. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  294. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  295. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  296. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  297. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  298. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  299. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  300. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  301. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  302. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  303. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  304. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  305. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  306. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  307. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  308. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  309. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  310. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
  311. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
  312. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  313. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  314. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
  315. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  316. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  317. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  318. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
  319. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  320. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  321. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
  322. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
  323. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
  324. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  325. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  326. 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.