Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
If you make an edit, a temporary account will be created for you.

Editing Module:Th-rm

From The Petit Planet Wiki
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
local p = {}
local p = {}


local arguments = require('Module:Arguments')
local U = mw.ustring
local tt = require('Module:Tt')
local gsub = U.gsub
local find = U.find
local sub = U.sub
local match = U.match
local len = U.len


local AUTO_TOOLTIP = 'This romanization was generated automatically. Please add a user-curated romanization as soon as possible.'
local INITIAL = {
 
local THAI = '[ก-๛]'
 
-- Initial consonants.
local consonants = {
['ก'] = 'k',
['ก'] = 'k',
['ข'] = 'kh',
['ข'] = 'kh', ['ฃ'] = 'kh', ['ค'] = 'kh', ['ฅ'] = 'kh', ['ฆ'] = 'kh',
['ฃ'] = 'kh',
['ค'] = 'kh',
['ฅ'] = 'kh',
['ฆ'] = 'kh',
['ง'] = 'ng',
['ง'] = 'ng',
['จ'] = 'ch',
['จ'] = 'ch', ['ฉ'] = 'ch', ['ช'] = 'ch',
['ฉ'] = 'ch',
['ช'] = 'ch',
['ซ'] = 's',
['ซ'] = 's',
['ฌ'] = 'ch',
['ฌ'] = 'ch',
Line 25: Line 18:
['ฎ'] = 'd',
['ฎ'] = 'd',
['ฏ'] = 't',
['ฏ'] = 't',
['ฐ'] = 'th',
['ฐ'] = 'th', ['ฑ'] = 'th', ['ฒ'] = 'th',
['ฑ'] = 'th',
['ฒ'] = 'th',
['ณ'] = 'n',
['ณ'] = 'n',
['ด'] = 'd',
['ด'] = 'd',
['ต'] = 't',
['ต'] = 't',
['ถ'] = 'th',
['ถ'] = 'th', ['ท'] = 'th', ['ธ'] = 'th',
['ท'] = 'th',
['ธ'] = 'th',
['น'] = 'n',
['น'] = 'n',
['บ'] = 'b',
['บ'] = 'b',
Line 47: Line 36:
['ล'] = 'l',
['ล'] = 'l',
['ว'] = 'w',
['ว'] = 'w',
['ศ'] = 's',
['ศ'] = 's', ['ษ'] = 's', ['ส'] = 's',
['ษ'] = 's',
['ส'] = 's',
['ห'] = 'h',
['ห'] = 'h',
['ฬ'] = 'l',
['ฬ'] = 'l',
['ฮ'] = 'h',
['ฮ'] = 'h'
['อ'] = ''
}
}


-- Final consonants.
local FINAL = {
local finals = {
['ก'] = 'k',
['ก'] = 'k',
['ข'] = 'k',
['ข'] = 'k', ['ฃ'] = 'k', ['ค'] = 'k', ['ฅ'] = 'k', ['ฆ'] = 'k',
['ฃ'] = 'k',
['ง'] = 'ng',
['ค'] = 'k',
['จ'] = 't', ['ฉ'] = 't', ['ช'] = 't', ['ฌ'] = '',
['ฅ'] = 'k',
['ฆ'] = 'k',
 
['จ'] = 't',
['ฉ'] = 't',
['ช'] = 't',
['ซ'] = 't',
['ซ'] = 't',
['ฌ'] = 't',
['ญ'] = 'n',
['ฎ'] = 't',
['ฎ'] = 't', ['ฏ'] = 't',
['ฏ'] = 't',
['ฐ'] = 't', ['ฑ'] = 't', ['ฒ'] = 't',
['ฐ'] = 't',
['ณ'] = 'n',
['ฑ'] = 't',
['ฒ'] = 't',
['ด'] = 't',
['ด'] = 't',
['ต'] = 't',
['ต'] = 't',
['ถ'] = 't',
['ถ'] = 't', ['ท'] = 't', ['ธ'] = 't',
['ท'] = 't',
['น'] = 'n',
['ธ'] = 't',
['ศ'] = 't',
['ษ'] = 't',
['ส'] = 't',
 
['บ'] = 'p',
['บ'] = 'p',
['ป'] = 'p',
['ป'] = 'p',
['ผ'] = 'p',
['ผ'] = '', ['ฝ'] = '',
['ฝ'] = 'p',
['พ'] = 'p', ['ฟ'] = 'p', ['ภ'] = 'p',
['พ'] = 'p',
['ม'] = 'm',
['ฟ'] = 'p',
['ย'] = '',
['ภ'] = 'p',
 
['ง'] = 'ng',
 
['ญ'] = 'n',
['ณ'] = 'n',
['น'] = 'n',
['ร'] = 'n',
['ร'] = 'n',
['ล'] = 'n',
['ล'] = 'n',
['ว'] = '',
['ศ'] = 't', ['ษ'] = 't', ['ส'] = 't',
['ห'] = '',
['ฬ'] = 'n',
['ฬ'] = 'n',
 
['ฮ'] = ''
['ม'] = 'm'
}
}


-- Vowels.
-- Vowel patterns are tested longest-first.
local vowels = {
local VOWELS = {
['เียะ'] = 'ia',
{ 'เ' , 'ะ', 'e' },
['เีย'] = 'ia',
{ 'เ' , '็', 'e' },
['เือะ'] = 'uea',
{ 'เ' , '', 'e' },
['เือ'] = 'uea',
['เือย'] = 'ueai',
['เียว'] = 'iao',


['ัวะ'] = 'ua',
{ 'แ' , 'ะ', 'ae' },
['ัว'] = 'ua',
{ 'แ' , '',  'ae' },


['เิ็ย'] = 'oei',
{ 'โ' , 'ะ', 'o' },
['เิย'] = 'oei',
{ 'โ' , '',  'o' },
['เอย'] = 'oei',
{ 'เ' , 'าะ', 'o' },
{ ''  , 'อ', 'o' },


['็อย'] = 'oi',
{ 'เ' , 'อะ', 'oe' },
['อย'] = 'oi',
{ 'เ' , 'ิ', 'oe' },
{ 'เ' , 'อ', 'oe' },


['ุย'] = 'ui',
{ 'เ' , 'ียะ', 'ia' },
['วย'] = 'uai',
{ 'เ' , 'ีย', 'ia' },


['ัย'] = 'ai',
{ 'เ' , 'ือะ', 'uea' },
['ไย'] = 'ai',
{ 'เ' , 'ือ', 'uea' },
['าย'] = 'ai',
['ใ'] = 'ai',
['ไ'] = 'ai',


['เ็ว'] = 'eo',
{ '' , 'ัวะ', 'ua' },
['แ็ว'] = 'aeo',
{ '' , 'ัว', 'ua' },
['เา'] = 'ao',
{ '' , 'ว', 'ua' },
['าว'] = 'ao',
['แว'] = 'aeo',
['เว'] = 'eo',


['ิว'] = 'io',
{ 'ใ', '', 'ai' },
['ีว'] = 'io',
{ 'ไ', '', 'ai' },
{ '' , 'ัย', 'ai' },
{ 'ไ', 'ย', 'ai' },
{ '' , 'าย', 'ai' },


['ำ'] = 'am',
{ 'เ', 'า', 'ao' },
{ '' , 'าว', 'ao' },


['ือ'] = 'ue',
{ '' , 'ุย', 'ui' },
['ื'] = 'ue',
['ึ'] = 'ue',


['ิ'] = 'i',
{ 'โ', 'ย', 'oi' },
['ี'] = 'i',
{ '' , 'อย', 'oi' },


['ุ'] = 'u',
{ 'เ', 'ย', 'oei' },
['ู'] = 'u',
{ 'เ', 'ือย', 'ueai' },
{ '' , 'วย', 'uai' },


['เ็'] = 'e',
{ '' , 'ิว', 'io' },
['เ'] = 'e',


['แ็'] = 'ae',
{ 'เ', '็ว', 'eo' },
['แ'] = 'ae',
{ 'เ', 'ว', 'eo' },


['โะ'] = 'o',
{ 'แ', '็ว', 'aeo' },
['โ'] = 'o',
{ 'แ', 'ว', 'aeo' },


['เาะ'] = 'o',
{ 'เ', 'ียว', 'iao' },
['อ'] = 'o',


['เอะ'] = 'oe',
{ '' , 'ะ', 'a' },
['เอ'] = 'oe',
{ '' , 'ั', 'a' },
['เะ'] = 'e',
{ '' , 'า', 'a' },
{ '' , 'ำ', 'am' },


['ะ'] = 'a',
{ '' , 'ิ', 'i' },
['ั'] = 'a',
{ '' , 'ี', 'i' },
['า'] = 'a'
}


-- Longest vowel forms must be checked first.
{ '' , 'ึ', 'ue' },
local vowel_order = {
{ '' , 'ื', 'ue' },
'เือย',
{ '' , 'ือ', 'ue' },
'เียว',
'เือะ',
'เียะ',
'เีย',
'เือ',
'ัวะ',
'ัว',
'เิ็ย',
'เิย',
'็อย',
'เ็ว',
'แ็ว',
'เอย',
'เา',
'าว',
'เว',
'แว',
'าย',
'ไย',
'ัย',
'ุย',
'วย',
'อย',
'ำ',
'ิว',
'ีว',
'ิ',
'ี',
'ึ',
'ื',
'ุ',
'ู',
'เ็',
'แ็',
'เาะ',
'เอะ',
'เอ',
'เะ',
'ะ',
'ั',
'า',
'เ',
'แ',
'โ',
'อ',
'ใ',
'ไ'
}


local consonant_set = {}
{ '' , 'ุ', 'u' },
{ '' , 'ู', 'u' },


for c in pairs(consonants) do
{ '' , 'รร', 'a' }
consonant_set[c] = true
end
 
-- Thai consonant clusters.
local valid_clusters = {
['กร'] = true,
['กล'] = true,
['กว'] = true,
['ขร'] = true,
['ขล'] = true,
['ขว'] = true,
['คร'] = true,
['คล'] = true,
['คว'] = true,
['ฆร'] = true,
['ฆล'] = true,
['จร'] = true,
['ตร'] = true,
['ปร'] = true,
['ปล'] = true,
['พร'] = true,
['พล'] = true,
['ผล'] = true,
['ทร'] = true,
['ธร'] = true,
['ศร'] = true,
['สร'] = true,
['สล'] = true,
['สว'] = true,
['ซร'] = true,
['ฝร'] = true,
['ฟร'] = true
}
}
-- ห is silent in these clusters when followed by a vowel.
local h_silent_clusters = {
['หง'] = true,
['หน'] = true,
['หม'] = true,
['หย'] = true,
['หร'] = true,
['หล'] = true,
['หว'] = true,
['หญ'] = true
}
-- ร is silent in these clusters when followed by a vowel.
local r_silent_clusters = {
['จร'] = true,
['ซร'] = true,
['ศร'] = true,
['สร'] = true
}
local function chars(text)
local result = {}
for c in mw.text.gsplit(text, '') do
table.insert(result, c)
end
return result
end


local function isConsonant(c)
local function isConsonant(c)
return c and consonant_set[c] == true
return c and INITIAL[c] ~= nil
end
end


local function isThai(c)
local function isThai(c)
return c and mw.ustring.find(c, THAI) ~= nil
return c and match(c, '[ก-๛]') ~= nil
end
end


local function isFrontVowel(c)
local function isToneMark(c)
return c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ'
return c and match(c, '[่้๊๋]') ~= nil
end
end


local function skipMarks(c, pos)
local function isSilentMark(c)
while c[pos] and (
return c == '์'
c[pos] == '็' or
end
c[pos] == '่' or
c[pos] == '้' or
c[pos] == '๊' or
c[pos] == '๋' or
c[pos] == 'ํ' or
c[pos] == '๎'
) do
pos = pos + 1
end


return pos
local function clean(str)
str = mw.text.unstrip(str or '')
str = gsub(str, '<br%s*/?>', ' ')
str = gsub(str, '<[^>]+>', '')
return str
end
end


local function removeSilent(chars_)
local function applyOrthographicExceptions(str)
local result = {}
-- Silent letters marked with ์.
local i = 1
-- Remove the marked letter and its ์ marker.
str = gsub(str, '([ก-ฮ])์', '')


while chars_[i] do
-- Tone marks have no RTGS representation.
if chars_[i] == '์' then
str = gsub(str, '[่้๊๋]', '')
-- ์ makes the following consonant(s) silent.
i = i + 1


