Skip to content

Instantly share code, notes, and snippets.

@71
Created September 13, 2025 07:20
Show Gist options
  • Select an option

  • Save 71/6283d525bd924672504bf5dfcde4dcc8 to your computer and use it in GitHub Desktop.

Select an option

Save 71/6283d525bd924672504bf5dfcde4dcc8 to your computer and use it in GitHub Desktop.
(Not tested)
// Raw translation of
// https://github.com/71/study-korean/blob/c4f3de22cd433c045458198956031f6edbb54f13/app/src/utils/korean.ts
/// A Korean syllable.
public struct KoreanSyllable: CustomStringConvertible {
public let initialJamo: UnicodeScalar
public let medialJamo: UnicodeScalar
public let finalJamo: UnicodeScalar?
/// Converts a Korean syllable such as 김 to its jamo ㄱㅣㅁ.
public init?(_ syllable: Character) {
guard let scalar = syllable.unicodeScalars.first, syllable.unicodeScalars.count == 1 else {
return nil
}
self.init(scalar)
}
/// Converts a Korean syllable such as 김 to its jamo ㄱㅣㅁ.
public init?(_ syllable: UnicodeScalar) {
guard syllable.isKoreanSyllable else { return nil }
let x = Int(syllable.value) - syllableBase
let initialIndex = x / 28 / 21
let medialIndex = (x / 28) % 21
let finalIndex = x % 28
initialJamo = initial[initialIndex]!
medialJamo = medial[medialIndex]!
finalJamo = finalIndex == 0 ? nil : final[finalIndex - 1]
}
/// The jamo making up the syllable.
public var description: String {
if let finalJamo {
"\(initialJamo)\(medialJamo)\(finalJamo)"
} else {
"\(initialJamo)\(medialJamo)"
}
}
}
extension Character {
/// Whether this character is a Korean syllable such as 김.
public var isKoreanSyllable: Bool {
guard let scalar = unicodeScalars.first, unicodeScalars.count == 1 else { return false }
return scalar.isKoreanSyllable
}
}
extension UnicodeScalar {
/// Whether this Unicode scalar is a Korean syllable such as 김.
public var isKoreanSyllable: Bool {
value >= 0xac00 && value <= 0xd7a3
}
}
/// First Unicode scalar representing a Korean syllable.
private let syllableBase = 0xac00
private let initial = "ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ".utf16.map { UnicodeScalar($0) }
private let medial = "ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ".utf16.map { UnicodeScalar($0) }
private let final = "ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅅㅆㅇㅈㅊㅋㅌㅍㅎ".utf16.map { UnicodeScalar($0) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment