@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,473 +1,360 @@
1
1
  ---
2
2
  name: ios-localization
3
- description: "Implement, review, or improve localization and internationalization in iOS/macOS apps - String Catalogs (.xcstrings), generated localizable symbols, stable key naming, LocalizedStringKey, LocalizedStringResource, pluralization, FormatStyle for numbers/dates/measurements, right-to-left layout, Dynamic Type, and locale-aware formatting. Use when adding multi-language support, setting up String Catalogs, enabling generated symbols for compile-time-safe localization keys, handling plural forms, formatting dates/numbers/currencies for different locales, testing localizations, or making UI work correctly in RTL languages like Arabic and Hebrew."
3
+ description: "i18n and l10n for iOS and macOS: String Catalogs (.xcstrings), generated localizable symbols with compile-time-checked keys, stable key naming, LocalizedStringKey, LocalizedStringResource, String(localized:), plurals, device variations, locale-aware FormatStyle for numbers, dates, currency and measurements, right-to-left layout, Dynamic Type, localization testing. Use when implementing or reviewing localization, adding languages, setting up catalogs, formatting values per locale, testing translations or making UI work in Arabic or Hebrew. Not for custom or parseable FormatStyle, parsing, interval or URL format styles (swift-formatstyle)."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # iOS Localization & Internationalization
8
+ # iOS Localization
9
9
 
10
- Localize iOS 26+ apps using String Catalogs, modern string types, FormatStyle, and RTL-aware layout. Localization mistakes cause App Store rejections in non-English markets, mistranslated UI, and broken layouts. Ship with correct localization from the start.
10
+ This skill targets iOS 26+ apps built with String Catalogs, the modern Swift
11
+ string types, `FormatStyle` and layout that respects writing direction. Each API
12
+ below keeps its own, often much older, availability.
11
13
 
12
- ## Contents
14
+ Retrofitting localization late is expensive. Hard-coded copy, glued-together
15
+ sentences and fixed widths show up as rejected builds in non-English
16
+ storefronts, mistranslated screens and clipped layouts. Treat every visible
17
+ string and every formatted value as localizable from the first commit.
13
18
 