while chars_[i] and (
-- ฤ
isConsonant(chars_[i]) or
str = gsub(str, 'ฤกษ์', 'roe')
chars_[i] == '็' or
str = gsub(str, 'ฤิ', 'ri')
chars_[i] == '่' or
str = gsub(str, 'ฤ', 'rue')
chars_[i] == '้' or
str = gsub(str, 'ฤๅ', 'rue')
chars_[i] == '๊' or
 
chars_[i] == '๋'
-- ฦ / ฦๅ
) do
str = gsub(str, 'ฦๅ', 'lue')
i = i + 1
str = gsub(str, 'ฦ', 'lue')
end
else
table.insert(result, chars_[i])
i = i + 1
end
end


return result
return str
end
end


local function getVowel(c, pos)
local function getVowel(str, pos)
local remaining = table.concat(c, '', pos)
local remaining = sub(str, pos, -1)
 
for _, form in ipairs(vowel_order) do
local length = mw.ustring.len(form)
 
if mw.ustring.sub(remaining, 1, length) == form then
return form, vowels[form]
end
end


return nil, nil
-- Explicit special vowel patterns.
end
local patterns = {
{ 'เ', 'ื', 'อ', 'ย', 'ueai' },
{ 'เ', 'ี', 'ย', 'ว', 'iao' },
{ 'เ', 'ี', 'ย', 'ะ', 'ia' },
{ 'เ', 'ี', 'ย', '',  'ia' },
{ 'เ', 'ื', 'อ', 'ะ', 'uea' },
{ 'เ', 'ื', 'อ', '',  'uea' },


local function getInitial(c, pos)
{ 'เ', '็', 'ว', '', 'eo' },
local c1 = c[pos]
{ 'เ', 'ว', '', '', 'eo' },
{ 'แ', '็', 'ว', '', 'aeo' },
{ 'แ', 'ว', '', '', 'aeo' },


if not isConsonant(c1) then
{ 'โ', 'ย', '', '', 'oi' },
return '', pos
{ '', 'อ', 'ย', '', 'oi' },
end
{ 'เ', 'ย', '', '', 'oei' },


local c2 = c[pos + 1]
{ '', 'ว', 'ย', '', 'uai' },
{ '', 'ุ', 'ย', '', 'ui' },
{ '', 'ิ', 'ว', '', 'io' },


-- ห is not pronounced in หง หน หม หย หร หล หว หญ.
{ 'เ', 'า', '', '', 'ao' },
if c1 == 'ห' and c2 and h_silent_clusters[c1 .. c2] then
{ '', 'า', 'ว', '', 'ao' },
return consonants[c2], pos + 2, true
end


-- ทร is pronounced s in the relevant Sanskrit-derived words.
{ '', 'ั', 'ว', 'ะ', 'ua' },
-- This is the broad automatic fallback; exceptions can be manually
{ '', 'ั', 'ว', '', 'ua' },
-- supplied with th_rm.
{ '', 'ว', '', '', 'ua' },
if c1 == 'ท' and c2 == 'ร' then
return 's', pos + 2, false
end


if c2 and valid_clusters[c1 .. c2] then
{ 'ใ', '', '', '', 'ai' },
-- ร is silent in these clusters.
{ 'ไ', '', '', '', 'ai' },
if r_silent_clusters[c1 .. c2] then
{ '', 'ั', 'ย', '', 'ai' },
return consonants[c1], pos + 2, false
{ 'ไ', 'ย', '', '', 'ai' },
end
{ '', 'า', 'ย', '', 'ai' },


return consonants[c1] .. consonants[c2], pos + 2, false
{ 'เ', 'า', 'ะ', '', 'ao' },
end
{ 'โ', 'ะ', '', '', 'o' },
{ 'เ', 'า', '', '', 'ao' },
{ 'เ', 'าะ', '', '', 'o' },


return consonants[c1], pos + 1, false
{ 'เ', 'อ', '', '', 'oe' },
end
{ 'เ', 'ิ', '', '', 'oe' },
{ 'เ', 'อะ', '', '', 'oe' },


local function getCoda(c, pos)
{ 'แ', 'ะ', '', '', 'ae' },
local current = c[pos]
{ 'แ', '', '', '', 'ae' },
{ 'เ', 'ะ', '', '', 'e' },
{ 'เ', '็', '', '', 'e' },
{ 'เ', '', '', '', 'e' },
{ 'โ', '', '', '', 'o' },


if not current or not isConsonant(current) then
{ '', 'ำ', '', '', 'am' },
return '', pos
{ '', 'ะ', '', '', 'a' },
end
{ '', 'ั', '', '', 'a' },
{ '', 'า', '', '', 'a' },
{ '', 'ิ', '', '', 'i' },
{ '', 'ี', '', '', 'i' },
{ '', 'ึ', '', '', 'ue' },
{ '', 'ือ', '', '', 'ue' },
{ '', 'ื', '', '', 'ue' },
{ '', 'ุ', '', '', 'u' },
{ '', 'ู', '', '', 'u' },
{ '', 'อ', '', '', 'o' }
}


