Editing Module:Th-rm
From The Petit Planet Wiki
More actions
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 | local U = mw.ustring | ||
local | local gsub = U.gsub | ||
local find = U.find | |||
local sub = U.sub | |||
local match = U.match | |||
local len = U.len | |||
local | local INITIAL = { | ||
['ก'] = 'k', | ['ก'] = 'k', | ||
['ข'] = 'kh', | ['ข'] = 'kh', ['ฃ'] = 'kh', ['ค'] = 'kh', ['ฅ'] = 'kh', ['ฆ'] = 'kh', | ||
['ง'] = 'ng', | ['ง'] = 'ng', | ||
['จ'] = 'ch', | ['จ'] = 'ch', ['ฉ'] = 'ch', ['ช'] = 'ch', | ||
['ซ'] = 's', | ['ซ'] = 's', | ||
['ฌ'] = 'ch', | ['ฌ'] = 'ch', | ||
| Line 25: | Line 18: | ||
['ฎ'] = 'd', | ['ฎ'] = 'd', | ||
['ฏ'] = 't', | ['ฏ'] = 't', | ||
['ฐ'] = 'th', | ['ฐ'] = 'th', ['ฑ'] = 'th', ['ฒ'] = 'th', | ||
['ณ'] = 'n', | ['ณ'] = 'n', | ||
['ด'] = 'd', | ['ด'] = 'd', | ||
['ต'] = 't', | ['ต'] = 't', | ||
['ถ'] = 'th', | ['ถ'] = 'th', ['ท'] = 'th', ['ธ'] = 'th', | ||
['น'] = 'n', | ['น'] = 'n', | ||
['บ'] = 'b', | ['บ'] = 'b', | ||
| Line 47: | Line 36: | ||
['ล'] = 'l', | ['ล'] = 'l', | ||
['ว'] = 'w', | ['ว'] = 'w', | ||
['ศ'] = 's', | ['ศ'] = 's', ['ษ'] = 's', ['ส'] = 's', | ||
['ห'] = 'h', | ['ห'] = 'h', | ||
['ฬ'] = 'l', | ['ฬ'] = 'l', | ||
['ฮ'] = 'h | ['ฮ'] = 'h' | ||
} | } | ||
local FINAL = { | |||
local | |||
['ก'] = 'k', | ['ก'] = 'k', | ||
['ข'] = 'k', | ['ข'] = 'k', ['ฃ'] = 'k', ['ค'] = 'k', ['ฅ'] = 'k', ['ฆ'] = 'k', | ||
['ง'] = 'ng', | |||
['จ'] = 't', ['ฉ'] = 't', ['ช'] = 't', ['ฌ'] = '', | |||
['จ'] = 't', | |||
['ซ'] = 't', | ['ซ'] = 't', | ||
[' | ['ญ'] = 'n', | ||
['ฎ'] = 't', | ['ฎ'] = 't', ['ฏ'] = 't', | ||
['ฐ'] = 't', ['ฑ'] = 't', ['ฒ'] = 't', | |||
['ฐ'] = 't', | ['ณ'] = 'n', | ||
[' | |||
['ด'] = 't', | ['ด'] = 't', | ||
['ต'] = 't', | ['ต'] = 't', | ||
['ถ'] = 't', | ['ถ'] = 't', ['ท'] = 't', ['ธ'] = 't', | ||
['น'] = 'n', | |||
[' | |||
['บ'] = 'p', | ['บ'] = 'p', | ||
['ป'] = 'p', | ['ป'] = 'p', | ||
['ผ'] = ' | ['ผ'] = '', ['ฝ'] = '', | ||
['พ'] = 'p', ['ฟ'] = 'p', ['ภ'] = 'p', | |||
['พ'] = 'p', | ['ม'] = 'm', | ||
['ย'] = '', | |||
[' | |||
[' | |||
['ร'] = 'n', | ['ร'] = 'n', | ||
['ล'] = 'n', | ['ล'] = 'n', | ||
['ว'] = '', | |||
['ศ'] = 't', ['ษ'] = 't', ['ส'] = 't', | |||
['ห'] = '', | |||
['ฬ'] = 'n', | ['ฬ'] = 'n', | ||
['ฮ'] = '' | |||
[' | |||
} | } | ||
-- | -- Vowel patterns are tested longest-first. | ||
local | local VOWELS = { | ||
{ 'เ' , 'ะ', 'e' }, | |||
{ 'เ' , '็', 'e' }, | |||
{ 'เ' , '', 'e' }, | |||
{ 'แ' , 'ะ', 'ae' }, | |||
{ 'แ' , '', 'ae' }, | |||
{ 'โ' , 'ะ', 'o' }, | |||
{ 'โ' , '', 'o' }, | |||
{ 'เ' , 'าะ', 'o' }, | |||
{ '' , 'อ', 'o' }, | |||
{ 'เ' , 'อะ', 'oe' }, | |||
{ 'เ' , 'ิ', 'oe' }, | |||
{ 'เ' , 'อ', 'oe' }, | |||
{ 'เ' , 'ียะ', 'ia' }, | |||
{ 'เ' , 'ีย', 'ia' }, | |||
{ 'เ' , 'ือะ', 'uea' }, | |||
{ 'เ' , 'ือ', 'uea' }, | |||
{ '' , 'ัวะ', 'ua' }, | |||
{ '' , 'ัว', 'ua' }, | |||
{ '' , 'ว', 'ua' }, | |||
{ 'ใ', '', 'ai' }, | |||
{ 'ไ', '', 'ai' }, | |||
{ '' , 'ัย', 'ai' }, | |||
{ 'ไ', 'ย', 'ai' }, | |||
{ '' , 'าย', 'ai' }, | |||
{ 'เ', 'า', 'ao' }, | |||
{ '' , 'าว', 'ao' }, | |||
{ '' , 'ุย', 'ui' }, | |||
{ 'โ', 'ย', 'oi' }, | |||
{ '' , 'อย', 'oi' }, | |||
{ 'เ', 'ย', 'oei' }, | |||
{ 'เ', 'ือย', 'ueai' }, | |||
{ '' , 'วย', 'uai' }, | |||
{ '' , 'ิว', 'io' }, | |||
{ 'เ', '็ว', 'eo' }, | |||
{ 'เ', 'ว', 'eo' }, | |||
{ 'แ', '็ว', 'aeo' }, | |||
{ 'แ', 'ว', 'aeo' }, | |||
{ 'เ', 'ียว', 'iao' }, | |||
{ '' , 'ะ', 'a' }, | |||
{ '' , 'ั', 'a' }, | |||
{ '' , 'า', 'a' }, | |||
{ '' , 'ำ', 'am' }, | |||
{ '' , 'ิ', 'i' }, | |||
{ '' , 'ี', 'i' }, | |||
} | |||
{ '' , 'ึ', 'ue' }, | |||
{ '' , 'ื', 'ue' }, | |||
{ '' , 'ือ', 'ue' }, | |||
' | |||
' | |||
{ '' , 'ุ', 'u' }, | |||
{ '' , 'ู', 'u' }, | |||
{ '' , 'รร', 'a' } | |||
} | } | ||
local function isConsonant(c) | local function isConsonant(c) | ||
return c and | return c and INITIAL[c] ~= nil | ||
end | end | ||
local function isThai(c) | local function isThai(c) | ||
return c and | return c and match(c, '[ก-๛]') ~= nil | ||
end | end | ||
local function | local function isToneMark(c) | ||
return c | return c and match(c, '[่้๊๋]') ~= nil | ||
end | end | ||
local function | local function isSilentMark(c) | ||
return c == '์' | |||
end | |||
return | local function clean(str) | ||
str = mw.text.unstrip(str or '') | |||
str = gsub(str, '<br%s*/?>', ' ') | |||
str = gsub(str, '<[^>]+>', '') | |||
return str | |||
end | end | ||
local function | local function applyOrthographicExceptions(str) | ||
-- Silent letters marked with ์. | |||
-- Remove the marked letter and its ์ marker. | |||
str = gsub(str, '([ก-ฮ])์', '') | |||
-- Tone marks have no RTGS representation. | |||
str = gsub(str, '[่้๊๋]', '') | |||
-- ฤ | |||
str = gsub(str, 'ฤกษ์', 'roe') | |||
str = gsub(str, 'ฤิ', 'ri') | |||
str = gsub(str, 'ฤ', 'rue') | |||
str = gsub(str, 'ฤๅ', 'rue') | |||
-- ฦ / ฦๅ | |||
str = gsub(str, 'ฦๅ', 'lue') | |||
str = gsub(str, 'ฦ', 'lue') | |||
return | return str | ||
end | end | ||
local function getVowel( | local function getVowel(str, pos) | ||
local remaining = | local remaining = sub(str, pos, -1) | ||
-- Explicit special vowel patterns. | |||
local patterns = { | |||
{ 'เ', 'ื', 'อ', 'ย', 'ueai' }, | |||
{ 'เ', 'ี', 'ย', 'ว', 'iao' }, | |||
{ 'เ', 'ี', 'ย', 'ะ', 'ia' }, | |||
{ 'เ', 'ี', 'ย', '', 'ia' }, | |||
{ 'เ', 'ื', 'อ', 'ะ', 'uea' }, | |||
{ 'เ', 'ื', 'อ', '', 'uea' }, | |||
{ 'เ', '็', 'ว', '', 'eo' }, | |||
{ 'เ', 'ว', '', '', 'eo' }, | |||
{ 'แ', '็', 'ว', '', 'aeo' }, | |||
{ 'แ', 'ว', '', '', 'aeo' }, | |||
{ 'โ', 'ย', '', '', 'oi' }, | |||
{ '', 'อ', 'ย', '', 'oi' }, | |||
{ 'เ', 'ย', '', '', 'oei' }, | |||
{ '', 'ว', 'ย', '', 'uai' }, | |||
{ '', 'ุ', 'ย', '', 'ui' }, | |||
{ '', 'ิ', 'ว', '', 'io' }, | |||
{ 'เ', 'า', '', '', 'ao' }, | |||
{ '', 'า', 'ว', '', 'ao' }, | |||
{ '', 'ั', 'ว', 'ะ', 'ua' }, | |||
{ '', 'ั', 'ว', '', 'ua' }, | |||
{ '', 'ว', '', '', 'ua' }, | |||
{ 'ใ', '', '', '', 'ai' }, | |||
{ 'ไ', '', '', '', 'ai' }, | |||
{ '', 'ั', 'ย', '', 'ai' }, | |||
{ 'ไ', 'ย', '', '', 'ai' }, | |||
{ '', 'า', 'ย', '', 'ai' }, | |||
{ 'เ', 'า', 'ะ', '', 'ao' }, | |||
{ 'โ', 'ะ', '', '', 'o' }, | |||
{ 'เ', 'า', '', '', 'ao' }, | |||
{ 'เ', 'าะ', '', '', 'o' }, | |||
{ 'เ', 'อ', '', '', 'oe' }, | |||
{ 'เ', 'ิ', '', '', 'oe' }, | |||
{ 'เ', 'อะ', '', '', 'oe' }, | |||
{ 'แ', 'ะ', '', '', 'ae' }, | |||
{ 'แ', '', '', '', 'ae' }, | |||
{ 'เ', 'ะ', '', '', 'e' }, | |||
{ 'เ', '็', '', '', 'e' }, | |||
{ 'เ', '', '', '', 'e' }, | |||
{ 'โ', '', '', '', 'o' }, | |||
{ '', 'ำ', '', '', 'am' }, | |||
{ '', 'ะ', '', '', 'a' }, | |||
{ '', 'ั', '', '', 'a' }, | |||
{ '', 'า', '', '', 'a' }, | |||
{ '', 'ิ', '', '', 'i' }, | |||
{ '', 'ี', '', '', 'i' }, | |||
{ '', 'ึ', '', '', 'ue' }, | |||
{ '', 'ือ', '', '', 'ue' }, | |||
{ '', 'ื', '', '', 'ue' }, | |||
{ '', 'ุ', '', '', 'u' }, | |||
{ '', 'ู', '', '', 'u' }, | |||
{ '', 'อ', '', '', 'o' } | |||
} | |||
for _, v in ipairs(patterns) do | |||
local a, b, c, d, roman = v | |||
local pattern = a .. b .. c .. d | |||
if pattern ~= '' and sub(remaining, 1, len(pattern)) == pattern then | |||
return roman, len(pattern) | |||
end | |||
end | end | ||
-- | -- Implied a. | ||
return 'a', 0 | |||
end | |||
local function nextVowelPosition(str, pos) | |||
local i = pos | |||
while i <= len(str) do | |||
local c = sub(str, i, i) | |||
if c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ' then | |||
end | return i | ||
end | |||
if match(c, '[ะาิีึืุูัำอ]') then | |||
return i | |||
end | |||
i = i + 1 | |||
end | end | ||
return nil | |||
return | |||
end | end | ||
local function | local function romanizeSyllable(str, startPos) | ||
local pos = | local pos = startPos | ||
local n = len(str) | |||
-- Preposed vowel. | |||
local preVowel = '' | |||
local preLen = 0 | |||
local c = sub(str, pos, pos) | |||
if c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ' then | |||
preVowel = c | |||
preLen = 1 | |||
pos = pos + 1 | pos = pos + 1 | ||
end | end | ||
local | -- Initial consonant. | ||
local initial = sub(str, pos, pos) | |||
if not isConsonant(initial) then | |||
-- Non-Thai character. | |||
return initial, 1 | |||
if | |||
return | |||
end | end | ||
pos = pos + 1 | |||
local initialRom = INITIAL[initial] or '' | |||
-- ห- exception. | |||
if initial == 'ห' then | |||
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 | |||
-- Consonant clusters where ร is not represented. | |||
if (initial == 'จ' or initial == 'ซ' or initial == 'ศ' or initial == 'ส') | |||
and sub(str, pos, pos) == 'ร' then | |||
initialRom = INITIAL[initial] | |||
pos = pos + 1 | |||
end | |||
-- Find the vowel from the current position, including preposed vowels. | |||
local vowelStart = startPos + preLen + 1 | |||
local vowelRoman | |||
local vowelLen | |||
if preLen > 0 then | |||
vowelRoman, vowelLen = getVowel(str, startPos + 1) | |||
else | else | ||
vowelRoman, vowelLen = getVowel(str, pos) | |||
end | end | ||
-- | -- If the vowel was explicitly consumed by getVowel, advance. | ||
if | if vowelLen > 0 then | ||
if | if preLen > 0 then | ||
pos = startPos + preLen + 1 + vowelLen | |||
else | else | ||
pos = pos + vowelLen | |||
end | end | ||
end | end | ||
-- Collect possible final consonant. | |||
local final = sub(str, pos, pos) | |||
local finalRom = '' | |||
if isConsonant(final) then | |||
local after = sub(str, pos + 1, pos + 1) | |||
-- A consonant followed by a vowel-starting syllable is normally | |||
-- | -- treated as the next syllable's initial rather than this syllable's final. | ||
-- | local nextIsVowel = after and ( | ||
match(after, '[ะาิีึืุูัำอ]') or | |||
match(after, '[เแโใไ]') | |||
) | |||
if not nextIsVowel then | |||
finalRom = FINAL[final] or '' | |||
pos = pos + 1 | |||
-- -ร following another final consonant is silent in RTGS. | |||
if final == 'ร' then | |||
finalRom = 'n' | |||
end | |||
end | |||
end | |||
end | end | ||
-- | -- ทร- exception. | ||
if | if initial == 'ท' and sub(str, pos, pos) == 'ร' then | ||
initialRom = 's' | |||
pos = pos + 1 | |||
end | end | ||
return | return initialRom .. vowelRoman .. finalRom, math.max(1, pos - startPos) | ||
end | end | ||
local function romanizeWord(word) | local function romanizeWord(word) | ||
if word == '' then | |||
return '' | |||
end | |||
-- Manual markers: | |||
-- < > = force space | |||
-- <-> = force hyphen | |||
word = gsub(word, '< >', ' ') | |||
word = gsub(word, '<->', '-') | |||
local | local output = {} | ||
local pos = 1 | local pos = 1 | ||
local | local n = len(word) | ||
while pos <= | while pos <= n do | ||
local c = sub(word, pos, pos) | |||
if | if c == '<' then | ||
local | local close = find(word, '>', pos + 1, true) | ||
if close then | |||
if | pos = close + 1 | ||
else | else | ||
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 | ||
local roman, consumed = romanizeSyllable(word, pos) | |||
pos = pos + | table.insert(output, roman) | ||
pos = pos + consumed | |||
end | end | ||
end | end | ||
| Line 626: | Line 424: | ||
end | end | ||
local function capitalize(str, sentence) | |||
local chars = mw.text.split(str, '') | |||
local shouldCap = true | |||
local function | |||
local | |||
for i, c in ipairs(chars) do | |||
if match(c, '%a') then | |||
if | if shouldCap then | ||
chars[i] = U.upper(c) | |||
shouldCap = false | |||
elseif sentence then | |||
shouldCap = false | |||
end | |||
elseif c == ' ' then | |||
if sentence then | |||
shouldCap = true | |||
else | |||
shouldCap = true | |||
end | end | ||
elseif match(c, '[%.!?]') then | |||
shouldCap = true | |||
end | end | ||
end | end | ||
return | return table.concat(chars) | ||
end | end | ||
function p.main(frame) | function p.main(frame) | ||
local args = | local args = require('Module:Arguments').getArgs(frame, { | ||
parentFirst = true, | parentFirst = true, | ||
wrappers = {'Template:Th-rm'} | wrappers = {'Template:Th-rm'} | ||
}) | }) | ||
if not args[1] or args[1] == '' then | |||
return '' | return '' | ||
end | end | ||
if not | local str = clean(args[1]) | ||
-- Don't romanize text which contains no Thai script. | |||
if not match(str, '[ก-๛]') then | |||
return '' | return '' | ||
end | end | ||
str = applyOrthographicExceptions(str) | |||
local result = romanizeWord(str) | |||
if args.capi then | if args.capi then | ||
result = | result = capitalize(result, false) | ||
elseif args.sent then | |||
result = capitalize(result, true) | |||
end | end | ||
return result | |||
return | |||
end | end | ||
return p | return p | ||