Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Special pages
Random page
Wiki Discord
Contents
Neighbors
Galaxy
> Hexia
> Norvan
> Pashah
> Taffeh
Creatures
> Insects
> Fishes
> Shore-Dwellers
Items
> Dishes
> Furniture
Game Systems
> Dress Up
> Luca Arbor
> Loomix Footprints
> Loomix Vehicle Services
> Loomix Homes
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Editing
Module
:
Th-rm
Module
Discussion
English
Read
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit source
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Once you make an edit, a temporary account will be created for you.
Learn more
.
Log in
or
create an account
to continue receiving notifications after this account expires, and to access other features.
Anti-spam check. Do
not
fill this in!
local p = {} local arguments = require('Module:Arguments') local tt = require('Module:Tt') local AUTO_TOOLTIP = 'This romanization was generated automatically. Please add a user-curated romanization as soon as possible.' local THAI = '[ก-๛]' -- Initial consonants. local consonants = { ['ก'] = 'k', ['ข'] = 'kh', ['ฃ'] = 'kh', ['ค'] = 'kh', ['ฅ'] = 'kh', ['ฆ'] = 'kh', ['ง'] = 'ng', ['จ'] = 'ch', ['ฉ'] = 'ch', ['ช'] = 'ch', ['ซ'] = 's', ['ฌ'] = 'ch', ['ญ'] = 'y', ['ฎ'] = 'd', ['ฏ'] = 't', ['ฐ'] = 'th', ['ฑ'] = 'th', ['ฒ'] = 'th', ['ณ'] = 'n', ['ด'] = 'd', ['ต'] = 't', ['ถ'] = 'th', ['ท'] = 'th', ['ธ'] = 'th', ['น'] = 'n', ['บ'] = 'b', ['ป'] = 'p', ['ผ'] = 'ph', ['ฝ'] = 'f', ['พ'] = 'ph', ['ฟ'] = 'f', ['ภ'] = 'ph', ['ม'] = 'm', ['ย'] = 'y', ['ร'] = 'r', ['ล'] = 'l', ['ว'] = 'w', ['ศ'] = 's', ['ษ'] = 's', ['ส'] = 's', ['ห'] = 'h', ['ฬ'] = 'l', ['ฮ'] = 'h', ['อ'] = '' } -- Final consonants. local finals = { ['ก'] = 'k', ['ข'] = 'k', ['ฃ'] = 'k', ['ค'] = 'k', ['ฅ'] = 'k', ['ฆ'] = 'k', ['จ'] = 't', ['ฉ'] = 't', ['ช'] = 't', ['ซ'] = 't', ['ฌ'] = 't', ['ฎ'] = 't', ['ฏ'] = 't', ['ฐ'] = 't', ['ฑ'] = 't', ['ฒ'] = 't', ['ด'] = 't', ['ต'] = 't', ['ถ'] = 't', ['ท'] = 't', ['ธ'] = 't', ['ศ'] = 't', ['ษ'] = 't', ['ส'] = 't', ['บ'] = 'p', ['ป'] = 'p', ['ผ'] = 'p', ['ฝ'] = 'p', ['พ'] = 'p', ['ฟ'] = 'p', ['ภ'] = 'p', ['ง'] = 'ng', ['ญ'] = 'n', ['ณ'] = 'n', ['น'] = 'n', ['ร'] = 'n', ['ล'] = 'n', ['ฬ'] = 'n', ['ม'] = 'm' } -- Vowels. local vowels = { ['เียะ'] = 'ia', ['เีย'] = 'ia', ['เือะ'] = 'uea', ['เือ'] = 'uea', ['เือย'] = 'ueai', ['เียว'] = 'iao', ['ัวะ'] = 'ua', ['ัว'] = 'ua', ['เิ็ย'] = 'oei', ['เิย'] = 'oei', ['เอย'] = 'oei', ['็อย'] = 'oi', ['อย'] = 'oi', ['ุย'] = 'ui', ['วย'] = 'uai', ['ัย'] = 'ai', ['ไย'] = 'ai', ['าย'] = 'ai', ['ใ'] = 'ai', ['ไ'] = 'ai', ['เ็ว'] = 'eo', ['แ็ว'] = 'aeo', ['เา'] = 'ao', ['าว'] = 'ao', ['แว'] = 'aeo', ['เว'] = 'eo', ['ิว'] = 'io', ['ีว'] = 'io', ['ำ'] = 'am', ['ือ'] = 'ue', ['ื'] = 'ue', ['ึ'] = 'ue', ['ิ'] = 'i', ['ี'] = 'i', ['ุ'] = 'u', ['ู'] = 'u', ['เ็'] = 'e', ['เ'] = 'e', ['แ็'] = 'ae', ['แ'] = 'ae', ['โะ'] = 'o', ['โ'] = 'o', ['เาะ'] = 'o', ['อ'] = 'o', ['เอะ'] = 'oe', ['เอ'] = 'oe', ['เะ'] = 'e', ['ะ'] = 'a', ['ั'] = 'a', ['า'] = 'a' } -- Longest vowel forms must be checked first. local vowel_order = { 'เือย', 'เียว', 'เือะ', 'เียะ', 'เีย', 'เือ', 'ัวะ', 'ัว', 'เิ็ย', 'เิย', '็อย', 'เ็ว', 'แ็ว', 'เอย', 'เา', 'าว', 'เว', 'แว', 'าย', 'ไย', 'ัย', 'ุย', 'วย', 'อย', 'ำ', 'ิว', 'ีว', 'ิ', 'ี', 'ึ', 'ื', 'ุ', 'ู', 'เ็', 'แ็', 'เาะ', 'เอะ', 'เอ', 'เะ', 'ะ', 'ั', 'า', 'เ', 'แ', 'โ', 'อ', 'ใ', 'ไ' } local consonant_set = {} for c in pairs(consonants) do 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) return c and consonant_set[c] == true end local function isThai(c) return c and mw.ustring.find(c, THAI) ~= nil end local function isFrontVowel(c) return c == 'เ' or c == 'แ' or c == 'โ' or c == 'ใ' or c == 'ไ' end local function skipMarks(c, pos) while c[pos] and ( c[pos] == '็' or c[pos] == '่' or c[pos] == '้' or c[pos] == '๊' or c[pos] == '๋' or c[pos] == 'ํ' or c[pos] == '๎' ) do pos = pos + 1 end return pos end local function removeSilent(chars_) local result = {} local i = 1 while chars_[i] do if chars_[i] == '์' then -- ์ makes the following consonant(s) silent. i = i + 1 while chars_[i] and ( isConsonant(chars_[i]) or chars_[i] == '็' or chars_[i] == '่' or chars_[i] == '้' or chars_[i] == '๊' or chars_[i] == '๋' ) do i = i + 1 end else table.insert(result, chars_[i]) i = i + 1 end end return result end local function getVowel(c, pos) local remaining = table.concat(c, '', pos) 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 end local function getInitial(c, pos) local c1 = c[pos] if not isConsonant(c1) then return '', pos end local c2 = c[pos + 1] -- ห is not pronounced in หง หน หม หย หร หล หว หญ. if c1 == 'ห' and c2 and h_silent_clusters[c1 .. c2] then return consonants[c2], pos + 2, true end -- ทร is pronounced s in the relevant Sanskrit-derived words. -- This is the broad automatic fallback; exceptions can be manually -- supplied with th_rm. if c1 == 'ท' and c2 == 'ร' then return 's', pos + 2, false end if c2 and valid_clusters[c1 .. c2] then -- ร is silent in these clusters. if r_silent_clusters[c1 .. c2] then return consonants[c1], pos + 2, false end return consonants[c1] .. consonants[c2], pos + 2, false end return consonants[c1], pos + 1, false end local function getCoda(c, pos) local current = c[pos] if not current or not isConsonant(current) then return '', pos end -- These do not act as ordinary codas here. if current == 'อ' or current == 'ห' or current == 'ฮ' then return '', pos end -- ย and ว are generally part of the vowel/diphthong. if current == 'ย' or current == 'ว' then return '', pos end if finals[current] then return finals[current], pos + 1 end return '', pos + 1 end local function startsNextSyllable(c, pos) if not c[pos] or not isConsonant(c[pos]) then return false end if isFrontVowel(c[pos + 1]) then return true end local _, vowel = getVowel(c, pos + 1) return vowel ~= nil end local function parseSyllable(c, start) local pos = start if not c[pos] then return nil, pos end local initial = '' local cluster = false -- Preposed vowels. local front = '' if isFrontVowel(c[pos]) then front = c[pos] pos = pos + 1 end local initialPos = pos initial, pos, _, cluster = getInitial(c, pos) if initial == '' and not isConsonant(c[initialPos]) then return nil, start + 1 end local vowel local vowelForm 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 vowel = 'oe' vowelForm = 'เอ' pos = pos + 1 elseif front == 'เ' and c[pos] == 'า' then vowel = 'ao' vowelForm = 'เา' pos = pos + 1 elseif front == 'เ' and c[pos] == '็' then vowel = 'e' vowelForm = 'เ็' pos = pos + 1 elseif front == 'แ' and c[pos] == '็' then vowel = 'ae' 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 vowelForm, vowel = getVowel(c, pos) if vowelForm then pos = pos + mw.ustring.len(vowelForm) end end -- Implied vowels. if not vowel then if c[pos] and isConsonant(c[pos]) then if startsNextSyllable(c, pos) then vowel = 'a' else vowel = 'o' end else vowel = 'a' end end pos = skipMarks(c, pos) -- Final consonant. local coda = '' local codaPos = pos if c[pos] and isConsonant(c[pos]) then -- If another consonant begins the next syllable, don't consume -- it as a coda. if startsNextSyllable(c, pos) then coda = '' else coda, codaPos = getCoda(c, pos) end end pos = codaPos pos = skipMarks(c, pos) return { initial = initial, vowel = vowel, coda = coda, next = pos }, pos end local function shouldHyphen(previous, current) if not previous or not current then return false end -- Before a succeeding syllable beginning with a vowel. if current.initial == '' and current.vowel ~= '' then return true end -- Before ng when the preceding syllable ends in a vowel. if previous.coda == '' and current.initial == 'ng' then return true end return false end local function romanizeWord(word) local c = chars(word) c = removeSilent(c) local syllables = {} local pos = 1 local safety = 0 while pos <= #c and safety < 1000 do safety = safety + 1 if isConsonant(c[pos]) or isFrontVowel(c[pos]) then local syllable, nextPos = parseSyllable(c, pos) if syllable then table.insert(syllables, syllable) if nextPos <= pos then pos = pos + 1 else pos = nextPos end else -- Fail safely rather than looping forever. pos = pos + 1 end else -- Thai punctuation/marks that aren't part of a syllable. pos = pos + 1 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 return table.concat(output) end -- Parse the text while treating <> and <-> as hard boundaries. -- -- <> = literal space -- <-> = 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 -- Manual hyphen. if mw.ustring.sub(text, pos, pos + 2) == '<->' then table.insert(result, '-') pos = pos + 3 -- Manual space. elseif mw.ustring.sub(text, pos, pos + 1) == '<>' then table.insert(result, ' ') pos = pos + 2 -- Thai run. elseif isThai(mw.ustring.sub(text, pos, pos)) then 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 local word = mw.ustring.sub(text, start, pos - 1) 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 local function capitalizeSentence(text) local prefix, first = mw.ustring.match( text, '^([%s%p]*)(%a)' ) if not first then return text end return prefix .. 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 function p.main(frame) local args = arguments.getArgs(frame, { parentFirst = true, wrappers = {'Template:Th-rm'} }) local text = args[1] if not text or mw.text.trim(text) == '' then return '' end if not hasThai(text) then return '' end local result = p.romanize(text) if result == '' then return '' end if args.capi then result = capitalizeWords(result) end if args.sent then result = capitalizeSentence(result) end -- Automatically generated romanizations get a Tt warning. return tt._main({ [1] = result, [2] = AUTO_TOOLTIP, ['class'] = args.class }) end return p
Summary:
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:||}}
{{#if:<condition>|<result if true>|<result if false>}}
{{#ifeq:|||}}
{{#ifeq:<text1>|<text2>|<result if text1=text2>|<result if text1≠text2>}}
{{#expr:}}
{{#expr:<mathematical expression>}}
{{#switch:||#default=}}
{{#switch:<text1>|<text2>=<result if text1=text2>|<text3>=<result if text1=text3>|#default=<result if no valid match>}}
{{#replace:||}}
{{#replace:<text1>|<plain text to find in text1>|<plain text to insert in place of the text found>}}
{{#titleparts:}}
{{#replace:<page name>}}
{{#tag:|}}
{{#tag:<name of html tag>|<content inside html 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
—
,
­
Pages included on this page:
Template:Documentation/Header
(
edit
)
Template:Documentation/styles.css
(
edit
)
Template:T
(
edit
)
Template:TOC Right
(
edit
)
Module:Arguments
(
edit
)
Module:Arguments/i18n
(
edit
)
Module:Common/i18n
(
edit
)
Module:Config
(
edit
)
Module:Documentation
(
edit
)
Module:Documentation/config
(
edit
)
Module:Documentation/i18n
(
edit
)
Module:Entrypoint
(
edit
)
Module:Exists
(
edit
)
Module:Fallbacklist
(
edit
)
Module:Feature
(
edit
)
Module:Formatting
(
edit
)
Module:I18n
(
edit
)
Module:Languages
(
edit
)
Module:TableTools
(
edit
)
Module:Th-rm/doc
(
edit
)
Module:Yesno
(
edit
)
This page is a member of 2 hidden categories:
Category:Pages using DynamicPageList4 parser function
Category:Pages using DynamicPageList4
Search
Search
Editing
Module
:
Th-rm
Add topic