-- These do not act as ordinary codas here.
for _, v in ipairs(patterns) do
if current == 'อ' or current == 'ห' or current == 'ฮ' then
local a, b, c, d, roman = v
return '', pos
local pattern = a .. b .. c .. d
if pattern ~= '' and sub(remaining, 1, len(pattern)) == pattern then
return roman, len(pattern)
end
end
end


-- ย and ว are generally part of the vowel/diphthong.
-- Implied a.
if current == 'ย' or current == 'ว' then
return 'a', 0
return '', pos
end
end


if finals[current] then
local function nextVowelPosition(str, pos)
return finals[current], pos + 1
local i = pos
end
while i <= len(str) do
local c = sub(str, i, i)


return '', pos + 1
if c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ' then
end
return i
end


local function startsNextSyllable(c, pos)
if match(c, '[ะาิีึืุูัำอ]') then
if not c[pos] or not isConsonant(c[pos]) then
return i
return false
end
end


if isFrontVowel(c[pos + 1]) then
i = i + 1
return true
end
end


local _, vowel = getVowel(c, pos + 1)
return nil
 
return vowel ~= nil
end
end


local function parseSyllable(c, start)
local function romanizeSyllable(str, startPos)
local pos = start
local pos = startPos
local n = len(str)


if not c[pos] then
-- Preposed vowel.
return nil, pos
local preVowel = ''
end
local preLen = 0
local c = sub(str, pos, pos)


local initial = ''
if c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ' then
local cluster = false
preVowel = c
 
preLen = 1
-- Preposed vowels.
local front = ''
 
if isFrontVowel(c[pos]) then
front = c[pos]
pos = pos + 1
pos = pos + 1
end
end


local initialPos = pos
-- Initial consonant.
local initial = sub(str, pos, pos)


initial, pos, _, cluster =
if not isConsonant(initial) then
getInitial(c, pos)
-- Non-Thai character.
 
return initial, 1
if initial == '' and not isConsonant(c[initialPos]) then
return nil, start + 1
end
end


local vowel
pos = pos + 1
local vowelForm
local initialRom = INITIAL[initial] or ''
 
if front ~= '' then
-- Handle the vowel forms which contain a preposed vowel.
if front == 'เ' and c[pos] == 'ี' and c[pos + 1] == 'ย' then
vowel = 'ia'
vowelForm = 'เีย'
pos = pos + 2
 
elseif front == 'เ' and c[pos] == 'ื' and c[pos + 1] == 'อ' then
vowel = 'uea'
vowelForm = 'เือ'
pos = pos + 2


elseif front == 'เ' and c[pos] == 'อ' then
-- ห- exception.
vowel = 'oe'
if initial == 'ห' then
vowelForm = 'เอ'
local second = sub(str, pos, pos)
if second and match(second, '[งนมยรลวญณฬ]') then
initialRom = INITIAL[second]
pos = pos + 1
pos = pos + 1
initial = second
end
end


elseif front == 'เ' and c[pos] == 'า' then
-- Consonant clusters where ร is not represented.
vowel = 'ao'
if (initial == 'จ' or initial == 'ซ' or initial == 'ศ' or initial == 'ส')
vowelForm = 'เา'
and sub(str, pos, pos) == 'ร' then
pos = pos + 1
initialRom = INITIAL[initial]
pos = pos + 1
end


elseif front == 'เ' and c[pos] == '็' then
-- Find the vowel from the current position, including preposed vowels.
vowel = 'e'
local vowelStart = startPos + preLen + 1
vowelForm = 'เ็'
local vowelRoman
pos = pos + 1
local vowelLen


elseif front == 'แ' and c[pos] == '็' then
if preLen > 0 then
vowel = 'ae'
vowelRoman, vowelLen = getVowel(str, startPos + 1)
vowelForm = 'แ็'
pos = pos + 1
 
elseif front == 'โ' and c[pos] == 'ะ' then
vowel = 'o'
vowelForm = 'โะ'
pos = pos + 1
 
elseif front == 'ใ' or front == 'ไ' then
vowel = 'ai'
vowelForm = front
 
else
vowel = vowels[front]
vowelForm = front
end
else
else
vowelForm, vowel = getVowel(c, pos)
vowelRoman, vowelLen = getVowel(str, pos)
 
if vowelForm then
pos = pos + mw.ustring.len(vowelForm)
end
end
end


-- Implied vowels.
-- If the vowel was explicitly consumed by getVowel, advance.
if not vowel then
if vowelLen > 0 then
if c[pos] and isConsonant(c[pos]) then
if preLen > 0 then
if startsNextSyllable(c, pos) then
pos = startPos + preLen + 1 + vowelLen
vowel = 'a'
else
vowel = 'o'
end
else
else
vowel = 'a'
pos = pos + vowelLen
end
end
end
end


pos = skipMarks(c, pos)
-- Collect possible final consonant.
local final = sub(str, pos, pos)
local finalRom = ''


-- Final consonant.
if isConsonant(final) then
local coda = ''
local after = sub(str, pos + 1, pos + 1)
local codaPos = pos


if c[pos] and isConsonant(c[pos]) then
-- A consonant followed by a vowel-starting syllable is normally
-- If another consonant begins the next syllable, don't consume
-- treated as the next syllable's initial rather than this syllable's final.
-- it as a coda.
local nextIsVowel = after and (
if startsNextSyllable(c, pos) then
match(after, '[ะาิีึืุูัำอ]') or
coda = ''
match(after, '[เแโใไ]')
else
)
coda, codaPos = getCoda(c, pos)
end
end


pos = codaPos
if not nextIsVowel then
pos = skipMarks(c, pos)
finalRom = FINAL[final] or ''
pos = pos + 1


return {
-- -ร following another final consonant is silent in RTGS.
initial = initial,
if final == 'ร' then
vowel = vowel,
finalRom = 'n'
coda = coda,
end
next = pos
end
}, pos
end
 
local function shouldHyphen(previous, current)
if not previous or not current then
return false
end
end


-- Before a succeeding syllable beginning with a vowel.
-- ทร- exception.
if current.initial == '' and current.vowel ~= '' then
if initial == 'ท' and sub(str, pos, pos) == 'ร' then
return true
initialRom = 's'
end
pos = pos + 1
 
-- Before ng when the preceding syllable ends in a vowel.
if previous.coda == '' and current.initial == 'ng' then
return true
end
end


return false
return initialRom .. vowelRoman .. finalRom, math.max(1, pos - startPos)
end
end


local function romanizeWord(word)
local function romanizeWord(word)
local c = chars(word)
if word == '' then
c = removeSilent(c)
return ''
end
 
-- Manual markers:
-- < > = force space
-- <-> = force hyphen
word = gsub(word, '< >', ' ')
word = gsub(word, '<->', '-')


local syllables = {}
local output = {}
local pos = 1
local pos = 1
local safety = 0
local n = len(word)


while pos <= #c and safety < 1000 do
while pos <= n do
safety = safety + 1
local c = sub(word, pos, pos)


if isConsonant(c[pos]) or isFrontVowel(c[pos]) then
if c == '<' then
local syllable, nextPos = parseSyllable(c, pos)
local close = find(word, '>', pos + 1, true)
 
if close then
if syllable then
pos = close + 1
table.insert(syllables, syllable)
 
if nextPos <= pos then
pos = pos + 1
else
pos = nextPos
end
else
else
-- Fail safely rather than looping forever.
table.insert(output, c)
pos = pos + 1
pos = pos + 1
end
end
elseif not isThai(c) then
table.insert(output, c)
pos = pos + 1
else
else
-- Thai punctuation/marks that aren't part of a syllable.
local roman, consumed = romanizeSyllable(word, pos)
pos = pos + 1
table.insert(output, roman)
pos = pos + consumed
end
end
end
local output = {}
for i, syllable in ipairs(syllables) do
if shouldHyphen(syllables[i - 1], syllable) then
table.insert(output, '-')
end
table.insert(
output,
(syllable.initial or '') ..
(syllable.vowel or '') ..
(syllable.coda or '')
)
end
end


Line 626: Line 424:
end
end


-- Parse the text while treating <> and <-> as hard boundaries.
local function capitalize(str, sentence)
--
local chars = mw.text.split(str, '')
-- <>  = literal space
local shouldCap = true
-- <-> = literal hyphen
--
-- Because each Thai section is romanized independently, automatic
-- hyphenation can never cross one of these markers.
local function romanizeThaiText(text)
local result = {}
local pos = 1
local length = mw.ustring.len(text)


while pos <= length do
for i, c in ipairs(chars) do
-- Manual hyphen.
if match(c, '%a') then
if mw.ustring.sub(text, pos, pos + 2) == '<->' then
if shouldCap then
table.insert(result, '-')
chars[i] = U.upper(c)
pos = pos + 3
shouldCap = false
 
elseif sentence then
-- Manual space.
shouldCap = false
elseif mw.ustring.sub(text, pos, pos + 1) == '<>' then
end
table.insert(result, ' ')
elseif c == ' ' then
pos = pos + 2
if sentence then
 
shouldCap = true
-- Thai run.
else
elseif isThai(mw.ustring.sub(text, pos, pos)) then
shouldCap = true
local start = pos
 
while pos <= length do
local character = mw.ustring.sub(text, pos, pos)
 
if not isThai(character) then
break
end
 
-- Stop before a manual control marker.
if mw.ustring.sub(text, pos, pos + 2) == '<->' then
break
end
 
if mw.ustring.sub(text, pos, pos + 1) == '<>' then
break
end
 
pos = pos + 1
end
end
 
elseif match(c, '[%.!?]') then
local word = mw.ustring.sub(text, start, pos - 1)
shouldCap = true
 
table.insert(result, romanizeWord(word))
 
-- Everything else is preserved.
else
table.insert(
result,
mw.ustring.sub(text, pos, pos)
)
 
pos = pos + 1
end
end
 
return table.concat(result)
end
 
local function convertThaiDigits(text)
local digits = {
['๐'] = '0',
['๑'] = '1',
['๒'] = '2',
['๓'] = '3',
['๔'] = '4',
['๕'] = '5',
['๖'] = '6',
['๗'] = '7',
['๘'] = '8',
['๙'] = '9'
}
 
