Edge Rewrite
// request.cf · coarse context

A page that knows where it met you.

Only coarse request metadata is shown. This demo does not display or persist visitor IP addresses.

Country
US
Cloudflare location
CMH
Connection
HTTP/2
Language
Not provided

Ray ID: a27c594dfc3118aa

Jump to content

Module:Ko-translit/data/sandbox

From Wikipedia, the free encyclopedia
local p = {}
local m_utils = require('Module:Ko-utils')
local gsub = mw.ustring.gsub
local gsub_iterate = m_utils.gsub_iterate

--[[
IMPORTANT NOTE before editing this module:
1. Make sure that you use a font that displays the following characters differently, and that you know the differences of them:
	ᄀ (U+1100)
	ᆨ (U+11A8)
	ㄱ (U+3131)
2. When dealing with decomposed Hangul,
	a. [ᄀ-ᄒ] should not be directly followed by [ᅡ-ᅵ] because MediaWiki applies Unicode Normalization Form C (NFC), which converts any sequence of [ᄀ-ᄒ][ᅡ-ᅵ] into a precomposed character. Use square brackets or parentheses to avoid this (e.g. ᄀ[ᅡ], (ᄀ)ᅡ, etc.)
	b. ᄀ[ᅡ] or (ᄀ)ᅡ at the end of a pattern is equivalent to not just 가 but [가-갛] in precomposed form. To match a syllabic block without a final consonant at the end of a pattern, use both vowel + [^ᆨ-ᇂ] and vowel + $
		For example, to only match 가 (and not [각-갛]) at the end of a pattern, use both ᄀ[ᅡ][^ᆨ-ᇂ] and ᄀ[ᅡ]$
--]]