14
- - [String Catalogs (.xcstrings)](#string-catalogs-xcstrings)
15
- - [String Catalogs (Xcode 15+) and Generated Symbols (Xcode 26+)](#string-catalogs-xcode-15-and-generated-symbols-xcode-26)
16
- - [String Types -- Decision Guide](#string-types-decision-guide)
17
- - [String Interpolation in Localized Strings](#string-interpolation-in-localized-strings)
18
- - [Pluralization](#pluralization)
19
- - [FormatStyle -- Locale-Aware Formatting](#formatstyle-locale-aware-formatting)
20
- - [Right-to-Left (RTL) Layout](#right-to-left-rtl-layout)
21
- - [Common Mistakes](#common-mistakes)
22
- - [Localization Review Checklist](#review-checklist)
23
- - [References](#references)
19
+ Deep material lives in two references:
24
20
 
25
- ## String Catalogs (.xcstrings)
21
+ - [references/string-catalogs.md](references/string-catalogs.md): catalog
22
+ creation, extraction rules, key management, bundles and Swift packages,
23
+ plurals, device variants, translator export and import, the JSON format,
24
+ generated symbols, testing and migration.
25
+ - [references/formatstyle-locale.md](references/formatstyle-locale.md):
26
+ locale-aware formatting for every value type, legacy formatter migration, RTL
27
+ in depth, `@ScaledMetric` and layout checks with Accessibility Inspector.
26
28
 
27
- String Catalogs are the recommended Xcode 15+ workflow for new localization work. They keep localizable strings, pluralization rules, and device variations together in an Xcode-managed JSON file with a visual editor. Legacy `.strings` and `.stringsdict` files can coexist during migration, but new Swift and SwiftUI code should default to String Catalogs.
29
+ ## String Catalogs
28
30
 
29
- **Why String Catalogs exist:**
30
- - `.strings` files required manual key management and fell out of sync
31
- - `.stringsdict` required complex XML for plurals
32
- - String Catalogs auto-extract strings from code, track translation state, and support plurals natively
31
+ A String Catalog is a JSON file managed by Xcode, edited through a visual
32
+ table, that keeps source strings, translations, plural forms and per-device
33
+ variants in one place. Catalogs have been the recommended way to localize
34
+ since Xcode 15. Legacy `.strings` and `.stringsdict` files can live next to a
35
+ catalog while a project migrates, but new Swift and SwiftUI code should start
36
+ in a catalog.
33
37
 
34
- **How automatic extraction works:**
38
+ Why the switch: `.strings` files needed hand-maintained keys that silently
39
+ drifted from the code, and `.stringsdict` plural rules were long XML
40
+ dictionaries. A catalog is filled in by the build, tracks the state of each
41
+ translation, and models plurals directly.
35
42
 
36
- Xcode scans for these patterns on each build:
43
+ Every build, Xcode scans the source for known localizable call patterns and
44
+ adds any key it finds. Keys then show a state in the editor such as Needs
45
+ Review, Translated or Stale.
37
46
 
38
47
  ```swift
39
- // SwiftUI -- automatically extracted (LocalizedStringKey)
40
- Text("Welcome back") // key: "Welcome back"
41
- Label("Settings", systemImage: "gear")
42
- Button("Save") { }
43
- Toggle("Dark Mode", isOn: $dark)
44
-
45
- // Programmatic -- automatically extracted
46
- String(localized: "No items found")
47
- LocalizedStringResource("Order placed")
48
-
49
- // NOT extracted -- plain String, not localized
50
- let msg = "Hello" // just a String, invisible to Xcode
51
- ```
52
-
53
- Xcode adds discovered keys to the String Catalog automatically. Mark translations as Needs Review, Translated, or Stale in the editor.
48
+ struct TripHeader: View {
49
+ @State private var alertsOn = true
50
+
51
+ var body: some View {
52
+ VStack {
53
+ Text("Your upcoming trips") // extracted
54
+ Label("Boarding pass", systemImage: "ticket") // extracted
55
+ Button("Check in") { } // extracted
56
+ Toggle("Gate alerts", isOn: $alertsOn) // extracted
57
+ }
58
+ }
59
+ }
54
60
 
55
- For detailed String Catalog workflows, migration, and testing strategies, see [references/string-catalogs.md](references/string-catalogs.md).
61
+ let banner = String(localized: "Seat changed") // extracted
62
+ let hint = LocalizedStringResource("Arrive two hours early") // extracted
63
+ let debugTag = "trip-header" // plain String: never extracted, never translated
64
+ ```
56
65
 
57
- ## String Catalogs (Xcode 15+) and Generated Symbols (Xcode 26+)
66
+ For a SwiftUI initializer the literal itself becomes the key.
58
67
 
59
- 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.
68
+ ## Generated Symbols (Xcode 26) on Top of Catalogs
60
69
 
61
- **Enable:** Build Settings > Localization > Generate String Catalog Symbols → `Yes` (on by default in new Xcode 26 projects). Requires catalog format version `1.1`.
70
+ When a question is about generated symbols or about migrating to them, say
71
+ this first: catalogs are the Xcode 15+ workflow, and generated symbols are a
72
+ separate typed-access layer that Xcode 26 builds on those catalogs. Do not say
73
+ catalogs require Xcode 26, and do not tie them to iOS 17.
62
74
 
63
- **Workflow:** Add a key manually via the (+) button in the String Catalog editor - manual keys have the **Generate Swift Symbol** checkbox enabled by default. Auto-extracted keys can also opt in via Refactor > Convert Strings to Symbols. 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.
75
+ - Turn it on with Build Settings > Localization > Generate String Catalog
76
+ Symbols = `Yes`. New Xcode 26 projects already have it on.
77
+ - The catalog must use format version `1.1`.
78
+ - A key added by hand with the (+) button has Generate Swift Symbol ticked by
79
+ default. Keys that came from extraction opt in through Refactor > Convert
80
+ Strings to Symbols, which can be undone later.
81
+ - Pick stable, hand-written keys for anything reached through a symbol. A key
82
+ derived from the English copy renames its symbol the moment someone edits
83
+ the wording, and every call site churns.
64
84
 
65
85
  ```swift
66
- // Generated from key "item_available" in Localizable.xcstrings
67
- Text(.itemAvailable)
86
+ // Localizable.xcstrings: "cart_empty" -> "Your cart is empty"
87
+ Text(.cartEmpty)
68
88
 
69
- // Parameterized key "products_count" with %1$(count)lld
70
- Text(.productsCount(count: 42))
89
+ // "seats_left" -> "%1$(remaining)lld seats left"
90
+ Text(.seatsLeft(remaining: 3))
71
91
 
72
- // Non-default table "Checkout.xcstrings"
73
- Text(.Checkout.confirmOrderCta)
92
+ // Separate table Payments.xcstrings, key "apply_voucher_cta"
93
+ Text(.Payments.applyVoucherCta)
74
94
  ```
75
95
 
76
- Xcode derives symbol names by camelCasing the key: `settings.notifications.toggle` → `.settingsNotificationsToggle`. You can convert existing extracted strings to symbols via Refactor > Convert Strings to Symbols (reversible).
96
+ Symbols are the key in camelCase: `profile.privacy.header` becomes
97
+ `.profilePrivacyHeader`. They are generated with `internal` access, so another
98
+ module needs a small public wrapper. When wrappers pile up across many modules,
99
+ the open-source `xcstrings-tool` package plugin generates public accessors.
77
100
 
78
- Generated symbols are `internal`. For cross-module access, create a public wrapper extension. For heavier multi-module setups, use [xcstrings-tool](https://github.com/liamnichols/xcstrings-tool) instead.
101
+ ## Picking a String Type
79
102
 
80
- For the full generated symbols reference - extraction states, symbol derivation rules, and cross-module patterns - see [references/string-catalogs.md](references/string-catalogs.md).
103
+ ### LocalizedStringKey
81
104
 
82
- ## String Types -- Decision Guide
83
-
84
- ### LocalizedStringKey (SwiftUI default)
85
-
86
- SwiftUI views accept `LocalizedStringKey` for their text parameters. String literals are implicitly converted -- no extra work needed.
105
+ Text parameters of SwiftUI views are `LocalizedStringKey`, and a string literal
106
+ converts to it implicitly, so lookup just happens:
87
107
 
88
108
  ```swift
89
- // These all create a LocalizedStringKey lookup automatically:
90
- Text("Welcome back")
91
- Label("Profile", systemImage: "person")
92
- Button("Delete") { deleteItem() }
93
- .navigationTitle("Home")
109
+ NavigationStack {
110
+ List {
111
+ Label("Saved places", systemImage: "mappin")
112
+ Button("Clear history") { }
113
+ }
114
+ .navigationTitle("Places")
115
+ }
94
116
  ```
95
117
 
96
- Use `LocalizedStringKey` when passing strings directly to SwiftUI view initializers. Do not construct `LocalizedStringKey` manually in most cases.
118
+ Pass literals straight into SwiftUI initializers. Building a
119
+ `LocalizedStringKey` by hand is rarely needed.
97
120
 
98
- ### String(localized:) -- Modern NSLocalizedString replacement
121
+ ### String(localized:)
99
122
 
100
- Use for any localized string outside a SwiftUI view initializer. Returns a plain `String`. The literal/interpolated initializer is available iOS 15+; resolving a `LocalizedStringResource` is iOS 16+.
123
+ `String(localized:)` replaces `NSLocalizedString`. It returns a resolved
124
+ `String` for code that is not a SwiftUI initializer argument. The literal and
125
+ interpolation form needs iOS 15; resolving a `LocalizedStringResource` needs
126
+ iOS 16.
101
127
 
102
128
  ```swift
103
- // Basic
104
- let title = String(localized: "Welcome back")
129
+ let title = String(localized: "Refund requested")
130
+ let note = String(localized: "refund.pending.note",
131
+ defaultValue: "Refunds take up to 5 business days")
132
+ let label = String(localized: "Download", table: "Offline", bundle: .module)
133
+ let verb = String(localized: "Book",
134
+ comment: "Verb on a button that reserves a table")
135
+ ```
105
136
 
106
- // With default value (key differs from English text)
107
- let msg = String(localized: "error.network",
108
- defaultValue: "Check your internet connection")
137
+ A Swift package that still shows English falls into one of three setup gaps.
138
+ Check them in order before touching bundle lookup:
109
139
 
110
- // With table and bundle
111
- let label = String(localized: "onboarding.title",
112
- table: "Onboarding",
113
- bundle: .module)
140
+ 1. `Package.swift` sets `defaultLocalization`.
141
+ 2. The target's `resources` processes the folder that holds the catalog, for
142
+ example `.process("Resources")`.
143
+ 3. `Localizable.xcstrings` really sits inside that processed folder.
114
144
 
115
- // With comment for translators
116
- let btn = String(localized: "Save",
117
- comment: "Button title to save the current document")
118
- ```
145
+ Only once all three hold, debug lookup with `bundle: .module` in
146
+ `String(localized:)` and `Text(_:bundle:)`.
119
147
 
120
- For Swift package localization failures, answer with this explicit resource checklist before bundle debugging:
121
- 1. `Package.swift` declares `defaultLocalization`.
122
- 2. The target `resources` list processes the catalog location, such as `.process("Resources")`.
123
- 3. `Localizable.xcstrings` is actually inside that processed target-resource path.
124
- Only after those pass, debug lookup with `bundle: .module` or `Text(..., bundle: .module)`.
148
+ Xcode can still export and migrate literal-key `NSLocalizedString` calls, but
149
+ new code uses `String(localized:)`, SwiftUI literals,
150
+ `LocalizedStringResource` or generated symbols.
125
151
 
126
- Existing `NSLocalizedString` literal keys can still be exported or migrated by Xcode tooling, but new Swift code should prefer `String(localized:)`, SwiftUI literals, `LocalizedStringResource`, or generated symbols.
152
+ ### LocalizedStringResource
127
153
 
128
- ### LocalizedStringResource -- Pass localization info without resolving
129
-
130
- Use when a string must be carried as a localizable value for later resolution, especially for App Intents, widgets, notifications, generated localizable symbols, and system APIs that accept `LocalizedStringResource` directly. Use `String(localized:)` when code needs the resolved string immediately. Available iOS 16+.
154
+ `LocalizedStringResource` (iOS 16+) carries a localizable value that someone
155
+ else resolves later: App Intents, widgets, notifications, generated symbols
156
+ and system APIs that accept it. When you need the text now, use
157
+ `String(localized:)`.
131
158
 
132
159
  ```swift
133
- // App Intents require LocalizedStringResource
134
- struct OrderCoffeeIntent: AppIntent {
135
- static var title: LocalizedStringResource = "Order Coffee"
160
+ struct StartTimerIntent: AppIntent {
161
+ static let title: LocalizedStringResource = "Start Focus Timer"
162
+ func perform() async throws -> some IntentResult { .result() }
136
163
  }
137
164
 
138
- // Widgets
139
- struct MyWidget: Widget {
165
+ struct StepsWidget: Widget {
140
166
  var body: some WidgetConfiguration {
141
- StaticConfiguration(kind: "timer",
142
- provider: Provider()) { entry in
143
- TimerView(entry: entry)
167
+ StaticConfiguration(kind: "steps", provider: StepsProvider()) { entry in
168
+ StepsView(entry: entry)
144
169
  }
145
- .configurationDisplayName(LocalizedStringResource("Timer"))
170
+ .configurationDisplayName(LocalizedStringResource("Daily Steps"))
146
171
  }
147
172
  }
148
173
 
149
- // Pass around without resolving yet
150
- func showAlert(title: LocalizedStringResource, message: LocalizedStringResource) {
151
- // Resolved at display time with the user's current locale
152
- let resolved = String(localized: title)
174
+ func showToast(_ message: LocalizedStringResource) {
175
+ let text = String(localized: message) // resolved in the current locale
176
+ toastCenter.present(text)
153
177
  }
154
178
  ```
155
179
 
156
- ### When to use each type
180
+ ### Which type where
157
181
 
158
182
  | Context | Type | Why |
159
- |---------|------|-----|
160
- | SwiftUI view text parameters | `LocalizedStringKey` (implicit) | SwiftUI handles lookup automatically |
161
- | Computed strings in view models / services | `String(localized:)` | Returns resolved `String` for logic |
162
- | App Intents, widgets, system APIs | `LocalizedStringResource` | Framework resolves at display time |
163
- | Error messages shown to users | `String(localized:)` | Resolved in catch blocks |
164
- | Logging / analytics (not user-facing) | Plain `String` | No localization needed |
165
-
166
- ## String Interpolation in Localized Strings
167
-
168
- Interpolated values in localized strings become positional arguments that translators can reorder.
183
+ |---|---|---|
184
+ | SwiftUI view text parameters | `LocalizedStringKey` (implicit) | SwiftUI does the lookup |
185
+ | Strings built in view models or services | `String(localized:)` | Logic needs the resolved value |
186
+ | App Intents, widgets, system APIs | `LocalizedStringResource` | The framework resolves at display time |
187
+ | Error text shown to the user | `String(localized:)` | Resolved inside the `catch` |
188
+ | Logs and analytics | `String` | Never shown to users |
169
189
 
170
- ```swift
171
- // English: "Welcome, Alice! You have 3 new messages."
172
- // German: "Willkommen, Alice! Sie haben 3 neue Nachrichten."
173
- // Japanese: "Alice さん、新しいメッセージが 3 件あります。"
174
- let text = String(localized: "Welcome, \(name)! You have \(count) new messages.")
175
- ```
190
+ ## Interpolation
176
191
 
177
- In the String Catalog, this appears with `%@` and `%lld` placeholders that translators can reorder:
178
- - English: `"Welcome, %@! You have %lld new messages."`
179
- - Japanese: `"%@さん、新しいメッセージが%lld件あります。"`
192
+ Interpolated values become positional arguments, so a translator can move them
193
+ around the sentence:
180
194
 
181
- **Type-safe interpolation** (preferred over format specifiers):
182
195
  ```swift
183
- // Interpolation provides type safety
184
- String(localized: "Score: \(score, format: .number)")
185
- String(localized: "Due: \(date, format: .dateTime.month().day())")
196
+ let summary = String(localized: "\(guestName) booked \(nights) nights")
197
+ // Catalog key: "%@ booked %lld nights"
198
+ // Japanese can place the arguments in its own order.
186
199
  ```
187
200
 
188
- ## Pluralization
189
-
190
- String Catalogs handle pluralization natively -- no `.stringsdict` XML required.
201
+ Give interpolations a format instead of raw specifiers:
202
+ `\(distance, format: .number)` or `\(departure, format: .dateTime.hour().minute())`.
191
203
 
192
- ### Setup in String Catalog
204
+ ## Plurals
193
205
 
194
- When a localized string contains an integer interpolation, Xcode detects it and offers plural variants in the String Catalog editor. Supply translations for each CLDR plural category:
195
-
196
- | Category | English example | Arabic example |
197
- |----------|----------------|----------------|
198
- | zero | (not used) | 0 items |
199
- | one | 1 item | 1 item |
200
- | two | (not used) | 2 items (dual) |
201
- | few | (not used) | 3-10 items |
202
- | many | (not used) | 11-99 items |
203
- | other | 2+ items | 100+ items |
204
-
205
- English uses only `one` and `other`. Arabic uses all six. Always supply `other` as the fallback.
206
+ Catalogs model plurals directly; no `.stringsdict`. Interpolate an integer,
207
+ build, and the editor offers plural variants for that key. CLDR defines six
208
+ categories: zero, one, two, few, many, other. English only uses one and other.
209
+ Arabic uses all six: zero, one, two (dual), few (3 to 10), many (11 to 99) and
210
+ other (100 and up). Always fill `other`; it is the fallback.
206
211
 
207
212
  ```swift
208
- // Code -- single interpolation triggers plural support
209
- Text("\(unreadCount) unread messages")
210
-
211
- // String Catalog entries (English):
212
- // one: "%lld unread message"
213
- // other: "%lld unread messages"
213
+ Text("\(pendingInvites) pending invites")
214
+ // en one: "%lld pending invite"
215
+ // en other: "%lld pending invites"
214
216
  ```
215
217
 
216
- ### Device Variations
218
+ ### Device variations
217
219
 
218
- String Catalogs support device-specific text (iPhone vs iPad vs Mac):
220
+ Vary by Device lets one key read differently per device, for instance "Tap to
221
+ edit" on iPhone, "Tap or click to edit" on iPad and "Click to edit" on Mac.
219
222
 
220
- ```swift
221
- // In String Catalog editor, enable "Vary by Device" for a key
222
- // iPhone: "Tap to continue"
223
- // iPad: "Tap or click to continue"
224
- // Mac: "Click to continue"
225
- ```
223
+ ### Grammar agreement (iOS 15+)
226
224
 
227
- ### Grammar Agreement (iOS 15+)
228
-
229
- Use `^[...]` inflection syntax for automatic grammatical agreement:
230
-
231
- ```swift
232
- // Automatically adjusts for gender/number in supported languages
233
- Text("^[\(count) \("photo")](inflect: true) added")
234
- // English: "1 photo added" / "3 photos added"
235
- // Spanish: "1 foto agregada" / "3 fotos agregadas"
236
- ```
237
-
238
- ## FormatStyle -- Locale-Aware Formatting
239
-
240
- Never hard-code date, number, or measurement formats. Use `FormatStyle` (iOS 15+) so formatting adapts to the user's locale automatically.
241
-
242
- Locale-aware formatting matters even in single-language apps because user locale affects separators, calendars, currency, units, names, and list formatting. When giving user-facing formatting advice, explicitly recommend testing or previewing output under multiple locales such as `en_US`, `de_DE`, `ar_SA`, and `ja_JP`.
243
-
244
- `ios-localization` owns `FormatStyle` guidance when the issue is locale-aware user-facing display, including numbers, dates, currency, units, names, lists, calendars, separators, and locale preview/testing. For custom `FormatStyle`, `ParseableFormatStyle`, parsing, `Date.IntervalFormatStyle`, `URL.FormatStyle`, or reusable formatter API design, route to `swift-formatstyle`; keep `ios-localization` advice to locale risks and testing unless implementation is explicitly requested.
245
-
246
- ### Dates
247
-
248
- ```swift
249
- let now = Date.now
250
-
251
- // Preset styles
252
- now.formatted(date: .long, time: .shortened)
253
- // US: "January 15, 2026 at 3:30 PM"
254
- // DE: "15. Januar 2026 um 15:30"
255
- // JP: "2026年1月15日 15:30"
256
-
257
- // Component-based
258
- now.formatted(.dateTime.month(.wide).day().year())
259
- // US: "January 15, 2026"
260
-
261
- // In SwiftUI
262
- Text(now, format: .dateTime.month().day().year())
263
- ```
264
-
265
- ### Numbers
225
+ Automatic grammar agreement fixes gender and number for supported languages
226
+ with the inflection markup `^[...](inflect: true)`:
266
227
 
267
228
  ```swift
268
- let count = 1234567
269
- count.formatted() // "1,234,567" (US) / "1.234.567" (DE)
270
- count.formatted(.number.precision(.fractionLength(2)))
271
- count.formatted(.percent) // For 0.85 -> "85%" (US) / "85 %" (FR)
272
-
273
- // Currency
274
- let price = Decimal(29.99)
275
- price.formatted(.currency(code: "USD")) // "$29.99" (US) / "29,99 $US" (FR)
276
- price.formatted(.currency(code: "EUR")) // "29,99 EUR" (DE)
229
+ Text("Added ^[\(bottleCount) bottle](inflect: true) to your cellar")
230
+ // English: 1 bottle / 3 bottles; Spanish forms agree automatically.
277
231
  ```
278
232
 
279
- ### Measurements
233
+ ## Locale-Aware Formatting with FormatStyle
280
234
 
281
- ```swift
282
- let distance = Measurement(value: 5, unit: UnitLength.kilometers)
283
- distance.formatted(.measurement(width: .wide))
284
- // US: "3.1 miles" (auto-converts!) / DE: "5 Kilometer"
235
+ Never hard-code date, number or measurement patterns; use `FormatStyle`
236
+ (iOS 15+). Locale still matters in a one-language app: decimal and grouping
237
+ separators, calendars, currency symbols, units, name order and list
238
+ conjunctions all follow the user's region. Whenever you advise on user-facing
239
+ formatting, also tell the reader to preview or test under several locales such
240
+ as `en_US`, `de_DE`, `ar_SA` and `ja_JP`.
285
241
 
286
- let temp = Measurement(value: 22, unit: UnitTemperature.celsius)
287
- temp.formatted(.measurement(width: .abbreviated))
288
- // US: "72 F" (auto-converts!) / FR: "22 C"
289
- ```
290
-
291
- ### Duration, PersonName, Lists
242
+ Scope boundary: this skill owns `FormatStyle` for locale-aware display
243
+ (numbers, dates, currency, units, names, lists, calendars, separators, and
244
+ locale previews and tests). Custom `FormatStyle` types, `ParseableFormatStyle`,
245
+ parsing, `Date.IntervalFormatStyle`, `URL.FormatStyle` and reusable formatter
246
+ API design belong to `swift-formatstyle`. Here, only point out locale risks and
247
+ testing for those, unless the user explicitly asks for an implementation.
292
248
 
293
249
  ```swift
294
- // Duration
295
- let dur = Duration.seconds(3661)
296
- dur.formatted(.time(pattern: .hourMinuteSecond)) // "1:01:01"
297
-
298
- // Person names
299
- let name = PersonNameComponents(givenName: "John", familyName: "Doe")
300
- name.formatted(.name(style: .long)) // "John Doe" (US) / "Doe John" (JP)
301
-
302
- // Lists
303
- let items = ["Apples", "Oranges", "Bananas"]
304
- items.formatted(.list(type: .and)) // "Apples, Oranges, and Bananas" (EN)
305
- // "Apples, Oranges et Bananas" (FR)
250
+ let flight = Date.now
251
+ flight.formatted(date: .long, time: .shortened)
252
+ // en_US "June 3, 2026 at 4:05 PM", de_DE "3. Juni 2026 um 16:05"; ja_JP uses year-month-day order
253
+ flight.formatted(.dateTime.month(.wide).day().year())
254
+ Text(flight, format: .dateTime.weekday().hour().minute())
255
+
256
+ let visitors = 1_284_503
257
+ visitors.formatted() // "1,284,503" / "1.284.503"
258
+ 3.14159.formatted(.number.precision(.fractionLength(2)))
259
+ 0.18.formatted(.percent) // "18%"
260
+ Decimal(59.9).formatted(.currency(code: "USD"))
261
+ Decimal(59.9).formatted(.currency(code: "EUR")) // symbol position follows locale
262
+
263
+ Measurement(value: 42, unit: UnitLength.kilometers)
264
+ .formatted(.measurement(width: .wide)) // miles in en_US
265
+ Measurement(value: 21, unit: UnitTemperature.celsius)
266
+ .formatted(.measurement(width: .abbreviated)) // Fahrenheit in en_US
267
+
268
+ Duration.seconds(5_025).formatted(.time(pattern: .hourMinuteSecond)) // "1:23:45"
269
+ var author = PersonNameComponents(); author.givenName = "Aiko"; author.familyName = "Tanaka"
270
+ author.formatted(.name(style: .long)) // order differs en_US vs ja_JP
271
+ ["tea", "coffee", "juice"].formatted(.list(type: .and)) // "tea, coffee, and juice"; French joins with "et" and no serial comma
306
272
  ```
307
273
 
308
- For the complete FormatStyle reference, custom styles, and RTL layout, see [references/formatstyle-locale.md](references/formatstyle-locale.md).
309
-
310
- ## Right-to-Left (RTL) Layout
311
-
312
- SwiftUI automatically mirrors layouts for RTL languages (Arabic, Hebrew, Urdu, Persian). Most views require zero changes.
313
-
314
- ### What SwiftUI auto-mirrors
274
+ Full coverage of every style is in
275
+ [references/formatstyle-locale.md](references/formatstyle-locale.md).
315
276
 
316
- - `HStack` children reverse order
317
- - `.leading` / `.trailing` alignment and padding swap sides
318
- - `NavigationStack` back button moves to trailing edge
319
- - `List` disclosure indicators flip
320
- - Text alignment follows reading direction
277
+ ## Right-to-Left Layout
321
278
 
322
- ### What needs manual attention
279
+ SwiftUI mirrors layout for Arabic, Hebrew, Urdu and Persian on its own; most
280
+ views need nothing. It flips `HStack` order, `.leading` and `.trailing`
281
+ alignment and padding, puts the `NavigationStack` back button on the trailing
282
+ side, mirrors `List` disclosure chevrons, and aligns text to the reading
283
+ direction.
323
284
 
324
285
  ```swift
325
- // Testing RTL in previews
326
- MyView()
327
- .environment(\.layoutDirection, .rightToLeft)
328
- .environment(\.locale, Locale(identifier: "ar"))
286
+ #Preview("Checkout, Arabic") {
287
+ CheckoutView()
288
+ .environment(\.layoutDirection, .rightToLeft)
289
+ .environment(\.locale, Locale(identifier: "ar"))
290
+ }
329
291
 
330
- // Images that should mirror (directional arrows, progress indicators)
331
- Image(systemName: "chevron.right")
292
+ Image(systemName: "arrowshape.forward") // directional: mirror it
332
293
  .flipsForRightToLeftLayoutDirection(true)
333
294
 
334
- // Images that should NOT mirror: logos, photos, clocks, music notes
335
-
336
- // Forced LTR for specific content (phone numbers, code)
337
- Text("+1 (555) 123-4567")
295
+ Text(verbatim: supportHotline) // phone numbers and code stay LTR
338
296
  .environment(\.layoutDirection, .leftToRight)
339
297
  ```
340
298
 
341
- ### Layout rules
299
+ Leave logos, photos, clocks and musical notation unmirrored.
342
300
 
343
- - **DO** use `.leading` / `.trailing` -- they auto-flip for RTL
344
- - **DON'T** use `.left` / `.right` -- they are fixed and break RTL
345
- - **DO** use `HStack` / `VStack` -- they respect layout direction
346
- - **DON'T** use absolute `offset(x:)` for directional positioning
301
+ Rules: prefer `.leading` and `.trailing` (they flip) over `.left` and `.right`
302
+ (they do not); build with `HStack` and `VStack`; do not use absolute
303
+ `offset(x:)` to place things in a direction.
347
304
 
348
305
  ## Common Mistakes
349
306
 
350
- ### DON'T: Use NSLocalizedString in new Swift code
351
- ```swift
352
- // LEGACY -- Xcode can export literal keys, but new Swift code should use modern APIs
353
- let title = NSLocalizedString("welcome_title", comment: "Welcome screen title")
354
- ```
355
-
356
- ### DO: Use String(localized:) or let SwiftUI handle it
357
- ```swift
358
- // CORRECT
359
- let title = String(localized: "welcome_title",
360
- defaultValue: "Welcome!",
361
- comment: "Welcome screen title")
362
- // Or in SwiftUI, just:
363
- Text("Welcome!")
364
- ```
365
-
366
- ### DON'T: Concatenate localized strings
367
- ```swift
368
- // WRONG -- word order varies by language
369
- let greeting = String(localized: "Hello") + ", " + name + "!"
370
- ```
371
-
372
- ### DO: Use string interpolation
373
- ```swift
374
- // CORRECT -- translators can reorder placeholders
375
- let greeting = String(localized: "Hello, \(name)!")
376
- ```
377
-
378
- ### DON'T: Hard-code date/number formats
379
- ```swift
380
- // WRONG -- US-only format
381
- let formatter = DateFormatter()
382
- formatter.dateFormat = "MM/dd/yyyy" // Meaningless in most countries
383
- ```
384
-
385
- ### DO: Use FormatStyle
386
- ```swift
387
- // CORRECT -- adapts to user locale
388
- Text(date, format: .dateTime.month().day().year())
389
- ```
390
-
391
- ### DON'T: Use fixed-width layouts
392
- ```swift
393
- // WRONG -- German text is ~30% longer than English
394
- Text(title).frame(width: 120)
395
- ```
396
-
397
- ### DO: Use flexible layouts
398
- ```swift
399
- // CORRECT
400
- Text(title).fixedSize(horizontal: false, vertical: true)
401
- // Or use VStack/wrapping that accommodates expansion
402
- ```
403
-
404
- ### DON'T: Use .left / .right for alignment
405
- ```swift
406
- // WRONG -- does not flip for RTL
407
- HStack { Spacer(); text }.padding(.left, 16)
408
- ```
409
-
410
- ### DO: Use .leading / .trailing
411
- ```swift
412
- // CORRECT
413
- HStack { Spacer(); text }.padding(.leading, 16)
414
- ```
415
-
416
- ### DON'T: Put user-facing strings as plain String outside SwiftUI
417
- ```swift
418
- // WRONG -- not localized
419
- let errorMessage = "Something went wrong"
420
- showAlert(message: errorMessage)
421
- ```
422
-
423
- ### DO: Use LocalizedStringResource for deferred resolution
424
- ```swift
425
- // CORRECT
426
- let errorMessage = LocalizedStringResource("Something went wrong")
427
- showAlert(message: String(localized: errorMessage))
428
- ```
429
-
430
- ### DON'T: Use natural-language text as the key for manually-managed strings
431
- ```swift
432
- // WRONG -- typo silently creates a new key, stales the old one, no compiler error
433
- Text("Wlecome Back") // was "Welcome Back" -- silent localization break
434
- ```
435
-
436
- ### DO: Use stable symbol-style keys and enable generated symbols
437
- ```swift
438
- // CORRECT -- key is stable; UI text lives in the catalog's default value
439
- Text(.welcomeBack) // generated from key "welcome_back" in String Catalog
440
- // Or without generated symbols:
441
- String(localized: "welcome_back", defaultValue: "Welcome Back")
442
- ```
443
-
444
- ### DON'T: Skip pseudolocalization testing
445
- Testing only in English hides truncation, layout, and RTL bugs.
446
-
447
- ### DO: Test with German (long) and Arabic (RTL) at minimum
448
- Use Xcode scheme settings to override the app language without changing device locale.
307
+ 1. `NSLocalizedString` in new Swift code. It is legacy; use
308
+ `String(localized:defaultValue:comment:)` or a `Text` literal.
309
+ 2. Building a sentence from localized fragments. Word order changes between
310
+ languages; localize one interpolated string.
311
+ 3. `DateFormatter` with a fixed `dateFormat` such as `"MM/dd/yyyy"`. Use
312
+ `Text(date, format: .dateTime.month().day().year())` or another FormatStyle.
313
+ 4. Fixed widths like `.frame(width: 120)` around text. German runs roughly 30%
314
+ longer than English; let text wrap with
315
+ `.fixedSize(horizontal: false, vertical: true)` or flexible stacks.
316
+ 5. `.padding(.left, 12)`. Use `.padding(.leading, 12)`.
317
+ 6. Passing user-facing text around as `String` outside SwiftUI. Carry a
318
+ `LocalizedStringResource` and resolve it with `String(localized:)` where it
319
+ is shown.
320
+ 7. English sentences as keys for strings you manage by hand. A typo creates a
321
+ brand new key, the old one goes stale, and the compiler says nothing. Use
322
+ stable symbol-style keys, for example `order_shipped` read as
323
+ `Text(.orderShipped)`, or
324
+ `String(localized: "order_shipped", defaultValue: "Your order is on its way")`.
325
+ 8. Testing only in English. Truncation, layout and RTL bugs stay hidden;
326
+ run the pseudolanguages.
327
+ 9. Not testing German (long text) and Arabic (RTL) at minimum. Switch the app
328
+ language in the scheme options instead of changing the device locale.
449
329
 
450
330
  ## Review Checklist
451
331
 
452
- - [ ] All user-facing strings use localization (`LocalizedStringKey` in SwiftUI or `String(localized:)`)
453
- - [ ] No string concatenation for user-visible text
454
- - [ ] Dates and numbers use `FormatStyle`, not hardcoded formats
455
- - [ ] Pluralization handled via String Catalog plural variants (not manual if/else)
456
- - [ ] Layout uses `.leading` / `.trailing`, not `.left` / `.right`
457
- - [ ] UI tested with long text (German) and RTL (Arabic)
458
- - [ ] String Catalog includes all target languages
459
- - [ ] Images needing RTL mirroring use `.flipsForRightToLeftLayoutDirection(true)`
460
- - [ ] App Intents and widgets use `LocalizedStringResource`
461
- - [ ] No `NSLocalizedString` usage in new code
462
- - [ ] Comments provided for ambiguous keys (context for translators)
463
- - [ ] `@ScaledMetric` used for spacing that must scale with Dynamic Type
464
- - [ ] Currency formatting uses explicit currency code, not locale default
465
- - [ ] Pseudolocalization tested (accented, right-to-left, double-length)
466
- - [ ] Manually-managed keys use stable symbol-style names, not English text as the key
467
- - [ ] Generate String Catalog Symbols enabled for targets with manually-managed keys
468
- - [ ] Ensure localized string types are Sendable; use @MainActor for locale-change UI updates
332
+ - [ ] Every user-facing string is localized (`LocalizedStringKey` or
333
+ `String(localized:)`)
334
+ - [ ] No string concatenation for visible text
335
+ - [ ] Dates and numbers go through `FormatStyle`, never fixed patterns
336
+ - [ ] Plurals use catalog plural variants, not `if count == 1`
337
+ - [ ] `.leading` and `.trailing` instead of `.left` and `.right`
338
+ - [ ] UI checked with long text (German) and RTL (Arabic)
339
+ - [ ] The catalog lists every shipping language
340
+ - [ ] Directional images use `.flipsForRightToLeftLayoutDirection(true)`
341
+ - [ ] App Intents and widgets take `LocalizedStringResource`
342
+ - [ ] No `NSLocalizedString` in new code
343
+ - [ ] Ambiguous keys carry translator comments
344
+ - [ ] Spacing that must track Dynamic Type uses `@ScaledMetric`
345
+ - [ ] Currency always names an explicit currency code instead of relying on the
346
+ locale default
347
+ - [ ] Pseudolocalization run: accented, right-to-left, double-length
348
+ - [ ] Hand-managed keys are stable symbol-style names, not English sentences
349
+ - [ ] Generate String Catalog Symbols is on for targets with manual keys
350
+ - [ ] Localized string types are `Sendable`; UI reacting to a locale change
351
+ updates on `@MainActor`
469
352
 
470
353
  ## References
471
354
 
472
- - FormatStyle patterns: [references/formatstyle-locale.md](references/formatstyle-locale.md)
473
- - String Catalogs guide: [references/string-catalogs.md](references/string-catalogs.md)
355
+ - [references/string-catalogs.md](references/string-catalogs.md): catalogs,
356
+ keys, bundles, packages, plurals, translator workflow, JSON, symbols,
357
+ testing and migration.
358
+ - [references/formatstyle-locale.md](references/formatstyle-locale.md):
359
+ FormatStyle per value type, forcing a locale, RTL, `@ScaledMetric` and
360
+ Accessibility Inspector.