for thai, latin in pairs(digits) do
text = mw.ustring.gsub(text, thai, latin)
end
 
return text
end
 
local function hasThai(text)
return mw.ustring.find(text, THAI) ~= nil
end
 
local function validateRomanization(text)
-- Never allow Thai characters to leak into the final result.
if hasThai(text) then
return false
end
 
return true
end
 
local function capitalizeWords(text)
return mw.ustring.gsub(
text,
'(%a)([%a]*)',
function(first, rest)
return mw.ustring.upper(first) .. rest
end
end
)
end
local function capitalizeSentence(text)
local prefix, first = mw.ustring.match(
text,
'^([%s%p]*)(%a)'
)
if not first then
return text
end
end


return prefix ..
return table.concat(chars)
mw.ustring.upper(first) ..
mw.ustring.sub(text, mw.ustring.len(prefix) + 2)
end
 
function p.romanize(text)
if not text or mw.text.trim(text) == '' then
return ''
end
 
-- Do not automatically romanize Latin-only text.
if not hasThai(text) then
return ''
end
 
text = convertThaiDigits(text)
 
local result = romanizeThaiText(text)
 
result = mw.ustring.gsub(result, '%s+', ' ')
result = mw.text.trim(result)
 
if not validateRomanization(result) then
return ''
end
 
return result
end
end


function p.main(frame)
function p.main(frame)
local args = arguments.getArgs(frame, {
local args = require('Module:Arguments').getArgs(frame, {
parentFirst = true,
parentFirst = true,
wrappers = {'Template:Th-rm'}
wrappers = {'Template:Th-rm'}
})
})


local text = args[1]
if not args[1] or args[1] == '' then
 
if not text or mw.text.trim(text) == '' then
return ''
return ''
end
end


if not hasThai(text) then
local str = clean(args[1])
 
-- Don't romanize text which contains no Thai script.
if not match(str, '[ก-๛]') then
return ''
return ''
end
end


local result = p.romanize(text)
str = applyOrthographicExceptions(str)


if result == '' then
local result = romanizeWord(str)
return ''
end


if args.capi then
if args.capi then
result = capitalizeWords(result)
result = capitalize(result, false)
elseif args.sent then
result = capitalize(result, true)
end
end


if args.sent then
return result
result = capitalizeSentence(result)
end
 
-- Automatically generated romanizations get a Tt warning.
return tt._main({
[1] = result,
[2] = AUTO_TOOLTIP,
['class'] = args.class
})
end
end


return p
return p
Please note that all contributions to The Petit Planet Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Petit Planet Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template
Below are commonly used wikitext from MediaWiki:Edittools. Click on any to insert them in the edit box.
File Pages==Summary====Licensing=={{Fairuse}}{{File|}}
Dynamic Page List¦²«»²{¦}²«»«/»«!----»
Array in DPL¹^2{}^2^2{¹}^2
Parser Functions{{#if:||}}
{{#ifeq:|||}}
{{#expr:}}
{{#switch:||#default=}}
{{#replace:||}}
{{#titleparts:}}
{{#tag:|}}
Markup{{}}|[][[]][[Category:]]#REDIRECT [[]] [[Category:Redirect Pages]]<code></code><includeonly></includeonly><noinclude></noinclude><nowiki></nowiki><!----><br>§
Notices{{Stub|}}{{Stub Dialogue}}{{Upcoming}}{{Under Construction}}{{Placeholder|}}
Magic Words{{!}}{{formatnum:}}{{lc:}}{{uc:}}{{PAGENAME}}{{FULLPAGENAME}}{{ROOTPAGENAME}}{{BASEPAGENAME}}{{SUBPAGENAME}}{{DISPLAYTITLE:|noreplace}}__TOC____NOTOC____EXPECTUNUSEDCATEGORY____HIDDENCAT__
HTML Entities&mdash;&nbsp;&comma;&shy;