{"id":"f3422d67-7167-4e98-a32c-9a3fb9a5d180","shortId":"e9PQWh","kind":"skill","title":"natural-language","tagline":"Tokenize, tag, and analyze natural language text using Apple's NaturalLanguage framework and translate between languages with the Translation framework. Use when adding language identification, sentiment analysis, named entity recognition, part-of-speech tagging, text embeddings,","description":"# NaturalLanguage + Translation\n\nAnalyze natural language text for tokenization, part-of-speech tagging, named\nentity recognition, sentiment analysis, language identification, and word/sentence\nembeddings. Translate text between languages with the Translation framework.\nTargets Swift 6.3 / iOS 26+.\n\n> This skill covers two related frameworks: **NaturalLanguage** (`NLTokenizer`, `NLTagger`, `NLEmbedding`) for on-device text analysis, and **Translation** (`TranslationSession`, `LanguageAvailability`) for language translation.\n\n## Contents\n\n- [Setup](#setup)\n- [Tokenization](#tokenization)\n- [Language Identification](#language-identification)\n- [Part-of-Speech Tagging](#part-of-speech-tagging)\n- [Named Entity Recognition](#named-entity-recognition)\n- [Sentiment Analysis](#sentiment-analysis)\n- [Text Embeddings](#text-embeddings)\n- [Translation](#translation)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Setup\n\nImport `NaturalLanguage` for text analysis and `Translation` for language\ntranslation. No special entitlements or capabilities are required for\nNaturalLanguage. Translation requires iOS 17.4+ / macOS 14.4+.\n\n```swift\nimport NaturalLanguage\nimport Translation\n```\n\nNaturalLanguage classes (`NLTokenizer`, `NLTagger`) are **not thread-safe**.\nUse each instance from one thread or dispatch queue at a time.\n\n## Tokenization\n\nSegment text into words, sentences, or paragraphs with `NLTokenizer`.\n\n```swift\nimport NaturalLanguage\n\nfunc tokenizeWords(in text: String) -> [String] {\n    let tokenizer = NLTokenizer(unit: .word)\n    tokenizer.string = text\n\n    let range = text.startIndex..<text.endIndex\n    return tokenizer.tokens(for: range).map { String(text[$0]) }\n}\n```\n\n### Token Units\n\n| Unit | Description |\n|---|---|\n| `.word` | Individual words |\n| `.sentence` | Sentences |\n| `.paragraph` | Paragraphs |\n| `.document` | Entire document |\n\n### Enumerating with Attributes\n\nUse `enumerateTokens(in:using:)` to detect numeric or emoji tokens.\n\n```swift\nlet tokenizer = NLTokenizer(unit: .word)\ntokenizer.string = text\n\ntokenizer.enumerateTokens(in: text.startIndex..<text.endIndex) { range, attributes in\n    if attributes.contains(.numeric) {\n        print(\"Number: \\(text[range])\")\n    }\n    return true // continue enumeration\n}\n```\n\n## Language Identification\n\nDetect the dominant language of a string with `NLLanguageRecognizer`.\n\n```swift\nfunc detectLanguage(for text: String) -> NLLanguage? {\n    NLLanguageRecognizer.dominantLanguage(for: text)\n}\n\n// Multiple hypotheses with confidence scores\nfunc languageHypotheses(for text: String, max: Int = 5) -> [NLLanguage: Double] {\n    let recognizer = NLLanguageRecognizer()\n    recognizer.processString(text)\n    return recognizer.languageHypotheses(withMaximum: max)\n}\n```\n\nConstrain the recognizer to expected languages for better accuracy on short text.\n\n```swift\nlet recognizer = NLLanguageRecognizer()\nrecognizer.languageConstraints = [.english, .french, .spanish]\nrecognizer.processString(text)\nlet detected = recognizer.dominantLanguage\n```\n\n## Part-of-Speech Tagging\n\nIdentify nouns, verbs, adjectives, and other lexical classes with `NLTagger`.\n\n```swift\nfunc tagPartsOfSpeech(in text: String) -> [(String, NLTag)] {\n    let tagger = NLTagger(tagSchemes: [.lexicalClass])\n    tagger.string = text\n\n    var results: [(String, NLTag)] = []\n    let range = text.startIndex..<text.endIndex\n    let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace]\n\n    tagger.enumerateTags(in: range, unit: .word, scheme: .lexicalClass, options: options) { tag, tokenRange in\n        if let tag {\n            results.append((String(text[tokenRange]), tag))\n        }\n        return true\n    }\n    return results\n}\n```\n\n### Common Tag Schemes\n\n| Scheme | Output |\n|---|---|\n| `.lexicalClass` | Part of speech (noun, verb, adjective) |\n| `.nameType` | Named entity type (person, place, organization) |\n| `.nameTypeOrLexicalClass` | Combined NER + POS |\n| `.lemma` | Base form of a word |\n| `.language` | Per-token language |\n| `.sentimentScore` | Sentiment polarity score |\n\n## Named Entity Recognition\n\nExtract people, places, and organizations.\n\n```swift\nfunc extractEntities(from text: String) -> [(String, NLTag)] {\n    let tagger = NLTagger(tagSchemes: [.nameType])\n    tagger.string = text\n\n    var entities: [(String, NLTag)] = []\n    let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace, .joinNames]\n\n    tagger.enumerateTags(\n        in: text.startIndex..<text.endIndex,\n        unit: .word,\n        scheme: .nameType,\n        options: options\n    ) { tag, tokenRange in\n        if let tag, tag != .other {\n            entities.append((String(text[tokenRange]), tag))\n        }\n        return true\n    }\n    return entities\n}\n// NLTag values: .personalName, .placeName, .organizationName\n```\n\n## Sentiment Analysis\n\nScore text sentiment from -1.0 (negative) to +1.0 (positive).\n\n```swift\nfunc sentimentScore(for text: String) -> Double? {\n    let tagger = NLTagger(tagSchemes: [.sentimentScore])\n    tagger.string = text\n\n    let (tag, _) = tagger.tag(\n        at: text.startIndex,\n        unit: .paragraph,\n        scheme: .sentimentScore\n    )\n    return tag.flatMap { Double($0.rawValue) }\n}\n```\n\n## Text Embeddings\n\nMeasure semantic similarity between words or sentences with `NLEmbedding`.\n\n```swift\nfunc wordSimilarity(_ word1: String, _ word2: String) -> Double? {\n    guard let embedding = NLEmbedding.wordEmbedding(for: .english) else { return nil }\n    return embedding.distance(between: word1, and: word2, distanceType: .cosine)\n}\n\nfunc findSimilarWords(to word: String, count: Int = 5) -> [(String, Double)] {\n    guard let embedding = NLEmbedding.wordEmbedding(for: .english) else { return [] }\n    return embedding.neighbors(for: word, maximumCount: count, distanceType: .cosine)\n}\n```\n\nSentence embeddings compare entire sentences.\n\n```swift\nfunc sentenceSimilarity(_ s1: String, _ s2: String) -> Double? {\n    guard let embedding = NLEmbedding.sentenceEmbedding(for: .english) else { return nil }\n    return embedding.distance(between: s1, and: s2, distanceType: .cosine)\n}\n```\n\n## Translation\n\n### System Translation Overlay\n\nShow the built-in translation UI with `.translationPresentation()`.\n\n```swift\nimport SwiftUI\nimport Translation\n\nstruct TranslatableView: View {\n    @State private var showTranslation = false\n    let text = \"Hello, how are you?\"\n\n    var body: some View {\n        Button { showTranslation = true } label: {\n            Text(text)\n        }\n        .buttonStyle(.plain)\n        .translationPresentation(\n            isPresented: $showTranslation,\n            text: text\n        )\n    }\n}\n```\n\n### Programmatic Translation\n\nUse `.translationTask()` for programmatic translations within a view context.\n\n```swift\nstruct TranslatingView: View {\n    @State private var translatedText = \"\"\n    @State private var configuration: TranslationSession.Configuration?\n\n    var body: some View {\n        VStack {\n            Text(translatedText)\n            Button(\"Translate\") {\n                configuration = .init(source: Locale.Language(identifier: \"en\"),\n                                      target: Locale.Language(identifier: \"es\"))\n            }\n        }\n        .translationTask(configuration) { session in\n            let response = try await session.translate(\"Hello, world!\")\n            translatedText = response.targetText\n        }\n    }\n}\n```\n\n### Batch Translation\n\nTranslate multiple strings in a single session.\n\n```swift\n.translationTask(configuration) { session in\n    let requests = texts.enumerated().map { index, text in\n        TranslationSession.Request(sourceText: text,\n                                    clientIdentifier: \"\\(index)\")\n    }\n    let responses = try await session.translations(from: requests)\n    for response in responses {\n        print(\"\\(response.sourceText) -> \\(response.targetText)\")\n    }\n}\n```\n\n### Checking Language Availability\n\n```swift\nlet availability = LanguageAvailability()\nlet status = await availability.status(\n    from: Locale.Language(identifier: \"en\"),\n    to: Locale.Language(identifier: \"ja\")\n)\nswitch status {\ncase .installed: break    // Ready to translate offline\ncase .supported: break    // Needs download\ncase .unsupported: break  // Language pair not available\n}\n```\n\n## Common Mistakes\n\n### DON'T: Share NLTagger/NLTokenizer across threads\n\nThese classes are not thread-safe and will produce incorrect results or crash.\n\n```swift\n// WRONG\nlet sharedTagger = NLTagger(tagSchemes: [.lexicalClass])\nDispatchQueue.concurrentPerform(iterations: 10) { _ in\n    sharedTagger.string = someText  // Data race\n}\n\n// CORRECT\nawait withTaskGroup(of: Void.self) { group in\n    for _ in 0..<10 {\n        group.addTask {\n            let tagger = NLTagger(tagSchemes: [.lexicalClass])\n            tagger.string = someText\n            // process...\n        }\n    }\n}\n```\n\n### DON'T: Confuse NaturalLanguage with Core ML\n\nNaturalLanguage provides built-in linguistic analysis. Use Core ML for custom\ntrained models. They complement each other via `NLModel`.\n\n```swift\n// WRONG: Trying to do NER with raw Core ML\nlet coreMLModel = try MLModel(contentsOf: modelURL)\n\n// CORRECT: Use NLTagger for built-in NER\nlet tagger = NLTagger(tagSchemes: [.nameType])\n\n// Or load a custom Core ML model via NLModel\nlet nlModel = try NLModel(mlModel: coreMLModel)\ntagger.setModels([nlModel], forTagScheme: .nameType)\n```\n\n### DON'T: Assume embeddings exist for all languages\n\nNot all languages have word or sentence embeddings available on device.\n\n```swift\n// WRONG: Force unwrap\nlet embedding = NLEmbedding.wordEmbedding(for: .japanese)!\n\n// CORRECT: Handle nil\nguard let embedding = NLEmbedding.wordEmbedding(for: .japanese) else {\n    // Embedding not available for this language\n    return\n}\n```\n\n### DON'T: Create a new tagger per token\n\nCreating and configuring a tagger is expensive. Reuse it for the same text.\n\n```swift\n// WRONG: New tagger per word\nfor word in words {\n    let tagger = NLTagger(tagSchemes: [.lexicalClass])\n    tagger.string = word\n}\n\n// CORRECT: Set string once, enumerate\nlet tagger = NLTagger(tagSchemes: [.lexicalClass])\ntagger.string = fullText\ntagger.enumerateTags(in: fullText.startIndex..<fullText.endIndex,\n                     unit: .word, scheme: .lexicalClass, options: []) { tag, range in\n    return true\n}\n```\n\n### DON'T: Ignore language hints for short text\n\nLanguage detection on short strings (under ~20 characters) is unreliable.\nSet constraints or hints to improve accuracy.\n\n```swift\n// WRONG: Detect language of a single word\nlet lang = NLLanguageRecognizer.dominantLanguage(for: \"chat\")  // French or English?\n\n// CORRECT: Provide context\nlet recognizer = NLLanguageRecognizer()\nrecognizer.languageHints = [.english: 0.8, .french: 0.2]\nrecognizer.processString(\"chat\")\n```\n\n## Review Checklist\n\n- [ ] `NLTokenizer` and `NLTagger` instances used from a single thread\n- [ ] Tagger created once per text, not per token\n- [ ] Language detection uses constraints/hints for short text\n- [ ] `NLEmbedding` availability checked before use (returns nil if unavailable)\n- [ ] Translation `LanguageAvailability` checked before attempting translation\n- [ ] `.translationTask()` used within a SwiftUI view hierarchy\n- [ ] Batch translation uses `clientIdentifier` to match responses to requests\n- [ ] Sentiment scores handled as optional (may return nil for unsupported languages)\n- [ ] `.joinNames` option used with NER to keep multi-word names together\n- [ ] Custom ML models loaded via `NLModel`, not raw Core ML\n\n## References\n\n- Extended patterns (custom models, contextual embeddings, gazetteers): [references/translation-patterns.md](references/translation-patterns.md)\n- [Natural Language framework](https://sosumi.ai/documentation/naturallanguage)\n- [NLTokenizer](https://sosumi.ai/documentation/naturallanguage/nltokenizer)\n- [NLTagger](https://sosumi.ai/documentation/naturallanguage/nltagger)\n- [NLEmbedding](https://sosumi.ai/documentation/naturallanguage/nlembedding)\n- [NLLanguageRecognizer](https://sosumi.ai/documentation/naturallanguage/nllanguagerecognizer)\n- [Translation framework](https://sosumi.ai/documentation/translation)\n- [TranslationSession](https://sosumi.ai/documentation/translation/translationsession)\n- [LanguageAvailability](https://sosumi.ai/documentation/translation/languageavailability)","tags":["natural","language","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills"],"capabilities":["skill","source-dpearson2699","skill-natural-language","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/natural-language","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (12,404 chars)","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-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:42.912Z","embedding":null,"createdAt":"2026-04-18T20:34:33.972Z","updatedAt":"2026-05-18T18:53:42.912Z","lastSeenAt":"2026-05-18T18:53:42.912Z","tsv":"'+1.0':543 '-1.0':540 '/documentation/naturallanguage)':1249 '/documentation/naturallanguage/nlembedding)':1261 '/documentation/naturallanguage/nllanguagerecognizer)':1265 '/documentation/naturallanguage/nltagger)':1257 '/documentation/naturallanguage/nltokenizer)':1253 '/documentation/translation)':1270 '/documentation/translation/languageavailability)':1278 '/documentation/translation/translationsession)':1274 '0':240,895 '0.2':1141 '0.8':1139 '0.rawvalue':571 '10':880,896 '14.4':176 '17.4':174 '20':1104 '26':76 '5':327,615 '6.3':74 'accuraci':347,1114 'across':855 'ad':26 'adject':372,442 'analysi':30,58,92,128,131,156,535,919 'analyz':7,43 'appl':12 'assum':983 'attempt':1183 'attribut':257,281 'attributes.contains':284 'avail':811,814,848,997,1021,1171 'availability.status':819 'await':763,798,818,887 'base':455 'batch':769,1192 'better':346 'bodi':697,738 'break':832,839,844 'built':671,916,954 'built-in':670,915,953 'button':700,744 'buttonstyl':706 'capabl':166 'case':830,837,842 'charact':1105 'chat':1127,1143 'check':809,1172,1181 'checklist':145,148,1145 'class':183,376,858 'clientidentifi':793,1195 'combin':451 'common':139,142,431,849 'common-mistak':141 'compar':636 'complement':928 'confid':318 'configur':735,746,757,780,1036 'confus':908 'constrain':339 'constraint':1109 'constraints/hints':1166 'content':100 'contentsof':947 'context':723,1133 'contextu':1239 'continu':292 'core':911,921,941,966,1232 'coremlmodel':944,976 'correct':886,949,1009,1064,1131 'cosin':607,633,663 'count':613,631 'cover':79 'crash':870 'creat':1028,1034,1156 'custom':924,965,1224,1237 'data':884 'descript':244 'detect':263,296,362,1099,1117,1164 'detectlanguag':307 'devic':90,999 'dispatch':198 'dispatchqueue.concurrentperform':878 'distancetyp':606,632,662 'document':252,254 'domin':298 'doubl':329,551,570,590,617,646 'download':841 'els':597,624,653,1018 'embed':40,63,133,136,573,593,620,635,649,984,996,1005,1014,1019,1240 'embedding.distance':601,657 'embedding.neighbors':627 'emoji':266 'en':751,823 'english':356,596,623,652,1130,1138 'entir':253,637 'entiti':32,55,121,125,445,470,493,528 'entities.append':520 'entitl':164 'enumer':255,293,1068 'enumeratetoken':259 'es':755 'exist':985 'expect':343 'expens':1040 'extend':1235 'extract':472 'extractent':479 'fals':689 'findsimilarword':609 'forc':1002 'form':456 'fortagschem':979 'framework':15,23,71,82,1246,1267 'french':357,1128,1140 'fulltext':1075 'fulltext.endindex':1079 'fulltext.startindex':1078 'func':216,306,320,380,478,546,584,608,640 'gazett':1241 'group':891 'group.addtask':897 'guard':591,618,647,1012 'handl':1010,1203 'hello':692,765 'hierarchi':1191 'hint':1094,1111 'hypothes':316 'identif':28,60,106,109,295 'identifi':369,750,754,822,826 'ignor':1092 'import':152,178,180,214,678,680 'improv':1113 'incorrect':867 'index':787,794 'individu':246 'init':747 'instal':831 'instanc':193,1149 'int':326,614 'io':75,173 'ispres':709 'iter':879 'ja':827 'japanes':1008,1017 'joinnam':501,1212 'keep':1218 'label':703 'lang':1124 'languag':3,9,19,27,45,59,67,98,105,108,160,294,299,344,460,464,810,845,988,991,1024,1093,1098,1118,1163,1211,1245 'language-identif':107 'languageavail':96,815,1180,1275 'languagehypothes':321 'lemma':454 'let':222,229,269,330,352,361,387,398,402,420,485,496,516,552,559,592,619,648,690,760,783,795,813,816,873,898,943,957,971,1004,1013,1057,1069,1123,1134 'lexic':375 'lexicalclass':391,413,436,877,902,1061,1073,1083 'linguist':918 'load':963,1227 'locale.language':749,753,821,825 'maco':175 'map':237,786 'match':1197 'max':325,338 'maximumcount':630 'may':1206 'measur':574 'mistak':140,143,850 'ml':912,922,942,967,1225,1233 'mlmodel':946,975 'model':926,968,1226,1238 'modelurl':948 'multi':1220 'multi-word':1219 'multipl':315,772 'name':31,54,120,124,444,469,1222 'named-entity-recognit':123 'nametyp':443,489,509,961,980 'nametypeorlexicalclass':450 'natur':2,8,44,1244 'natural-languag':1 'naturallanguag':14,41,83,153,170,179,182,215,909,913 'need':840 'negat':541 'ner':452,938,956,1216 'new':1030,1049 'nil':599,655,1011,1176,1208 'nlembed':86,582,1170,1258 'nlembedding.sentenceembedding':650 'nlembedding.wordembedding':594,621,1006,1015 'nllanguag':311,328 'nllanguagerecogn':304,332,354,1136,1262 'nllanguagerecognizer.dominantlanguage':312,1125 'nlmodel':932,970,972,974,978,1229 'nltag':386,397,484,495,529 'nltagger':85,185,378,389,487,554,875,900,951,959,1059,1071,1148,1254 'nltagger.options':404,498 'nltagger/nltokenizer':854 'nltoken':84,184,212,224,271,1146,1250 'noun':370,440 'number':287 'numer':264,285 'offlin':836 'omitpunctu':405,499 'omitwhitespac':406,500 'on-devic':88 'one':195 'option':403,414,415,497,510,511,1084,1205,1213 'organ':449,476 'organizationnam':533 'output':435 'overlay':667 'pair':846 'paragraph':210,250,251,565 'part':35,50,111,116,365,437 'part-of-speech':34,49,110,364 'part-of-speech-tag':115 'pattern':1236 'peopl':473 'per':462,1032,1051,1158,1161 'per-token':461 'person':447 'personalnam':531 'place':448,474 'placenam':532 'plain':707 'polar':467 'pos':453 'posit':544 'print':286,806 'privat':686,729,733 'process':905 'produc':866 'programmat':713,718 'provid':914,1132 'queue':199 'race':885 'rang':230,236,280,289,399,409,1086 'raw':940,1231 'readi':833 'recogn':331,341,353,1135 'recognit':33,56,122,126,471 'recognizer.dominantlanguage':363 'recognizer.languageconstraints':355 'recognizer.languagehints':1137 'recognizer.languagehypotheses':336 'recognizer.processstring':333,359,1142 'refer':149,150,1234 'references/translation-patterns.md':1242,1243 'relat':81 'request':784,801,1200 'requir':168,172 'respons':761,796,803,805,1198 'response.sourcetext':807 'response.targettext':768,808 'result':395,430,868 'results.append':422 'return':233,290,335,427,429,525,527,568,598,600,625,626,654,656,1025,1088,1175,1207 'reus':1041 'review':144,147,1144 'review-checklist':146 's1':642,659 's2':644,661 'safe':190,863 'scheme':412,433,434,508,566,1082 'score':319,468,536,1202 'segment':204 'semant':575 'sentenc':208,248,249,580,634,638,995 'sentencesimilar':641 'sentiment':29,57,127,130,466,534,538,1201 'sentiment-analysi':129 'sentimentscor':465,547,556,567 'session':758,777,781 'session.translate':764 'session.translations':799 'set':1065,1108 'setup':101,102,151 'share':853 'sharedtagg':874 'sharedtagger.string':882 'short':349,1096,1101,1168 'show':668 'showtransl':688,701,710 'similar':576 'singl':776,1121,1153 'skill':78 'skill-natural-language' 'sometext':883,904 'sosumi.ai':1248,1252,1256,1260,1264,1269,1273,1277 'sosumi.ai/documentation/naturallanguage)':1247 'sosumi.ai/documentation/naturallanguage/nlembedding)':1259 'sosumi.ai/documentation/naturallanguage/nllanguagerecognizer)':1263 'sosumi.ai/documentation/naturallanguage/nltagger)':1255 'sosumi.ai/documentation/naturallanguage/nltokenizer)':1251 'sosumi.ai/documentation/translation)':1268 'sosumi.ai/documentation/translation/languageavailability)':1276 'sosumi.ai/documentation/translation/translationsession)':1272 'sourc':748 'source-dpearson2699' 'sourcetext':791 'spanish':358 'special':163 'speech':37,52,113,118,367,439 'state':685,728,732 'status':817,829 'string':220,221,238,302,310,324,384,385,396,423,482,483,494,521,550,587,589,612,616,643,645,773,1066,1102 'struct':682,725 'support':838 'swift':73,177,213,268,305,351,379,477,545,583,639,677,724,778,812,871,933,1000,1047,1115 'swiftui':679,1189 'switch':828 'system':665 'tag':5,38,53,114,119,368,416,421,426,432,512,517,518,524,560,1085 'tag.flatmap':569 'tagger':388,486,553,899,958,1031,1038,1050,1058,1070,1155 'tagger.enumeratetags':407,502,1076 'tagger.setmodels':977 'tagger.string':392,490,557,903,1062,1074 'tagger.tag':561 'tagpartsofspeech':381 'tagschem':390,488,555,876,901,960,1060,1072 'target':72,752 'text':10,39,46,65,91,132,135,155,205,219,228,239,275,288,309,314,323,334,350,360,383,393,424,481,491,522,537,549,558,572,691,704,705,711,712,742,788,792,1046,1097,1159,1169 'text-embed':134 'text.endindex':232,279,401,505 'text.startindex':231,278,400,504,563 'texts.enumerated':785 'thread':189,196,856,862,1154 'thread-saf':188,861 'time':202 'togeth':1223 'token':4,48,103,104,203,223,241,267,270,463,1033,1162 'tokenizer.enumeratetokens':276 'tokenizer.string':227,274 'tokenizer.tokens':234 'tokenizeword':217 'tokenrang':417,425,513,523 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'train':925 'translat':17,22,42,64,70,94,99,137,138,158,161,171,181,664,666,673,681,714,719,745,770,771,835,1179,1184,1193,1266 'translatableview':683 'translatedtext':731,743,767 'translatingview':726 'translationpresent':676,708 'translationsess':95,1271 'translationsession.configuration':736 'translationsession.request':790 'translationtask':716,756,779,1185 'tri':762,797,935,945,973 'true':291,428,526,702,1089 'two':80 'type':446 'ui':674 'unavail':1178 'unit':225,242,243,272,410,506,564,1080 'unreli':1107 'unsupport':843,1210 'unwrap':1003 'use':11,24,191,258,261,715,920,950,1150,1165,1174,1186,1194,1214 'valu':530 'var':394,492,687,696,730,734,737 'verb':371,441 'via':931,969,1228 'view':684,699,722,727,740,1190 'void.self':890 'vstack':741 'within':720,1187 'withmaximum':337 'withtaskgroup':888 'word':207,226,245,247,273,411,459,507,578,611,629,993,1052,1054,1056,1063,1081,1122,1221 'word/sentence':62 'word1':586,603 'word2':588,605 'wordsimilar':585 'world':766 'wrong':872,934,1001,1048,1116","prices":[{"id":"1982b877-4c37-4790-b803-43cf5cfb5462","listingId":"f3422d67-7167-4e98-a32c-9a3fb9a5d180","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:34:33.972Z"}],"sources":[{"listingId":"f3422d67-7167-4e98-a32c-9a3fb9a5d180","source":"github","sourceId":"dpearson2699/swift-ios-skills/natural-language","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/natural-language","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:07.471Z","lastSeenAt":"2026-05-18T18:53:42.912Z"},{"listingId":"f3422d67-7167-4e98-a32c-9a3fb9a5d180","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/natural-language","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/natural-language","isPrimary":true,"firstSeenAt":"2026-04-18T20:34:33.972Z","lastSeenAt":"2026-05-07T22:40:33.856Z"}],"details":{"listingId":"f3422d67-7167-4e98-a32c-9a3fb9a5d180","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"natural-language","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"4e7663f893189650a905880269397e5f9a29146e","skill_md_path":"skills/natural-language/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/natural-language"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"natural-language","description":"Tokenize, tag, and analyze natural language text using Apple's NaturalLanguage framework and translate between languages with the Translation framework. Use when adding language identification, sentiment analysis, named entity recognition, part-of-speech tagging, text embeddings, or in-app translation to iOS/macOS/visionOS apps."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/natural-language"},"updatedAt":"2026-05-18T18:53:42.912Z"}}