{"id":"e9b09a61-b84a-4c88-bebc-b1d17ff9cc9d","shortId":"kS3YqZ","kind":"skill","title":"Ios Localization","tagline":"Swift Ios Skills skill by Dpearson2699","description":"# iOS Localization & Internationalization\n\nLocalize 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.\n\n## Contents\n\n- [String Catalogs (.xcstrings)](#string-catalogs-xcstrings)\n- [String Types -- Decision Guide](#string-types-decision-guide)\n- [String Interpolation in Localized Strings](#string-interpolation-in-localized-strings)\n- [Pluralization](#pluralization)\n- [FormatStyle -- Locale-Aware Formatting](#formatstyle-locale-aware-formatting)\n- [Right-to-Left (RTL) Layout](#right-to-left-rtl-layout)\n- [Common Mistakes](#common-mistakes)\n- [Localization Review Checklist](#review-checklist)\n- [References](#references)\n\n## String Catalogs (.xcstrings)\n\nString Catalogs replaced `.strings` and `.stringsdict` files starting in Xcode 15 / iOS 17. They unify all localizable strings, pluralization rules, and device variations into a single JSON-based file with a visual editor.\n\n**Why String Catalogs exist:**\n- `.strings` files required manual key management and fell out of sync\n- `.stringsdict` required complex XML for plurals\n- String Catalogs auto-extract strings from code, track translation state, and support plurals natively\n\n**How automatic extraction works:**\n\nXcode scans for these patterns on each build:\n\n```swift\n// SwiftUI -- automatically extracted (LocalizedStringKey)\nText(\"Welcome back\")              // key: \"Welcome back\"\nLabel(\"Settings\", systemImage: \"gear\")\nButton(\"Save\") { }\nToggle(\"Dark Mode\", isOn: $dark)\n\n// Programmatic -- automatically extracted\nString(localized: \"No items found\")\nLocalizedStringResource(\"Order placed\")\n\n// NOT extracted -- plain String, not localized\nlet msg = \"Hello\"                 // just a String, invisible to Xcode\n```\n\nXcode adds discovered keys to the String Catalog automatically. Mark translations as Needs Review, Translated, or Stale in the editor.\n\nFor detailed String Catalog workflows, migration, and testing strategies, see [references/string-catalogs.md](references/string-catalogs.md).\n\n## String Types -- Decision Guide\n\n### LocalizedStringKey (SwiftUI default)\n\nSwiftUI views accept `LocalizedStringKey` for their text parameters. String literals are implicitly converted -- no extra work needed.\n\n```swift\n// These all create a LocalizedStringKey lookup automatically:\nText(\"Welcome back\")\nLabel(\"Profile\", systemImage: \"person\")\nButton(\"Delete\") { deleteItem() }\n.navigationTitle(\"Home\")\n```\n\nUse `LocalizedStringKey` when passing strings directly to SwiftUI view initializers. Do not construct `LocalizedStringKey` manually in most cases.\n\n### String(localized:) -- Modern NSLocalizedString replacement\n\nUse for any localized string outside a SwiftUI view initializer. Returns a plain `String`. Available iOS 16+.\n\n```swift\n// Basic\nlet title = String(localized: \"Welcome back\")\n\n// With default value (key differs from English text)\nlet msg = String(localized: \"error.network\",\n                 defaultValue: \"Check your internet connection\")\n\n// With table and bundle\nlet label = String(localized: \"onboarding.title\",\n                   table: \"Onboarding\",\n                   bundle: .module)\n\n// With comment for translators\nlet btn = String(localized: \"Save\",\n                 comment: \"Button title to save the current document\")\n```\n\n### LocalizedStringResource -- Pass localization info without resolving\n\nUse when you need to pass a localized string to an API that resolves it later (App Intents, widgets, notifications, system frameworks). Available iOS 16+.\n\n```swift\n// App Intents require LocalizedStringResource\nstruct OrderCoffeeIntent: AppIntent {\n    static var title: LocalizedStringResource = \"Order Coffee\"\n}\n\n// Widgets\nstruct MyWidget: Widget {\n    var body: some WidgetConfiguration {\n        StaticConfiguration(kind: \"timer\",\n                            provider: Provider()) { entry in\n            TimerView(entry: entry)\n        }\n        .configurationDisplayName(LocalizedStringResource(\"Timer\"))\n    }\n}\n\n// Pass around without resolving yet\nfunc showAlert(title: LocalizedStringResource, message: LocalizedStringResource) {\n    // Resolved at display time with the user's current locale\n    let resolved = String(localized: title)\n}\n```\n\n### When to use each type\n\n| Context | Type | Why |\n|---------|------|-----|\n| SwiftUI view text parameters | `LocalizedStringKey` (implicit) | SwiftUI handles lookup automatically |\n| Computed strings in view models / services | `String(localized:)` | Returns resolved `String` for logic |\n| App Intents, widgets, system APIs | `LocalizedStringResource` | Framework resolves at display time |\n| Error messages shown to users | `String(localized:)` | Resolved in catch blocks |\n| Logging / analytics (not user-facing) | Plain `String` | No localization needed |\n\n## String Interpolation in Localized Strings\n\nInterpolated values in localized strings become positional arguments that translators can reorder.\n\n```swift\n// English: \"Welcome, Alice! You have 3 new messages.\"\n// German:  \"Willkommen, Alice! Sie haben 3 neue Nachrichten.\"\n// Japanese: \"Alice さん、新しいメッセージが 3 件あります。\"\nlet text = String(localized: \"Welcome, \\(name)! You have \\(count) new messages.\")\n```\n\nIn the String Catalog, this appears with `%@` and `%lld` placeholders that translators can reorder:\n- English: `\"Welcome, %@! You have %lld new messages.\"`\n- Japanese: `\"%@さん、新しいメッセージが%lld件あります。\"`\n\n**Type-safe interpolation** (preferred over format specifiers):\n```swift\n// Interpolation provides type safety\nString(localized: \"Score: \\(score, format: .number)\")\nString(localized: \"Due: \\(date, format: .dateTime.month().day())\")\n```\n\n## Pluralization\n\nString Catalogs handle pluralization natively -- no `.stringsdict` XML required.\n\n### Setup in String Catalog\n\nWhen 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:\n\n| Category | English example | Arabic example |\n|----------|----------------|----------------|\n| zero | (not used) | 0 items |\n| one | 1 item | 1 item |\n| two | (not used) | 2 items (dual) |\n| few | (not used) | 3-10 items |\n| many | (not used) | 11-99 items |\n| other | 2+ items | 100+ items |\n\nEnglish uses only `one` and `other`. Arabic uses all six. Always supply `other` as the fallback.\n\n```swift\n// Code -- single interpolation triggers plural support\nText(\"\\(unreadCount) unread messages\")\n\n// String Catalog entries (English):\n//   one:   \"%lld unread message\"\n//   other: \"%lld unread messages\"\n```\n\n### Device Variations\n\nString Catalogs support device-specific text (iPhone vs iPad vs Mac):\n\n```swift\n// In String Catalog editor, enable \"Vary by Device\" for a key\n// iPhone: \"Tap to continue\"\n// iPad:   \"Tap or click to continue\"\n// Mac:    \"Click to continue\"\n```\n\n### Grammar Agreement (iOS 17+)\n\nUse `^[...]` inflection syntax for automatic grammatical agreement:\n\n```swift\n// Automatically adjusts for gender/number in supported languages\nText(\"^[\\(count) \\(\"photo\")](inflect: true) added\")\n// English: \"1 photo added\" / \"3 photos added\"\n// Spanish: \"1 foto agregada\" / \"3 fotos agregadas\"\n```\n\n## FormatStyle -- Locale-Aware Formatting\n\nNever hard-code date, number, or measurement formats. Use `FormatStyle` (iOS 15+) so formatting adapts to the user's locale automatically.\n\n### Dates\n\n```swift\nlet now = Date.now\n\n// Preset styles\nnow.formatted(date: .long, time: .shortened)\n// US: \"January 15, 2026 at 3:30 PM\"\n// DE: \"15. Januar 2026 um 15:30\"\n// JP: \"2026年1月15日 15:30\"\n\n// Component-based\nnow.formatted(.dateTime.month(.wide).day().year())\n// US: \"January 15, 2026\"\n\n// In SwiftUI\nText(now, format: .dateTime.month().day().year())\n```\n\n### Numbers\n\n```swift\nlet count = 1234567\ncount.formatted()                     // \"1,234,567\" (US) / \"1.234.567\" (DE)\ncount.formatted(.number.precision(.fractionLength(2)))\ncount.formatted(.percent)             // For 0.85 -> \"85%\" (US) / \"85 %\" (FR)\n\n// Currency\nlet price = Decimal(29.99)\nprice.formatted(.currency(code: \"USD\"))  // \"$29.99\" (US) / \"29,99 $US\" (FR)\nprice.formatted(.currency(code: \"EUR\"))  // \"29,99 EUR\" (DE)\n```\n\n### Measurements\n\n```swift\nlet distance = Measurement(value: 5, unit: UnitLength.kilometers)\ndistance.formatted(.measurement(width: .wide))\n// US: \"3.1 miles\" (auto-converts!) / DE: \"5 Kilometer\"\n\nlet temp = Measurement(value: 22, unit: UnitTemperature.celsius)\ntemp.formatted(.measurement(width: .abbreviated))\n// US: \"72 F\" (auto-converts!) / FR: \"22 C\"\n```\n\n### Duration, PersonName, Lists\n\n```swift\n// Duration\nlet dur = Duration.seconds(3661)\ndur.formatted(.time(pattern: .hourMinuteSecond))  // \"1:01:01\"\n\n// Person names\nlet name = PersonNameComponents(givenName: \"John\", familyName: \"Doe\")\nname.formatted(.name(style: .long))   // \"John Doe\" (US) / \"Doe John\" (JP)\n\n// Lists\nlet items = [\"Apples\", \"Oranges\", \"Bananas\"]\nitems.formatted(.list(type: .and))    // \"Apples, Oranges, and Bananas\" (EN)\n                                      // \"Apples, Oranges et Bananas\" (FR)\n```\n\nFor the complete FormatStyle reference, custom styles, and RTL layout, see [references/formatstyle-locale.md](references/formatstyle-locale.md).\n\n## Right-to-Left (RTL) Layout\n\nSwiftUI automatically mirrors layouts for RTL languages (Arabic, Hebrew, Urdu, Persian). Most views require zero changes.\n\n### What SwiftUI auto-mirrors\n\n- `HStack` children reverse order\n- `.leading` / `.trailing` alignment and padding swap sides\n- `NavigationStack` back button moves to trailing edge\n- `List` disclosure indicators flip\n- Text alignment follows reading direction\n\n### What needs manual attention\n\n```swift\n// Testing RTL in previews\nMyView()\n    .environment(\\.layoutDirection, .rightToLeft)\n    .environment(\\.locale, Locale(identifier: \"ar\"))\n\n// Images that should mirror (directional arrows, progress indicators)\nImage(systemName: \"chevron.right\")\n    .flipsForRightToLeftLayoutDirection(true)\n\n// Images that should NOT mirror: logos, photos, clocks, music notes\n\n// Forced LTR for specific content (phone numbers, code)\nText(\"+1 (555) 123-4567\")\n    .environment(\\.layoutDirection, .leftToRight)\n```\n\n### Layout rules\n\n- **DO** use `.leading` / `.trailing` -- they auto-flip for RTL\n- **DON'T** use `.left` / `.right` -- they are fixed and break RTL\n- **DO** use `HStack` / `VStack` -- they respect layout direction\n- **DON'T** use absolute `offset(x:)` for directional positioning\n\n## Common Mistakes\n\n### DON'T: Use NSLocalizedString in new code\n```swift\n// WRONG -- legacy API, verbose, no compiler integration with String Catalogs\nlet title = NSLocalizedString(\"welcome_title\", comment: \"Welcome screen title\")\n```\n\n### DO: Use String(localized:) or let SwiftUI handle it\n```swift\n// CORRECT\nlet title = String(localized: \"welcome_title\",\n                   defaultValue: \"Welcome!\",\n                   comment: \"Welcome screen title\")\n// Or in SwiftUI, just:\nText(\"Welcome!\")\n```\n\n### DON'T: Concatenate localized strings\n```swift\n// WRONG -- word order varies by language\nlet greeting = String(localized: \"Hello\") + \", \" + name + \"!\"\n```\n\n### DO: Use string interpolation\n```swift\n// CORRECT -- translators can reorder placeholders\nlet greeting = String(localized: \"Hello, \\(name)!\")\n```\n\n### DON'T: Hard-code date/number formats\n```swift\n// WRONG -- US-only format\nlet formatter = DateFormatter()\nformatter.dateFormat = \"MM/dd/yyyy\"  // Meaningless in most countries\n```\n\n### DO: Use FormatStyle\n```swift\n// CORRECT -- adapts to user locale\nText(date, format: .dateTime.month().day().year())\n```\n\n### DON'T: Use fixed-width layouts\n```swift\n// WRONG -- German text is ~30% longer than English\nText(title).frame(width: 120)\n```\n\n### DO: Use flexible layouts\n```swift\n// CORRECT\nText(title).fixedSize(horizontal: false, vertical: true)\n// Or use VStack/wrapping that accommodates expansion\n```\n\n### DON'T: Use .left / .right for alignment\n```swift\n// WRONG -- does not flip for RTL\nHStack { Spacer(); text }.padding(.left, 16)\n```\n\n### DO: Use .leading / .trailing\n```swift\n// CORRECT\nHStack { Spacer(); text }.padding(.leading, 16)\n```\n\n### DON'T: Put user-facing strings as plain String outside SwiftUI\n```swift\n// WRONG -- not localized\nlet errorMessage = \"Something went wrong\"\nshowAlert(message: errorMessage)\n```\n\n### DO: Use LocalizedStringResource for deferred resolution\n```swift\n// CORRECT\nlet errorMessage = LocalizedStringResource(\"Something went wrong\")\nshowAlert(message: String(localized: errorMessage))\n```\n\n### DON'T: Skip pseudolocalization testing\nTesting only in English hides truncation, layout, and RTL bugs.\n\n### DO: Test with German (long) and Arabic (RTL) at minimum\nUse Xcode scheme settings to override the app language without changing device locale.\n\n## Review Checklist\n\n- [ ] All user-facing strings use localization (`LocalizedStringKey` in SwiftUI or `String(localized:)`)\n- [ ] No string concatenation for user-visible text\n- [ ] Dates and numbers use `FormatStyle`, not hardcoded formats\n- [ ] Pluralization handled via String Catalog plural variants (not manual if/else)\n- [ ] Layout uses `.leading` / `.trailing`, not `.left` / `.right`\n- [ ] UI tested with long text (German) and RTL (Arabic)\n- [ ] String Catalog includes all target languages\n- [ ] Images needing RTL mirroring use `.flipsForRightToLeftLayoutDirection(true)`\n- [ ] App Intents and widgets use `LocalizedStringResource`\n- [ ] No `NSLocalizedString` usage in new code\n- [ ] Comments provided for ambiguous keys (context for translators)\n- [ ] `@ScaledMetric` used for spacing that must scale with Dynamic Type\n- [ ] Currency formatting uses explicit currency code, not locale default\n- [ ] Pseudolocalization tested (accented, right-to-left, double-length)\n- [ ] Ensure localized string types are Sendable; use @MainActor for locale-change UI updates\n\n## References\n\n- FormatStyle patterns: [references/formatstyle-locale.md](references/formatstyle-locale.md)\n- String Catalogs guide: [references/string-catalogs.md](references/string-catalogs.md)","tags":["ios","localization","swift","skills","dpearson2699"],"capabilities":["skill","source-dpearson2699","category-swift-ios-skills"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/ios-localization","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"install_from":"skills.sh"}},"qualityScore":"0.300","qualityRationale":"deterministic score 0.30 from registry signals: · indexed on skills.sh · published under dpearson2699/swift-ios-skills","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T05:40:37.567Z","embedding":null,"createdAt":"2026-04-18T20:33:26.811Z","updatedAt":"2026-04-22T05:40:37.567Z","lastSeenAt":"2026-04-22T05:40:37.567Z","tsv":"'+1':1215 '-10':745 '-4567':1218 '-99':751 '0':728 '0.85':973 '01':1057,1058 '1':731,733,863,870,960,1056 '1.234.567':964 '100':756 '11':750 '120':1411 '123':1217 '1234567':958 '15':129,893,917,924,928,932,944 '16':364,451,1450,1462 '17':131,840 '2':738,754,969 '2026':918,926,945 '2026年1月15日':931 '22':1027,1041 '234':961 '26':14 '29':989,997 '29.99':982,987 '3':600,608,615,744,866,873,920 '3.1':1015 '30':921,929,933,1403 '3661':1051 '5':1007,1021 '555':1216 '567':962 '72':1035 '85':974,976 '99':990,998 'abbrevi':1033 'absolut':1256 'accent':1655 'accept':290 'accommod':1429 'ad':861,865,868 'adapt':896,1381 'add':250 'adjust':850 'agreement':838,847 'agregada':872,875 'alic':597,605,612 'align':1144,1161,1437 'alway':768 'ambigu':1629 'analyt':567 'api':438,548,1274 'app':15,31,443,453,544,1538,1614 'appear':633 'appint':459 'appl':1081,1088,1093 'ar':1182 'arab':723,764,1124,1527,1600 'argument':589 'around':488 'arrow':1188 'attent':1168 'auto':177,1018,1038,1136,1230 'auto-convert':1017,1037 'auto-extract':176 'auto-flip':1229 'auto-mirror':1135 'automat':190,203,224,257,312,530,845,849,902,1118 'avail':362,449 'awar':26,84,89,879 'back':208,211,315,372,1150 'banana':1083,1091,1096 'base':147,936 'basic':366 'becom':587 'block':565 'bodi':471 'break':1243 'broken':42 'btn':409 'bug':1520 'build':200 'bundl':394,402 'button':216,320,414,1151 'c':1042 'case':342 'catalog':18,53,57,117,120,155,175,256,272,631,681,692,711,786,800,814,1281,1579,1602,1683 'catch':564 'categori':719,720 'category-swift-ios-skills' 'caus':30 'chang':1132,1541,1674 'check':387 'checklist':110,113,1545 'chevron.right':1193 'children':1139 'cldr':717 'click':830,834 'clock':1203 'code':181,775,884,985,995,1213,1270,1358,1625,1649 'coffe':465 'comment':405,413,1287,1310,1626 'common':103,106,1262 'common-mistak':105 'compil':1277 'complet':1100 'complex':170 'compon':935 'component-bas':934 'comput':531 'concaten':1322,1561 'configurationdisplaynam':484 'connect':390 'construct':337 'contain':697 'content':51,1210 'context':518,1631 'continu':826,832,836 'convert':300,1019,1039 'correct':46,1301,1343,1380,1417,1456,1494 'count':625,857,957 'count.formatted':959,966,970 'countri':1375 'creat':308 'currenc':978,984,994,1644,1648 'current':419,506 'custom':1103 'dark':219,222 'date':675,885,903,911,1386,1567 'date.now':907 'date/number':1359 'dateformatt':1369 'datetime.month':677,938,951,1388 'day':678,940,952,1389 'de':923,965,1000,1020 'decim':981 'decis':61,66,283 'default':287,374,1652 'defaultvalu':386,1308 'defer':1491 'delet':321 'deleteitem':322 'detail':270 'detect':702 'devic':140,797,803,819,1542 'device-specif':802 'differ':377 'direct':330,1164,1187,1252,1260 'disclosur':1157 'discov':251 'display':500,553 'distanc':1004 'distance.formatted':1010 'document':420 'doe':1067,1073,1075 'doubl':1661 'double-length':1660 'dpearson2699':8 'dual':740 'due':674 'dur':1049 'dur.formatted':1052 'durat':1043,1047 'duration.seconds':1050 'dynam':1642 'edg':1155 'editor':152,268,712,815 'en':1092 'enabl':816 'english':37,379,595,642,721,758,788,862,1406,1514 'ensur':1663 'entri':479,482,483,787 'environ':1175,1178,1219 'error':555 'error.network':385 'errormessag':1480,1486,1496,1505 'et':1095 'eur':996,999 'exampl':722,724 'exist':156 'expans':1430 'explicit':1647 'extra':302 'extract':178,191,204,225,235 'f':1036 'face':571,1468,1549 'fallback':773 'fals':1422 'familynam':1066 'fell':164 'file':125,148,158 'fix':1241,1395 'fixed-width':1394 'fixeds':1420 'flexibl':1414 'flip':1159,1231,1442 'flipsforrighttoleftlayoutdirect':1194,1612 'follow':1162 'forc':1206 'format':85,90,659,670,676,880,889,895,950,1360,1366,1387,1574,1645 'formatstyl':22,81,87,876,891,1101,1378,1571,1678 'formatstyle-locale-aware-format':86 'formatt':1368 'formatter.dateformat':1370 'foto':871,874 'found':230 'fr':977,992,1040,1097 'fractionlength':968 'frame':1409 'framework':448,550 'func':492 'gear':215 'gender/number':852 'german':603,1400,1524,1597 'givennam':1064 'grammar':837 'grammat':846 'greet':1333,1349 'guid':62,67,284,1684 'haben':607 'handl':528,682,1298,1576 'hard':883,1357 'hard-cod':882,1356 'hardcod':1573 'hebrew':1125 'hello':242,1336,1352 'hide':1515 'home':324 'horizont':1421 'hourminutesecond':1055 'hstack':1138,1247,1445,1457 'identifi':1181 'if/else':1584 'imag':1183,1191,1196,1607 'implicit':299,526 'includ':1603 'indic':1158,1190 'inflect':842,859 'info':424 'initi':334,357 'integ':699 'integr':1278 'intent':444,454,545,1615 'internation':11 'internet':389 'interpol':69,75,578,582,656,662,700,777,1341 'invis':246 'io':1,4,9,13,130,363,450,839,892 'ipad':808,827 'iphon':806,823 'ison':221 'item':229,729,732,734,739,746,752,755,757,1080 'items.formatted':1084 'januar':925 'januari':916,943 'japanes':611,649 'john':1065,1072,1076 'jp':930,1077 'json':146 'json-bas':145 'key':161,209,252,376,822,1630 'kilomet':1022 'kind':475 'label':212,316,396 'languag':855,1123,1331,1539,1606 'later':442 'layout':27,43,96,102,1107,1116,1120,1222,1251,1397,1415,1517,1585 'layoutdirect':1176,1220 'lead':1142,1226,1453,1461,1587 'left':94,100,1114,1237,1434,1449,1590,1659 'lefttoright':1221 'legaci':1273 'length':1662 'let':240,367,381,395,408,508,617,905,956,979,1003,1023,1048,1061,1079,1282,1296,1302,1332,1348,1367,1479,1495 'list':1045,1078,1085,1156 'liter':297 'lld':636,646,790,794 'lld件あります':652 'local':2,10,12,28,47,71,77,83,88,108,227,239,344,351,370,384,398,411,423,434,507,511,538,561,575,580,585,620,667,673,695,878,901,1179,1180,1294,1305,1323,1335,1351,1384,1478,1504,1543,1552,1558,1651,1664,1673 'locale-awar':82,877 'locale-chang':1672 'localiz':135 'localizedstringkey':205,285,291,310,326,338,525,1553 'localizedstringresourc':231,421,456,463,485,495,497,549,1489,1497,1619 'log':566 'logic':543 'logo':1201 'long':912,1071,1525,1595 'longer':1404 'lookup':311,529 'ltr':1207 'mac':810,833 'mainactor':1670 'manag':162 'mani':747 'manual':160,339,1167,1583 'mark':258 'market':38 'meaningless':1372 'measur':888,1001,1005,1011,1025,1031 'messag':496,556,602,627,648,784,792,796,1485,1502 'migrat':274 'mile':1016 'minimum':1530 'mirror':1119,1137,1186,1200,1610 'mistak':29,104,107,1263 'mistransl':39 'mm/dd/yyyy':1371 'mode':220 'model':535 'modern':19,345 'modul':403 'move':1152 'msg':241,382 'music':1204 'must':1639 'myview':1174 'mywidget':468 'nachrichten':610 'name':622,1060,1062,1069,1337,1353 'name.formatted':1068 'nativ':188,684 'navigationstack':1149 'navigationtitl':323 'need':261,304,430,576,1166,1608 'neue':609 'never':881 'new':601,626,647,1269,1624 'non':36 'non-english':35 'note':1205 'notif':446 'now.formatted':910,937 'nslocalizedstr':346,1267,1284,1621 'number':671,886,954,1212,1569 'number.precision':967 'offer':705 'offset':1257 'onboard':401 'onboarding.title':399 'one':730,761,789 'orang':1082,1089,1094 'order':232,464,1141,1328 'ordercoffeeint':458 'outsid':353,1473 'overrid':1536 'pad':1146,1448,1460 'paramet':295,524 'pass':328,422,432,487 'pattern':197,1054,1679 'percent':971 'persian':1127 'person':319,1059 'personnam':1044 'personnamecompon':1063 'phone':1211 'photo':858,864,867,1202 'place':233 'placehold':637,1347 'plain':236,360,572,1471 'plural':79,80,137,173,187,679,683,706,718,779,1575,1580 'pm':922 'posit':588,1261 'prefer':657 'preset':908 'preview':1173 'price':980 'price.formatted':983,993 'profil':317 'programmat':223 'progress':1189 'provid':477,478,663,1627 'pseudoloc':1509,1653 'put':1465 'read':1163 'refer':114,115,1102,1677 'references/formatstyle-locale.md':1109,1110,1680,1681 'references/string-catalogs.md':279,280,1685,1686 'reject':33 'reorder':593,641,1346 'replac':121,347 'requir':159,169,455,688,1130 'resolut':1492 'resolv':426,440,490,498,509,540,551,562 'respect':1250 'return':358,539 'revers':1140 'review':109,112,262,1544 'review-checklist':111 'right':92,98,1112,1238,1435,1591,1657 'right-to-left':91,1111,1656 'right-to-left-rtl-layout':97 'righttoleft':1177 'rtl':25,95,101,1106,1115,1122,1171,1233,1244,1444,1519,1528,1599,1609 'rtl-awar':24 'rule':138,1223 'safe':655 'safeti':665 'save':217,412,417 'scale':1640 'scaledmetr':1634 'scan':194 'scheme':1533 'score':668,669 'screen':1289,1312 'see':278,1108 'sendabl':1668 'servic':536 'set':213,1534 'setup':689 'ship':44 'shorten':914 'showalert':493,1484,1501 'shown':557 'side':1148 'sie':606 'singl':144,776 'six':767 'skill':5,6 'skip':1508 'someth':1481,1498 'source-dpearson2699' 'space':1637 'spacer':1446,1458 'spanish':869 'specif':804,1209 'specifi':660 'stale':265 'start':50,126 'state':184 'static':460 'staticconfigur':474 'store':32 'strategi':277 'string':17,20,52,56,59,64,68,72,74,78,116,119,122,136,154,157,174,179,226,237,245,255,271,281,296,329,343,352,361,369,383,397,410,435,510,532,537,541,560,573,577,581,586,619,630,666,672,680,691,696,710,785,799,813,1280,1293,1304,1324,1334,1340,1350,1469,1472,1503,1550,1557,1560,1578,1601,1665,1682 'string-catalogs-xcstr':55 'string-interpolation-in-localized-str':73 'string-types-decision-guid':63 'stringsdict':124,168,686 'struct':457,467 'style':909,1070,1104 'suppli':713,769 'support':186,780,801,854 'swap':1147 'swift':3,201,305,365,452,594,661,774,811,848,904,955,1002,1046,1169,1271,1300,1325,1342,1361,1379,1398,1416,1438,1455,1475,1493 'swiftui':202,286,288,332,355,521,527,947,1117,1134,1297,1316,1474,1555 'sync':167 'syntax':843 'system':447,547 'systemimag':214,318 'systemnam':1192 'tabl':392,400 'tap':824,828 'target':1605 'temp':1024 'temp.formatted':1030 'test':276,1170,1510,1511,1522,1593,1654 'text':206,294,313,380,523,618,781,805,856,948,1160,1214,1318,1385,1401,1407,1418,1447,1459,1566,1596 'time':501,554,913,1053 'timer':476,486 'timerview':481 'titl':368,415,462,494,512,1283,1286,1290,1303,1307,1313,1408,1419 'toggl':218 'track':182 'trail':1143,1154,1227,1454,1588 'translat':183,259,263,407,591,639,714,1344,1633 'trigger':778 'true':860,1195,1424,1613 'truncat':1516 'two':735 'type':21,60,65,282,517,519,654,664,1086,1643,1666 'type-saf':653 'ui':40,1592,1675 'um':927 'unifi':133 'unit':1008,1028 'unitlength.kilometers':1009 'unittemperature.celsius':1029 'unread':783,791,795 'unreadcount':782 'updat':1676 'urdu':1126 'us':915,942,963,975,988,991,1014,1034,1074,1364 'us-on':1363 'usag':1622 'usd':986 'use':16,325,348,427,515,727,737,743,749,759,765,841,890,1225,1236,1246,1255,1266,1292,1339,1377,1393,1413,1426,1433,1452,1488,1531,1551,1570,1586,1611,1618,1635,1646,1669 'user':504,559,570,899,1383,1467,1548,1564 'user-fac':569,1466,1547 'user-vis':1563 'valu':375,583,1006,1026 'var':461,470 'vari':817,1329 'variant':707,1581 'variat':141,798 'verbos':1275 'vertic':1423 'via':1577 'view':289,333,356,522,534,1129 'visibl':1565 'visual':151 'vs':807,809 'vstack':1248 'vstack/wrapping':1427 'welcom':207,210,314,371,596,621,643,1285,1288,1306,1309,1311,1319 'went':1482,1499 'wide':939,1013 'widget':445,466,469,546,1617 'widgetconfigur':473 'width':1012,1032,1396,1410 'willkommen':604 'without':425,489,1540 'word':1327 'work':192,303 'workflow':273 'wrong':1272,1326,1362,1399,1439,1476,1483,1500 'x':1258 'xcode':128,193,248,249,701,1532 'xcstring':54,58,118 'xml':171,687 'year':941,953,1390 'yet':491 'zero':725,1131 'さん':613,650 '件あります':616 '新しいメッセージが':614,651","prices":[{"id":"2c318726-3141-4192-8ae2-0fb9e04f671e","listingId":"e9b09a61-b84a-4c88-bebc-b1d17ff9cc9d","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:33:26.811Z"}],"sources":[{"listingId":"e9b09a61-b84a-4c88-bebc-b1d17ff9cc9d","source":"github","sourceId":"dpearson2699/swift-ios-skills/ios-localization","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/ios-localization","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:03.068Z","lastSeenAt":"2026-04-22T00:53:43.395Z"},{"listingId":"e9b09a61-b84a-4c88-bebc-b1d17ff9cc9d","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/ios-localization","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/ios-localization","isPrimary":true,"firstSeenAt":"2026-04-18T20:33:26.811Z","lastSeenAt":"2026-04-22T05:40:37.567Z"}],"details":{"listingId":"e9b09a61-b84a-4c88-bebc-b1d17ff9cc9d","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"ios-localization","source":"skills_sh","category":"swift-ios-skills","skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/ios-localization"},"updatedAt":"2026-04-22T05:40:37.567Z"}}