function p.respell(text, mode)
	--[[
	IMPORTANT: Before adding a replacement, be sure to check if it can ALWAYS be applied in ALL contexts.
		Good example: 싫증 → 실@증
		Bad example: 문자 → 문@자 (affects words like 방문자 (pronounced [방문자], not [방문짜]))
	--]]

	-- Validate mode param
	mode = mw.ustring.lower(mode)
	assert(mode == "mr" or mode == "rr", "mode must be either mr or rr")

	-- MR only: ㅢ → ㅣ, except 의, 희
	if mode == "mr" then
		text = gsub(text, "([ᄀ-ᄊᄌ-ᄑ])ᅴ", "%1ᅵ")
	end

	local replacements = {
		-- Converting some Compatibility Jamo (U+31xx) to Hangul Jamo (U+11xx) for linguistic contexts
		-- As Compatibility Jamo do not differentiate between initial/final, we convert only several jamo where initial/final is a relevant distinction
		{"ㄴ([ᄀ-ᄒ])", "ᆫ%1"}, -- -ㄴ다
		{"ㄹ([ᄀ-ᄒ])", "ᆯ%1"}, -- -ㄹ까, -ㄹ래
		{"ㄹ@([ᄀᄃᄇᄉᄌ])", "ᆯ@%1"}, -- -ㄹ지
		{"%-ㄹ", "-ᆯ"}, -- -ㄹ (with actual hyphen)
		{"ㅂ([ᄀ-ᄒ])", "ᆸ%1"}, -- -ㅂ니다, -ㅂ시다

		-- cases where ㄺㄱ is pronounced [ㄹㄲ]
		-- verb/adjective stem ending in ㄺ + ending/suffix beginning with ㄱ (e.g. 맑고 [말꼬], 긁개 [글깨])
		{"(ᄀ[ᅡᅮᅳ])ᆰᄀ", "%1ᆯ@ᄀ"}, -- 갉-, 굵-, 긁-
		{"(ᄂ[ᅡᅳ])ᆰᄀ", "%1ᆯ@ᄀ"}, -- 낡-, 늙-
		{"([ᄆᄇ][ᅡᅮ])ᆰᄀ", "%1ᆯ@ᄀ"}, -- 맑-, 묽-, 밝-, 붉-
		{"(ᄋ[ᅡᅥᅩᅵ])ᆰᄀ", "%1ᆯ@ᄀ"}, -- 앍-, 얽-, 옭-, 읽-
		-- otherwise, ㄺㄱ is pronounced [ㄱㄲ]; handled later in neutralization of syllable-final consonants

		-- Exception to palatalization:
		-- 곧이어 [고디어] resyllabification
		{"(ᄀ[ᅩ])ᆮᄋ(ᅵᄋ[ᅥ][^ᆨ-ᇂ])", "%1ᄃ%2"},
		{"(ᄀ[ᅩ])ᆮᄋ(ᅵᄋ[ᅥ])$", "%1ᄃ%2"},

		-- palatalization and ㅈ + -히-
		-- 여/혀 (contractions of 이어/히어) captured where it is valid (namely after verbs/adjectives)
		{"ᆮᄋ(ᅵ[ᆫᆯᆸ])", "ᄌ%1"}, -- e.g. 해돋이 [해도지]
		{"ᆮᄋ(ᅵ[^ᆨ-ᇂ])", "ᄌ%1"}, -- ㄷ여 does not occur in dictionary
		{"ᆮᄋ(ᅵ)$", "ᄌ%1"},
		{"[ᆮᆽ]ᄒ(ᅵ[ᆫᆯᆷᆸ])", "ᄎ%1"}, -- e.g. 굳히다 [구치다], 꽂히다 [꼬치다]
		{"[ᆮᆽ]ᄒ(ᅧᆻ)", "ᄎ%1"}, -- ㅈ + -히- included here because functionally same outcome
		{"[ᆮᆽ]ᄒ([ᅧᅵ][^ᆨ-ᇂ])", "ᄎ%1"}, -- other ㅈ + ㅎ cases are ㅈㅎ → ㄷㅎ → ㅌ
		{"[ᆮᆽ]ᄒ([ᅧᅵ])$", "ᄎ%1"},
		{"ᆴᄋ(ᅵ[ᆫᆯᆷᆸ])", "ᆯᄎ%1"}, -- e.g. 훑이다 [훌치다]
		{"ᆴᄋ(ᅧᆻ)", "ᆯᄎ%1"}, -- Other ㄾㅇ → ㄹㅌ
		{"ᆴᄋ([ᅧᅵ][^ᆨ-ᇂ])", "ᆯᄎ%1"},
		{"ᆴᄋ([ᅧᅵ])$", "ᆯᄎ%1"},
		{"ᇀᄋ(ᅵ[ᆫᆯᆷᆸ])", "ᄎ%1"}, -- e.g. 붙이다 [부치다]
		{"ᇀᄋ(ᅧᆻ)", "ᄎ%1"}, -- Other ㅌㅇ → ㅌ, or ㄷ (use $) or ㄴㄴ (use @)
		{"ᇀᄋ([ᅧᅵ][^ᆨ-ᇂ])", "ᄎ%1"},
		{"ᇀᄋ([ᅧᅵ])$", "ᄎ%1"},

		-- {ㄵ, ㄺ, ㄼ} + -히-
		{"ᆬᄒ(ᅵ[ᆫᆯᆷᆸ])", "ᆫᄎ%1"}, -- e.g. 앉히다 [안치다]
		{"ᆬᄒ(ᅧᆻ)", "ᆫᄎ%1"},
		{"ᆬᄒ([ᅧᅵ][^ᆨ-ᇂ])", "ᆫᄎ%1"},
		{"ᆬᄒ([ᅧᅵ])$", "ᆫᄎ%1"},
		{"ᆰᄒ(ᅵ[ᆫᆯᆷᆸ])", "ᆯᄏ%1"}, -- e.g. 밝히다 [발키다]
		{"ᆰᄒ(ᅧᆻ)", "ᆯᄏ%1"},
		{"ᆰᄒ([ᅧᅵ][^ᆨ-ᇂ])", "ᆯᄏ%1"},
		{"ᆰᄒ([ᅧᅵ])$", "ᆯᄏ%1"},
		{"ᆲᄒ(ᅵ[ᆫᆯᆷᆸ])", "ᆯᄑ%1"}, -- e.g. 넓히다 [널피다], 밟히다 [발피다]
		{"ᆲᄒ(ᅧᆻ)", "ᆯᄑ%1"},
		{"ᆲᄒ([ᅧᅵ][^ᆨ-ᇂ])", "ᆯᄑ%1"},
		{"ᆲᄒ([ᅧᅵ])$", "ᆯᄑ%1"},

		-- cases where 넓- is pronounced [넙] before consonant
		{"(ᄂ[ᅥ])ᆲ([ᄁᄄ-ᄈᄊᄍ-ᄒ])", "%1ᆸ%2"}, -- all except ㄱ, ㄴ, ㄷ, ㅅ, ㅇ, ㅈ (exceptions handled below)
		{"(ᄂ[ᅥ])ᆲ(ᄃ[ᅡ]ᄃ[ᅳ]ᆷ)", "%1ᆸ%2"}, -- 넓다듬이; all other 넓다 are [널따]
		{"(ᄂ[ᅥ])ᆲ(ᄃ[ᅮ]ᆼ)", "%1ᆸ%2"}, -- 넓둥글다; last remaining 넓ㄷ with [넙]
		{"(ᄂ[ᅥ])ᆲ(ᄉ[ᅡ]ᆯᄆ[ᅮ]ᆫ)", "%1ᆸ%2"}, -- 넓살문; only 넓ㅅ word with this pronunciation; compare 넓습니다 [널씀니다]
		{"(ᄂ[ᅥ])ᆲ(ᄌ[ᅥᅮ]ᆨ)", "%1ᆸ%2"}, -- 넓적-, 넓죽-

		-- 밟- is [밥] before consonant (except syllable-initial ㅇ; ㅎ covered earlier)
		{"(ᄇ[ᅡ])ᆲ([^ᄋ])", "%1ᆸ%2"},
		{"(ᄇ[ᅡ])ᆲ$", "%1ᆸ"},

		-- 여덟 + particle (tensification does not occur as it is a noun; only relevant to MR)
		{"(ᄋ[ᅧ]ᄃ[ᅥ])ᆲ([ᄀᄃᄇᄉᄌ])", "%1ᆯ%2"},

		-- tensification after ㄵ, ㄼ, ㄾ (only relevant to MR)
		-- ㄵ, ㄼ, ㄾ are only used in verb/adjective stems (except 여덟 handled above), and they tensify the ending following them (e.g. 앉고 [안꼬], 짧다 [짤따], 핥지 [할찌])
		-- syllable-final ㄻ is not included because it does not always cause tensification (e.g. 굶기다 [굼기다]); ㄻ should be handled with @ manually as appropriate
		-- syllable-initial ㅂ is not included because no verb/adjective ending starts with it
		-- syllable-initial ㅅ is handled later in additional ㅎ combinations
		{"([ᆬᆲᆴ])([ᄀᄃᄌ])", "%1@%2"},

		-- Exceptions to neutralization + resyllabification
		-- ㄴ-addition exceptions
		{"([ᆨ-ᇂ])ᄋ([ᅧᅵ]ᇁ)", "%1ᄂ%2"}, -- 옆, 잎
		{"([ᆨ-ᇂ])ᄋ(ᅲᆾ)", "%1ᄂ%2"}, -- 윷
		-- Other exceptions
		{"(ᄋ[ᅥ])ᆹᄋ(ᅢ[ᆫᆯᆷᆸᆻ])", "%1ᆸᄉ%2"}, -- 없애다 [업쌔다]
		{"(ᄋ[ᅥ])ᆹᄋ(ᅢ[^ᆨ-ᇂ])", "%1ᆸᄉ%2"},
		{"(ᄋ[ᅥ])ᆹᄋ(ᅢ)$", "%1ᆸᄉ%2"},
		{"(ᄆ[ᅡᅥ])ᆺᄋ(ᅵᆻ)", "%1ᄉ%2"}, -- 맛있다 [마싣따], 멋있다 [머싣따]
		{"(ᄇ[ᅡ])ᆮᄋ(ᅵᆺ)ᄀ", "%1ᄌ%2@ᄀ"}, -- 받잇ㄱ [바지ㄲ~바짇ㄲ]
		{"(ᄇ[ᅡ])ᆮᄋ(ᅵᆺ[ᄃᄌ])", "%1ᄌ%2"}, -- 받잇 + {ㄷ, ㅈ} [바지~바짇] + {[ㄸ], [ㅉ]}
		{"(ᄇ[ᅮ])ᇀᄋ(ᅵᆺ)ᄀ", "%1ᄎ%2@ᄀ"}, -- 붙잇ㄱ [부치ㄲ~부칟ㄲ]
		{"(ᄋ[ᅡ])ᇁᄋ(ᅦᆺ)(ᄀ[ᅥ]ᆺ)", "%1ᄑ%2@%3"}, -- 앞엣것 [아페껃~아펟껃]
		{"(ᄋ[ᅩ])ᆺᄋ(ᅦᆺᄂ[ᅵ][ᆫᆯᆸ])", "%1ᄉ%2"}, -- 옷엣니 [오센니]
		{"(ᄋ[ᅩ])ᆺᄋ(ᅦᆺᄂ[ᅵ][^ᆨ-ᇂ])", "%1ᄉ%2"},
		{"(ᄋ[ᅩ])ᆺᄋ(ᅦᆺᄂ[ᅵ])$", "%1ᄉ%2"},
		{"(ᄒ[ᅡ]ᆫᄉ[ᅩ])ᇀᄋ(ᅦᆺ)(ᄇ[ᅡ]ᆸ)", "%1ᄐ%2@%3"}, -- 한솥엣밥 [한소테빱~한소텓빱]

		-- Some neutralization + resyllabification automatically detected here
		-- Processing happens later in neutralization + resyllabification
		-- Other cases users must detect on their own and add $ to fix
		{"([ᆩᆪᆬᆰ-ᆵᆹ-ᆻᆽ-ᇂ])(ᄋ[ᅡᅥᅧ][ᆨ-ᆺᆼ-ᇂ])", "%1$%2"}, -- except 아, 았, 어, 었, 여, 였
		{"([ᆩᆪᆬᆰ-ᆵᆹ-ᆻᆽ-ᇂ])(ᄋ[ᅦ][ᆨ-ᆪᆬ-ᆮᆰ-ᇂ])", "%1$%2"}, -- except 에, 엔, 엘
		{"([ᆩᆪᆬᆰ-ᆵᆹ-ᆻᆽ-ᇂ])(ᄋ[ᅭᅴ][ᆨ-ᇂ])", "%1$%2"}, -- except 요, 의 (w/o final consonant)
		{"([ᆩᆪᆬᆰ-ᆵᆹ-ᆻᆽ-ᇂ])(ᄋ[ᅳᅵ][ᆨ-ᆪᆬ-ᆮᆰ-ᆶᆹ-ᇂ])", "%1$%2"}, -- except 으, 은, 을, 음, 읍, 이, 인, 일, 임, 입
		{"([ᆩᆪᆬᆰ-ᆵᆹ-ᆻᆽ-ᇂ])(ᄋ[ᅢ-ᅤᅨ-ᅬᅮ-ᅲ])", "%1$%2"},

		-- @ for ㄴ-addition
		-- Can't go with other @/$ irregularities because needs to occur before resyllabification
		{"([ᆨ-ᇂ])@ᄋ([ᅣᅤᅧᅨᅭᅲᅵ])", "%1ᄂ%2"}, -- e.g. 색연필 [생년필], 물엿 [물렫]

		-- Resyllabification
		-- {ㄱ, ㄷ, ㄹ/ㅀ, ㅂ} + ㅇ is handled later in neutralization + resyllabification; {ㄴ/ㄶ, ㅁ} + ㅇ is not needed for RR & MR
		{"ᆩᄋ", "ᄁ"},
		{"ᆪᄋ", "ᆨᄉ"},
		{"ᆬᄋ", "ᆫᄌ"},
		{"ᆰᄋ", "ᆯᄀ"},
		{"ᆱᄋ", "ᆯᄆ"},
		{"ᆲᄋ", "ᆯᄇ"},
		{"ᆳᄋ", "ᆯᄉ"},
		{"ᆴᄋ", "ᆯᄐ"},
		{"ᆵᄋ", "ᆯᄑ"},
		{"ᆹᄋ", "ᆸᄉ"},
		{"ᆺᄋ", "ᄉ"},
		{"ᆻᄋ", "ᄊ"},
		{"ᆽᄋ", "ᄌ"},
		{"ᆾᄋ", "ᄎ"},
		{"ᆿᄋ", "ᄏ"},
		{"ᇀᄋ", "ᄐ"},
		{"ᇁᄋ", "ᄑ"},
		{"ᇂᄋ", "ᄋ"}, -- silent; 좋아 [조아]

		-- 싫증 [실쯩] (only ㅀㅈ [ㄹㅉ] exception)
		{"(ᄉ[ᅵ])ᆶ(ᄌ[ᅳ]ᆼ)", "%1ᆯ@%2"},

		-- convert ㅎ combinations
		-- trivia: {ㄶ, ㅀ, ㅎ} + ㅂ don't actually exist, but added for completeness (syllable-final ㅎ is for aspiration anyway)
		{"ᆭᄀ", "ᆫᄏ"},
		{"ᆭᄃ", "ᆫᄐ"},
		{"ᆭᄇ", "ᆫᄑ"},
		{"ᆭᄌ", "ᆫᄎ"},
		{"ᆶᄀ", "ᆯᄏ"},
		{"ᆶᄃ", "ᆯᄐ"},
		{"ᆶᄇ", "ᆯᄑ"},
		{"ᆶᄌ", "ᆯᄎ"},
		{"ᇂᄀ", "ᄏ"},
		{"ᇂᄃ", "ᄐ"},
		{"ᇂᄇ", "ᄑ"},
		{"ᇂᄌ", "ᄎ"}
	}
	text = gsub_iterate(text, replacements)
	if mode == "mr" then
		replacements = {
			-- additional ㅎ combinations
			-- also including {ㄵ, ㄼ, ㄾ} + ㅅ here because functionally same outcome
			{"[ᆬᆭ]ᄉ", "ᆫᄊ"},
			{"[ᆲᆴᆶ]ᄉ", "ᆯᄊ"},
			{"ᇂᄉ", "ᄊ"},
			-- @ for written epenthetic ㅅ + ㄱ/ㅂ
			{"ᆺ@ᄀ", "ᄁ"},
			{"ᆺ@ᄇ", "ᄈ"}
		}
		text = gsub_iterate(text, replacements)
	else
		text = gsub(text, "ᇂᄉ", "ᄉ")
	end

	-- Neutralization of syllable-final consonants
	-- after this, the 27 syllable-final consonants are reduced to 7 (ㄱ, ㄴ, ㄷ, ㄹ, ㅁ, ㅂ, ㅇ)
	replacements = {
		{"[ᆩᆪᆰᆿ]", "ᆨ"},
		{"[ᆬᆭ]", "ᆫ"},
		{"[ᆺᆻᆽᆾᇀᇂ]", "ᆮ"},
		{"[ᆲᆳᆴᆶ]", "ᆯ"},
		{"ᆱ", "ᆷ"},
		{"[ᆵᆹᇁ]", "ᆸ"}
	}
	text = gsub_iterate(text, replacements)

	-- Remaining @/$ irregularities
	if mode == "mr" then
		text = gsub(text, "([ᅡ-ᅵᆫᆷᆼ])@ᄉ", "%1ᄊ") -- Tensification of ㅅ
	else
		replacements = {
			{"ᆨ@ᄒ", "ᄏ"},
			{"ᆮ@ᄒ", "ᄐ"},
			{"ᆸ@ᄒ", "ᄑ"}
		}
		text = gsub_iterate(text, replacements)
	end
	replacements = {
		-- ㄴㄹ [ㄴㄴ], e.g. 음운론 [으문논]
		{"ᆫ@ᄅ", "ᆫᄂ"},
		-- neutralization + resyllabification
		{"ᆨ%$?ᄋ", "ᄀ"},
		{"ᆮ%$?ᄋ", "ᄃ"}, -- e.g. 웃어른 [우더른]
		{"ᆯ%$?ᄋ", "ᄅ"},
		{"ᆸ%$?ᄋ", "ᄇ"},
		{"%$", ""} -- remove remaining $s
	}
	text = gsub_iterate(text, replacements)

	-- MR only: voicing of ㄱ, ㄷ, ㅂ, ㅈ
	if mode == "mr" then
		replacements = {
			{"ᆫᄀ", "ᆫ'`ᄀ"}, -- n'g
			{"([ᅡ-ᅵᆫᆯᆷᆼ])([ᄀᄃᄇᄌ])", "%1`%2"},
			{"([ᅡ-ᅵᆫᆯᆷᆼ])%*([ᄀᄃᄇᄌ])", "%1-`%2"} -- * is for additional hyphen in romanization only (voicing is retained after hyphen)
		}
		text = gsub_iterate(text, replacements)
	end
	-- remove remaining @s
	-- to reflect tensification in MR, @ needs to be retained while voicing of ㄱ, ㄷ, ㅂ, ㅈ is being applied (@ prevents voicing)
	-- e.g. 한자 [한짜] in MR is hancha (neither hanja nor hantcha)
	text = gsub(text, "@", "")

	-- Assimilation
	replacements = {
		{"[ᆨᆼ][ᄂᄅ]", "ᆼᄂ"},
		{"ᆨᄆ", "ᆼᄆ"},
		{"ᆫᄅ", "ᆯᄅ"},
		{"ᆮ[ᄂᄅ]", "ᆫᄂ"},
		{"ᆮᄆ", "ᆫᄆ"},
		{"ᆯᄂ", "ᆯᄅ"},
		{"[ᆷᆸ][ᄂᄅ]", "ᆷᄂ"},
		{"ᆸᄆ", "ᆷᄆ"}
	}
	text = gsub_iterate(text, replacements)
	-- MR only: no {kkk, ttt, ppp, sss/ts/tss, ttch}
	if mode == "mr" then
		replacements = {
			{"ᆨᄁ", "ᄁ"},
			{"ᆮᄄ", "ᄄ"},
			{"ᆸᄈ", "ᄈ"},
			{"ᆮ[ᄉᄊ]", "ᄊ"},
			{"ᆮᄍ", "ᄍ"}
		}
		text = gsub_iterate(text, replacements)
	end

	-- Drop the semivowel y (/j/) after ㅈ, ㅉ, ㅊ
	replacements = {
		{"([ᄌ-ᄎ])ᅣ", "%1ᅡ"},
		{"([ᄌ-ᄎ])ᅤ", "%1ᅢ"},
		{"([ᄌ-ᄎ])ᅧ", "%1ᅥ"},
		{"([ᄌ-ᄎ])ᅨ", "%1ᅦ"},
		{"([ᄌ-ᄎ])ᅭ", "%1ᅩ"},
		{"([ᄌ-ᄎ])ᅲ", "%1ᅮ"}
	}
	return gsub_iterate(text, replacements)
