packages feed

seonbi-0.3.0: test/Text/Seonbi/HanjaSpec.hs

{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Seonbi.HanjaSpec (spec) where

import Test.Hspec

import Text.Seonbi.Hanja
import Text.Seonbi.Html

inputFixture :: [HtmlEntity]
inputFixture =
    [ HtmlStartTag [] H1 ""
    , HtmlText [H1] "異蹟"
    , HtmlEndTag [] H1
    , HtmlStartTag [] P ""
    , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "黃昏이 湖水우로 걸어 오듯이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "내사 이 湖水가로"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "부르는 이 없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "불리워 온것은"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "참말 異蹟이외다."
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "오늘 따라"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "戀情, 自惚, 猜忌, 이것들이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "자꼬 金메달처럼 만져지는구려"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "하나, 내 모든 것을 餘念없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "물결에 써서 보내려니"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "당신은 湖面으로 나를 불러 내소서."
    , HtmlEndTag [] P
    ]

outputFixture :: [HtmlEntity]
outputFixture =
    [ HtmlStartTag [] H1 ""
    , HtmlText [H1] "리적"
    , HtmlEndTag [] H1
    , HtmlStartTag [] P ""
    , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "황혼이 호수우로 걸어 오듯이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "내사 이 호수가로"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "부르는 이 없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "불리워 온것은"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "참말 리적이외다."
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "오늘 따라"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "련정, 자홀, 시기, 이것들이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "자꼬 금메달처럼 만져지는구려"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "하나, 내 모든 것을 여념없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "물결에 써서 보내려니"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "당신은 호면으로 나를 불러 내소서."
    , HtmlEndTag [] P
    ]

outputWithInitialSoundLawFixture :: [HtmlEntity]
outputWithInitialSoundLawFixture =
    [ HtmlStartTag [] H1 ""
    , HtmlText [H1] "이적"
    , HtmlEndTag [] H1
    , HtmlStartTag [] P ""
    , HtmlText [P] "발에 터분한 것을 다 빼어 바리고"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "황혼이 호수우로 걸어 오듯이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "나도 삽분삽분 걸어 보리이까?"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "내사 이 호수가로"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "부르는 이 없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "불리워 온것은"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "참말 이적이외다."
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "오늘 따라"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "연정, 자홀, 시기, 이것들이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "자꼬 금메달처럼 만져지는구려"
    , HtmlEndTag [] P
    , HtmlStartTag [] P ""
    , HtmlText [P] "하나, 내 모든 것을 여념없이"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "물결에 써서 보내려니"
    , HtmlStartTag [P] BR "", HtmlEndTag [P] BR
    , HtmlText [P] "당신은 호면으로 나를 불러 내소서."
    , HtmlEndTag [] P
    ]

spec :: Spec
spec = do
    describe "phoneticizeHanjaChar" $ do
        it "returns the input as is if not a Hanja character" $ do
            phoneticizeHanjaChar 'A' `shouldBe` 'A'
            phoneticizeHanjaChar '가' `shouldBe` '가'
        it "returns the most frequent way to read" $ do
            phoneticizeHanjaChar '金' `shouldBe` '금'
            phoneticizeHanjaChar '北' `shouldBe` '북'
        it "does not follow Initial Sound Law" $ do
            phoneticizeHanjaChar '六' `shouldBe` '륙'
            phoneticizeHanjaChar '禮' `shouldBe` '례'
    describe "phoneticizeHanjaWord" $ do
        it "returns the input as is if there are no hanja at all" $ do
            phoneticizeHanjaWord "foo" `shouldBe` "foo"
            phoneticizeHanjaWord "테스트" `shouldBe` "테스트"
        it "transforms hanja chars into the corresponding hangul readings" $ do
            phoneticizeHanjaWord "漢字" `shouldBe` "한자"
            phoneticizeHanjaWord "言文" `shouldBe` "언문"
            phoneticizeHanjaWord "餘念" `shouldBe` "여념"
            phoneticizeHanjaWord "來日" `shouldBe` "래일"
            phoneticizeHanjaWord "未來" `shouldBe` "미래"
            phoneticizeHanjaWord "良質" `shouldBe` "량질"
            phoneticizeHanjaWord "力量" `shouldBe` "력량"
    describe "phoneticizeHanjaWordWithInitialSoundLaw" $ do
        let phone = phoneticizeHanjaWordWithInitialSoundLaw
        it "returns the input as is if there are no hanja at all" $ do
            phone "foo" `shouldBe` "foo"
            phone "테스트" `shouldBe` "테스트"
        it "transforms hanja chars into the corresponding Hangul readings" $ do
            phone "漢字" `shouldBe` "한자"
            phone "言文" `shouldBe` "언문"
            phone "餘念" `shouldBe` "여념"
            phone "未來" `shouldBe` "미래"
            phone "法律" `shouldBe` "법률"
            phone "一列" `shouldBe` "일렬"
        it "converts the first letter according to Initial Sound Law" $ do
            phone "來日" `shouldBe` "내일"
            phone "良質" `shouldBe` "양질"
            phone "力量" `shouldBe` "역량"
        it ("converts a letter followed by no batchim or nieun (N) according "
            ++ "to Initial Sound Law") $ do
            phone "羅列" `shouldBe` "나열"
            phone "序列" `shouldBe` "서열"
            phone "義烈" `shouldBe` "의열"
            phone "規律" `shouldBe` "규율"
            phone "煨栗" `shouldBe` "외율"
            phone "自律" `shouldBe` "자율"
            phone "卑劣" `shouldBe` "비열"
            phone "優劣" `shouldBe` "우열"
            phone "熾烈" `shouldBe` "치열"
            phone "比率" `shouldBe` "비율"
            phone "利率" `shouldBe` "이율"
            phone "棗栗" `shouldBe` "조율"
            phone "分裂" `shouldBe` "분열"
            phone "前列" `shouldBe` "전열"
            phone "百分率" `shouldBe` "백분율"
            phone "韻律" `shouldBe` "운율"
            phone "煥率" `shouldBe` "환율"
            phone "分列" `shouldBe` "분열"
            phone "先烈" `shouldBe` "선열"
            phone "賤劣" `shouldBe` "천열"
            phone "旋律" `shouldBe` "선율"
            phone "戰慄" `shouldBe` "전율"
        it "converts all hanja digits according to Initial Sound Law" $ do
            phone "千九百八十六年" `shouldBe` "천구백팔십육년"
            phone "第六共和國" `shouldBe` "제육공화국"
            phone "拾萬圓" `shouldBe` "십만원"
            phone "參佰拾圓" `shouldBe` "삼백십원"
            phone "仟參佰圓" `shouldBe` "천삼백원"
    describe "withDictionary" $ do
        let dict =
                [ ("標識", "표지")
                , ("毛澤東", "마오쩌둥")
                , ("交通", "교통")
                ]
        let phone = withDictionary dict phoneticizeHanjaWordWithInitialSoundLaw
        it "replaces Sino-Korean words with hangul letters in a dictionary" $ do
            phone "標識" `shouldBe` "표지"
            phone "毛澤東" `shouldBe` "마오쩌둥"
            phone "交通標識" `shouldBe` "교통표지"
        it "uses a fallback phoneticizer for unknown morphemes" $
            phone "知識" `shouldBe` "지식"
        it "uses a fallback phoneticizer for unknown prefixes" $
            phone "安全標識" `shouldBe` "안전표지"
        it "uses a fallback phoneticizer for unknown suffixes" $ do
            phone "毛澤東語錄" `shouldBe` "마오쩌둥어록"
            phone "毛澤東理論" `shouldBe` "마오쩌둥이론"
    describe "phoneticizeHanja" $ do
        specify "without initial sound law" $ do
            let conf = def { phoneticizer = phoneticizeHanjaWord }
            normalizeText (phoneticizeHanja conf inputFixture)
                `shouldBe` normalizeText outputFixture
        specify "with initial sound law" $ do
            let conf = def
                    { phoneticizer = phoneticizeHanjaWordWithInitialSoundLaw
                    }
            let phone = normalizeText . phoneticizeHanja conf
            phone inputFixture `shouldBe`
                normalizeText outputWithInitialSoundLawFixture
            phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`
                [HtmlText [] "1996년 그들이 지구를 지배했을 때"]
        specify "with hanjaInParentheses renderer" $ do
            let conf = def { wordRenderer = hanjaInParentheses }
            let phone = normalizeText . phoneticizeHanja conf
            phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`
                [HtmlText [] "1996년(年) 그들이 지구(地球)를 지배(支配)했을 때"]
        specify "with hanjaInRuby renderer" $ do
            let conf = def { wordRenderer = hanjaInRuby }
            let phone = normalizeText . phoneticizeHanja conf
            phone [HtmlText [] "1996年 그들이 地球를 支配했을 때"] `shouldBe`
                [ HtmlText [] "1996"
                , HtmlStartTag [] Ruby ""
                , HtmlText [Ruby] "年"
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] "("
                , HtmlEndTag [Ruby] RP
                , HtmlStartTag [Ruby] RT ""
                , HtmlText [Ruby, RT] "년"
                , HtmlEndTag [Ruby] RT
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] ")"
                , HtmlEndTag [Ruby] RP
                , HtmlEndTag [] Ruby
                , HtmlText [] " 그들이 "
                , HtmlStartTag [] Ruby ""
                , HtmlText [Ruby] "地球"
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] "("
                , HtmlEndTag [Ruby] RP
                , HtmlStartTag [Ruby] RT ""
                , HtmlText [Ruby, RT] "지구"
                , HtmlEndTag [Ruby] RT
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] ")"
                , HtmlEndTag [Ruby] RP
                , HtmlEndTag [] Ruby
                , HtmlText [] "를 "
                , HtmlStartTag [] Ruby ""
                , HtmlText [Ruby] "支配"
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] "("
                , HtmlEndTag [Ruby] RP
                , HtmlStartTag [Ruby] RT ""
                , HtmlText [Ruby, RT] "지배"
                , HtmlEndTag [Ruby] RT
                , HtmlStartTag [Ruby] RP ""
                , HtmlText [Ruby, RP] ")"
                , HtmlEndTag [Ruby] RP
                , HtmlEndTag [] Ruby
                , HtmlText [] "했을 때"
                ]
        it "disambiguate homophones" $ do
            let conf = def
                    { wordRenderer = hangulOnly
                    , homophoneRenderer = hanjaInParentheses
                    }
            let phone = normalizeText . phoneticizeHanja conf
            let input =
                    [ HtmlStartTag [] P ""
                    , HtmlText [P] "同音 異義語 例: 連霸와 連敗"
                    , HtmlEndTag [] P
                    ]
            phone input `shouldBe` normalizeText
                [ HtmlStartTag [] P ""
                , HtmlText [P] "동음 이의어 예: 연패(連霸)와 연패(連敗)"
                , HtmlEndTag [] P
                ]
        it "does not transform numeral-only words" $ do
            let conf = def { wordRenderer = hanjaInParentheses }
            let phone = normalizeText . phoneticizeHanja conf
            phone [HtmlText [] "4·19革命"] `shouldBe`
                [HtmlText [] "4·19혁명(革命)"]
            phone [HtmlText [] "1987年10月29日"] `shouldBe`
                [HtmlText [] "1987년(年)10월(月)29일(日)"]
        it "transforms hanja characters in HTML entities" $ do
            let phone = normalizeText . phoneticizeHanja def
            phone [HtmlText [] "<1996年 그들이 地球를 支配했을 때>"]
                `shouldBe`
                    [HtmlText [] "<1996년 그들이 지구를 지배했을 때>"]
        it "transforms nothing in preserved tags" $ do
            let phone = normalizeText . phoneticizeHanja def
            phone [HtmlText [Pre] "1996年 그들이 地球를 支配했을 때"] `shouldBe`
                [HtmlText [Pre] "1996年 그들이 地球를 支配했을 때"]
        it "transforms nothing in non-Korean elements" $ do
            let phone = normalizeText . phoneticizeHanja def
            let input =
                    [ HtmlStartTag [] P ""
                    , HtmlText [P] "2004年 開封한 日本 映畫 "
                    , HtmlStartTag [P] Span "lang=\"ja\""
                    , HtmlText [P, Span] "誰も知らない"
                    , HtmlEndTag [P] Span
                    , HtmlText [P] "는 이듬해 韓國에서도 "
                    , HtmlStartTag [P] Span "lang=ko-Hang"
                    , HtmlText [P, Span] "아무도 모른다"
                    , HtmlEndTag [P] Span
                    , HtmlText [P] "라는 題目으로 開封했다."
                    ]
            let output =
                    [ HtmlStartTag [] P ""
                    , HtmlText [P] "2004년 개봉한 일본 영화 "
                    , HtmlStartTag [P] Span "lang=\"ja\""
                    , HtmlText [P, Span] "誰も知らない"
                    , HtmlEndTag [P] Span
                    , HtmlText [P] "는 이듬해 한국에서도 "
                    , HtmlStartTag [P] Span "lang=ko-Hang"
                    , HtmlText [P, Span] "아무도 모른다"
                    , HtmlEndTag [P] Span
                    , HtmlText [P] "라는 제목으로 개봉했다."
                    ]
            phone input `shouldBe` output
    describe "convertInitialSoundLaw" $ do
        specify "녀, 뇨, 뉴, 니 should be 여, 요, 유, 이" $ do
            convertInitialSoundLaw '녀' `shouldBe` '여'
            convertInitialSoundLaw '뉴' `shouldBe` '유'
            convertInitialSoundLaw '년' `shouldBe` '연'
            convertInitialSoundLaw '니' `shouldBe` '이'
            convertInitialSoundLaw '뇨' `shouldBe` '요'
            convertInitialSoundLaw '닉' `shouldBe` '익'
        specify "랴, 려, 례, 료, 류, 리 should be 야, 여, 예, 요, 유, 이" $ do
            convertInitialSoundLaw '량' `shouldBe` '양'
            convertInitialSoundLaw '룡' `shouldBe` '용'
            convertInitialSoundLaw '력' `shouldBe` '역'
            convertInitialSoundLaw '류' `shouldBe` '유'
            convertInitialSoundLaw '례' `shouldBe` '예'
            convertInitialSoundLaw '림' `shouldBe` '임'
        specify "라, 래, 로, 뢰, 루, 르 should be 나, 내, 노, 뇌, 누, 느" $ do
            convertInitialSoundLaw '락' `shouldBe` '낙'
            convertInitialSoundLaw '뢰' `shouldBe` '뇌'
            convertInitialSoundLaw '래' `shouldBe` '내'
            convertInitialSoundLaw '루' `shouldBe` '누'
            convertInitialSoundLaw '로' `shouldBe` '노'
            convertInitialSoundLaw '릉' `shouldBe` '능'
    specify "revertInitialSoundLaw" $ do
        revertInitialSoundLaw '여' `shouldBe` ['녀', '려']
        revertInitialSoundLaw '유' `shouldBe` ['뉴', '류']
        revertInitialSoundLaw '연' `shouldBe` ['년', '련']
        revertInitialSoundLaw '이' `shouldBe` ['니', '리']
        revertInitialSoundLaw '요' `shouldBe` ['뇨', '료']
        revertInitialSoundLaw '입' `shouldBe` ['닙', '립']
        revertInitialSoundLaw '양' `shouldBe` ['량']
        revertInitialSoundLaw '예' `shouldBe` ['례']
        revertInitialSoundLaw '낙' `shouldBe` ['락']
        revertInitialSoundLaw '뇌' `shouldBe` ['뢰']
        revertInitialSoundLaw '내' `shouldBe` ['래']
        revertInitialSoundLaw '누' `shouldBe` ['루']
        revertInitialSoundLaw '노' `shouldBe` ['로']
        revertInitialSoundLaw '능' `shouldBe` ['릉']