This project builds upon the now-archived PanglongKeyboard-iOS, aiming to make customizing the Shan language keyboard layout for iOS much easier—until native support by Apple becomes available.
This project aims to replicate the native iOS keyboard layout experience for the Shan language. It prioritizes simplicity:
- No fancy themes (though they could be added later).
- No cluttered settings buttons (which can also be added later).
- No privacy concerns — no open access requested, no network usage — just type!
A multi-layered autocomplete system provides intelligent word suggestions using a 3-slot priority system:
- Personal suggestions — learned words based on user typing history
- Contextual suggestions — context-aware next-word predictions powered by a pre-trained n-gram (trigram/bigram/unigram) language model
- Dictionary suggestions — frequency-sorted word matches from a curated Shan word list
With fallbacks to:
- Syllable suggestions — when primary slots are unfilled
- Spell correction — edit-distance-based corrections when input is invalid
- Character predictions — next-character suggestions based on Shan grammar rules
All suggestions are validated through ShanGrammarRules to ensure grammatical correctness before display.
A centralized grammar validation engine (ShanGrammarRules.swift) that defines:
- Consonants, vowels, medials, tone marks, and final consonant rules
- Valid consonant cluster combinations (hor/lape clusters)
- Pair-level character validation (
canFollow) - Full string grammatical validation (
isGrammaticallyValid) - Word boundary detection and next-character prediction
A dictionary-based word segmentation engine using dynamic programming for optimal tokenization, with NSCache-based result caching for performance.
This project is based on KeyboardKit, which does not yet support the Shan locale. To address this, I created a custom fork: KeyboardKit-ShanPatched. This fork adds locale information for Shan.
Since the free version of KeyboardKit doesn't support an emoji keyboard, I integrated ISEmojiView, a SwiftUI package, to serve as a wrapper for emoji input.
ShanKeyboard-iOS/
├── ShanKeyboard/ # Host app (SwiftUI)
│ ├── ShanKeyboard.swift # App entry point
│ ├── HomeScreen.swift # Main screen
│ ├── AddKeyboardScreen.swift # Setup instructions
│ ├── LayoutSettings.swift # Layout configuration
│ ├── AboutScreen.swift # About page
│ └── Fonts/ # Custom fonts (Shan.ttf)
│
├── Shan/ # Keyboard extension target
│ ├── KeyboardViewController.swift # Main keyboard view controller
│ ├── Controller/
│ │ └── ShanKeyboardInputViewController.swift
│ ├── Action/
│ │ └── ActionHandlerProvider.swift
│ ├── Behavior/
│ │ └── BehaviorProvider.swift
│ ├── Callout/
│ │ └── CalloutProvider.swift
│ ├── Layout/ # Keyboard layout (iPhone & iPad)
│ │ ├── LayoutServiceProvider.swift
│ │ ├── CustomIPhoneService.swift
│ │ ├── CustomIPadService.swift
│ │ ├── KeyboardInputSet.swift
│ │ └── Toolbar.swift
│ ├── Style/
│ │ └── StyleProvider.swift
│ └── Autocomplete/ # Autocomplete pipeline
│ ├── AutocompleteServiceProvider.swift # Main orchestrator
│ ├── AutocompleteDataManager.swift # User learning & context
│ ├── LanguageService.swift # Shan language parsing
│ ├── ShanGrammarRules.swift # Grammar validation
│ ├── SharedResources.swift # Singleton resource manager
│ ├── Tokenizer/
│ │ └── Tokenizer.swift # Word segmentation
│ ├── Suggestion/ # Suggestion services
│ │ ├── WordCompletionService.swift
│ │ ├── ContextualSuggestionService.swift
│ │ ├── DictionaryService.swift
│ │ ├── NGramService.swift
│ │ ├── SpellCorrectionService.swift
│ │ ├── CharacterPredictionService.swift
│ │ └── TrieNode.swift
│ └── Resource/ # Data files
│ ├── dictionary.txt
│ ├── filtered_frequency_data.json
│ ├── filtered_frequency_data.plist
│ ├── bigram_data.json
│ └── bigram_data.plist
│
├── Scripts/
│ └── convert_resources.sh # JSON → binary plist converter
│
├── ShanKeyboardTests/ # Unit tests
└── ShanKeyboardUITests/ # UI tests
- Xcode (latest stable version)
- iOS Simulator or physical device
# Build the keyboard extension
xcodebuild -scheme Shan -destination 'platform=iOS Simulator,name=iPhone 17 Pro'
# Build the host app
xcodebuild -scheme ShanKeyboard -destination 'platform=iOS Simulator,name=iPhone 17 Pro'Or open ShanKeyboard.xcodeproj in Xcode and select the Shan scheme to build the keyboard extension, or the ShanKeyboard scheme for the host app.
A pre-build script (Scripts/convert_resources.sh) automatically converts JSON resource files to binary plist format for faster runtime parsing. This runs before the "Copy Bundle Resources" build phase. If you update filtered_frequency_data.json or bigram_data.json, the binary plist files will be regenerated on the next build.
- Build and run the ShanKeyboard host app on a simulator or device.
- Go to Settings → General → Keyboard → Keyboards → Add New Keyboard.
- Select ShanKeyboard — Shan.
- Switch to the Shan keyboard in any text input field.
- Word list & dictionary: sourced from the ShanNLP project
- Word/syllable frequency data: analyzed from the shannews.org domain dataset
- N-gram language model: pre-trained bigram/trigram model analyzed from the shannews.org domain dataset
- The keyboard does not request open access (
RequestsOpenAccess: false) - No network requests are made
- Sensitive text detection is enabled for passwords and credit card fields
- Privacy manifests (
PrivacyInfo.xcprivacy) are included in both targets
The app is available on the App Store. Feel free to also use this project as a foundation for developing your own keyboard apps.
Feel free to reach out if you have questions or if you want to contribute in any way:
- Website: noernova.com
- Twitter: @noer_nova
- E-mail: norhsangpha@gmail.com
MIT