end

function p.romanize_rr(text)
	local replacements = {
		{"ᆯᄅ", "ᆯl"},

		-- Vowels
		{"[ᅡㅏ]", "a"},
		{"[ᅢㅐ]", "ae"},
		{"[ᅣㅑ]", "ya"},
		{"[ᅤㅒ]", "yae"},
		{"[ᅥㅓ]", "eo"},
		{"[ᅦㅔ]", "e"},
		{"[ᅧㅕ]", "yeo"},
		{"[ᅨㅖ]", "ye"},
		{"[ᅩㅗ]", "o"},
		{"[ᅪㅘ]", "wa"},
		{"[ᅫㅙ]", "wae"},
		{"[ᅬㅚ]", "oe"},
		{"[ᅭㅛ]", "yo"},
		{"[ᅮㅜ]", "u"},
		{"[ᅯㅝ]", "wo"},
		{"[ᅰㅞ]", "we"},
		{"[ᅱㅟ]", "wi"},
		{"[ᅲㅠ]", "yu"},
		{"[ᅳㅡ]", "eu"},
		{"[ᅴㅢ]", "ui"},
		{"[ᅵㅣ]", "i"},

		-- to prevent input like 'ㅇ' (with ') from becoming italic markup (as [ᄋㅇ] is simply removed later)
		{"'([ᄋㅇ]+)'", "'%1'"},

		-- Consonants
		{"[ᄀㄱ]", "g"},
		{"[ᄁㄲ]", "kk"},
		{"ㄳ", "ks"},
		{"[ᄂᆫㄴ]", "n"},
		{"ㄵ", "nj"},
		{"ㄶ", "nh"},
		{"[ᄃㄷ]", "d"},
		{"[ᄄㄸ]", "tt"},
		{"[ᄅㄹ]", "r"},
		{"ᆯ", "l"},
		{"ㄺ", "lg"},
		{"ㄻ", "lm"},
		{"ㄼ", "lb"},
		{"ㄽ", "ls"},
		{"ㄾ", "lt"},
		{"ㄿ", "lp"},
		{"ㅀ", "lh"},
		{"[ᄆᆷㅁ]", "m"},
		{"[ᄇㅂ]", "b"},
		{"[ᄈㅃ]", "pp"},
		{"ㅄ", "ps"},
		{"[ᄉㅅ]", "s"},
		{"[ᄊㅆ]", "ss"},
		{"[ᄋㅇ]", ""},
		{"ᆼ", "ng"},
		{"[ᄌㅈ]", "j"},
		{"[ᄍㅉ]", "jj"},
		{"[ᄎㅊ]", "ch"},
		{"[ᄏᆨㅋ]", "k"},
		{"[ᄐᆮㅌ]", "t"},
		{"[ᄑᆸㅍ]", "p"},
		{"[ᄒㅎ]", "h"}
	}
	return gsub_iterate(text, replacements)
end

function p.romanize_mr(text)
	local replacements = {
		-- First some quirks related to MR
		{"ᆯᄅ", "ᆯl"},
		{"ᆯ%*ᄅ", "ᆯ-l"}, -- ㄹ-ㄹ (with hyphen in between) should probably be l-l rather than l-r
		{"ᆯᄒ", "rᄒ"},
		{"ᄉ[ᅱ]", "shᅱ"}, -- ㅅ is sh before ㅟ; otherwise sh is not used

		-- Vowels
		{"[ᅡㅏ]", "a"},
		{"[ᅢㅐ]", "ae"},
		{"[ᅣㅑ]", "ya"},
		{"[ᅤㅒ]", "yae"},
		{"[ᅥㅓ]", "ŏ"},
		{"[ᅦㅔ]", "e"},
		{"[ᅧㅕ]", "yŏ"},
		{"[ᅨㅖ]", "ye"},
		{"[ᅩㅗ]", "o"},
		{"[ᅪㅘ]", "wa"},
		{"[ᅫㅙ]", "wae"},
		{"[ᅬㅚ]", "oe"},
		{"[ᅭㅛ]", "yo"},
		{"[ᅮㅜ]", "u"},
		{"[ᅯㅝ]", "wŏ"},
		{"[ᅰㅞ]", "we"},
		{"[ᅱㅟ]", "wi"},
		{"[ᅲㅠ]", "yu"},
		{"[ᅳㅡ]", "ŭ"},
		{"[ᅴㅢ]", "ŭi"},
		{"[ᅵㅣ]", "i"},

		-- e → ë when e is not part of digraphs ae & oe (e.g. ㅐ is ae, but ㅏ에 is aë)
		{"([ao])ᄋe", "%1ë"},
		-- to prevent input like 'ㅇ' (with ') from becoming italic markup (as [ᄋㅇ] is simply removed later)
		{"'([ᄋㅇ]+)'", "'%1'"},

		-- Consonants
		{"`ᄀ", "g"},
		{"`ᄃ", "d"},
		{"`ᄇ", "b"},
		{"`ᄌ", "j"},
		{"`", ""},
		{"[ᄀᆨㄱ]", "k"},
		{"[ᄁㄲ]", "kk"},
		{"ㄳ", "ks"},
		{"[ᄂᆫㄴ]", "n"},
		{"ㄵ", "nj"},
		{"ㄶ", "nh"},
		{"[ᄃᆮㄷ]", "t"},
		{"[ᄄㄸ]", "tt"},
		{"[ᄅㄹ]", "r"},
		{"ᆯ", "l"},
		{"ㄺ", "lg"},
		{"ㄻ", "lm"},
		{"ㄼ", "lb"},
		{"ㄽ", "ls"},
		{"ㄾ", "lt'"},
		{"ㄿ", "lp'"},
		{"ㅀ", "rh"},
		{"[ᄆᆷㅁ]", "m"},
		{"[ᄇᆸㅂ]", "p"},
		{"[ᄈㅃ]", "pp"},
		{"ㅄ", "ps"},
		{"[ᄉㅅ]", "s"},
		{"[ᄊㅆ]", "ss"},
		{"[ᄋㅇ]", ""},
		{"ᆼ", "ng"},
		{"[ᄌㅈ]", "ch"},
		{"[ᄍㅉ]", "tch"},
		{"[ᄎㅊ]", "ch'"},
		{"[ᄏㅋ]", "k'"},
		{"[ᄐㅌ]", "t'"},
		{"[ᄑㅍ]", "p'"},
		{"[ᄒㅎ]", "h"}
	}
	return gsub_iterate(text, replacements)
end

return p