text: User talk:Sylveon Casino 4001

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: User talk:Sylveon Casino 4001


text:
Sylheti/Transliteration

Conjuncts
Conjuncts are transliterated as they are pronounced. While the pronunciation of some conjuncts is evident by their components, others are pronounced quite differently than the spelling would suggest. These include the following:
 * ꠇ + ꠇ = ꠇ꠆ꠇ (kkô)
 * ꠇ + ꠈ = ꠇ꠆ꠈ (kkô)
 * ꠌ + ꠌ = ꠌ꠆ꠌ (ccô)
 * ꠌ + ꠍ = ꠌ꠆ꠍ (ccô)

Wiktionary Contributors
It was originally written on English Wiktionary under Creative Commons Attribution-ShareAlike License. A list of main contributors:
 * 1) Msasag
 * 2) JohnC5
 * 3) SuryaNarayanMishra

title: Sylheti/Transliteration


text:
Category:Articles containing Sylheti-language text

__HIDDENCAT__


text: Template:IPAchar

title: Template:IPAchar


text:
Module:IPA/templates

local export = {}

local m_IPA = require("Module:IPA")

local U = mw.ustring.char local syllabic = U(0x0329)

-- Used for Template:IPA. function export.IPA(frame) local parent_args = frame.getParent and frame:getParent.args or frame local compat = parent_args["lang"] local offset = compat and 0 or 1 local params = { [compat and "lang" or 1] = {required = true, default = "en"}, [1 + offset] = {list = true, allow_holes = true}, ["ref"] = {list = true, allow_holes = true}, -- Came before 'ref' but too obscure ["n"] = {list = true, allow_holes = true, alias_of = "ref"}, ["qual"] = {list = true, allow_holes = true}, ["nocount"] = {type = "boolean"}, ["sort"] = {}, }	local args = require("Module:parameters").process(parent_args, params) local lang = args[compat and "lang" or 1] lang = require("Module:languages").getByCode(lang) or require("Module:languages").err(lang, compat and "lang" or 1)

-- Special:WhatLinksHere/Template:tracking/IPA/grc if lang and lang:getCode == "grc" then require("Module:debug").track("IPA/grc") end local items = {} for i = 1, math.max(args[1 + offset].maxindex, args["ref"].maxindex, args["qual"].maxindex) do		local pron = args[1 + offset][i] local refs = args["ref"][i] if refs then refs = require("Module:references").parse_references(refs) end local qual = args["qual"][i]

if not pron then if refs or qual then local param = i == 1 and "" or "" .. i error("Specified qual" .. param .. "= or ref" .. param .. "= without corresponding pronunciation") end else if lang then require("Module:IPA/tracking").run_tracking(pron, lang) end if pron or refs or qual then table.insert(items, {pron = pron, refs = refs, qualifiers = {qual}}) end end end return m_IPA.format_IPA_full(lang, items, nil, nil, args.sort, args.nocount) end

-- Used for Template:IPAchar. function export.IPAchar(frame) local params = { [1] = {list = true, allow_holes = true}, ["ref"] = {list = true, allow_holes = true}, -- Came before 'ref' but too obscure ["n"] = {list = true, allow_holes = true, alias_of = "ref"}, ["qual"] = {list = true, allow_holes = true}, -- FIXME, remove this. ["lang"] = {}, -- This parameter is not used and does nothing, but is allowed for futureproofing. }

local args = require("Module:parameters").process(frame.getParent and frame:getParent.args or frame, params) -- Special:WhatLinksHere/Template:tracking/IPAchar/lang if args.lang then require("Module:debug").track("IPAchar/lang") end

local items = {} for i = 1, math.max(args[1].maxindex, args["ref"].maxindex, args["qual"].maxindex) do		local pron = args[1][i] local refs = args["ref"][i] if refs then refs = require("Module:references").parse_references(refs) end local qual = args["qual"][i]

if pron or refs or qual then table.insert(items, {pron = pron, refs = refs, qualifiers = {qual}}) end end

-- Format return m_IPA.format_IPA_multiple(nil, items) end

function export.XSAMPA(frame) local params = { [1] = { required = true }, }	local args = require("Module:parameters").process(frame:getParent.args, params) return m_IPA.XSAMPA_to_IPA(args[1] or "[Eg'zA:mp5=]") end

-- Used by Template:X2IPA function export.X2IPAtemplate(frame) local parent_args = frame.getParent and frame:getParent.args or frame local compat = parent_args["lang"] local offset = compat and 0 or 1

local params = { [compat and "lang" or 1] = {required = true, default = "und"}, [1 + offset] = {list = true, allow_holes = true}, ["ref"] = {list = true, allow_holes = true}, -- Came before 'ref' but too obscure ["n"] = {list = true, allow_holes = true, alias_of = "ref"}, ["qual"] = { list = true, allow_holes = true }, }	local args = require("Module:parameters").process(parent_args, params) local m_XSAMPA = require("Module:IPA/X-SAMPA") local pronunciations, refs, qualifiers, lang = args[1 + offset], args["ref"], args["qual"], args[compat and "lang" or 1] local output = {} table.insert(output, "")

return table.concat(output) end

-- Used by Template:X2IPAchar function export.X2IPAchar(frame) local params = { [1] = { list = true, allow_holes = true }, ["ref"] = {list = true, allow_holes = true}, -- Came before 'ref' but too obscure ["n"] = {list = true, allow_holes = true, alias_of = "ref"}, ["qual"] = { list = true, allow_holes = true }, -- FIXME, remove this. ["lang"] = {}, }	local args = require("Module:parameters").process(frame:getParent.args, params) -- Special:WhatLinksHere/Template:tracking/X2IPAchar/lang if args.lang then require("Module:debug").track("X2IPAchar/lang") end

local m_XSAMPA = require("Module:IPA/X-SAMPA") local pronunciations, refs, qualifiers, lang = args[1], args["ref"], args["qual"], args["lang"] local output = {} table.insert(output, "") return table.concat(output) end

-- Used by Template:x2rhymes function export.X2rhymes(frame) local parent_args = frame.getParent and frame:getParent.args or frame local compat = parent_args["lang"] local offset = compat and 0 or 1

local params = { [compat and "lang" or 1] = {required = true, default = "und"}, [1 + offset] = {required = true, list = true, allow_holes = true}, }	local args = require("Module:parameters").process(parent_args, params) local m_XSAMPA = require("Module:IPA/X-SAMPA") pronunciations, lang = args[1 + offset], args[compat and "lang" or 1] local output = {} table.insert(output, "") return table.concat(output) end

return export

title: Module:IPA/templates


text:
Module:IPA

local export = {} local m_string_utils = require("Module:string utilities") -- Module:IPA/data

local m_data = mw.loadData('Module:IPA/data') -- Module:IPA/data local m_symbols = mw.loadData('Module:IPA/data/symbols') -- Module:IPA/data/symbols local m_syllables -- Module:syllables; loaded below if needed

local sub = m_string_utils.sub local find = m_string_utils.find local gsub = m_string_utils.gsub local len = m_string_utils.len local match = m_string_utils.match local gmatch = m_string_utils.gmatch local u = mw.ustring.char

local function track(page) require("Module:debug/track")("IPA/" .. page) return true end

function export.format_IPA_full(lang, items, err, separator, sortKey, no_count) local IPA_key, key_link, err_text, prefix, IPAs, category local hasKey = m_data.langs_with_infopages local namespace = mw.title.getCurrentTitle.nsText if err then err_text = ' ' .. err .. ' '	else if hasKey[lang:getCode] then IPA_key = "Appendix:" .. lang:getCanonicalName .. " pronunciation" else IPA_key = "wikipedia:" .. lang:getCanonicalName .. " phonology" end key_link = "key" end

local prefix = "IPA(" .. ( key_link or err_text ) .. "): " IPAs = export.format_IPA_multiple(lang, items, separator, no_count) if lang and (namespace == "" or namespace == "Reconstruction") then sortKey = sortKey or (lang:makeSortKey(mw.title.getCurrentTitle.text)) sortKey = sortKey and ("|" .. sortKey) or "" category = "" else category = "" end

return prefix .. IPAs .. category end

local function determine_repr(pron) local repr_mark = {} local repr, reconstructed -- remove initial asterisk before representation marks, used on some Reconstruction pages if find(pron, "^%*") then reconstructed = true pron = sub(pron, 2) end local representation_types = { ['/'] = { right = '/', type = 'phonemic', }, ['['] = { right = ']', type = 'phonetic', }, ['⟨'] = { right = '⟩', type = 'orthographic', }, ['-'] = { type = 'rhyme' }, }	repr_mark.i, repr_mark.f, repr_mark.left, repr_mark.right = find(pron, '^(.).-(.)$') local representation_type = representation_types[repr_mark.left] if representation_type then if representation_type.right then if repr_mark.right == representation_type.right then repr = representation_type.type end else repr = representation_type.type end else repr = nil end return repr, reconstructed end

local function hasInvalidSeparators(transcription) if find(transcription, "%.[ˈˌ]") then return true else return false end end

function export.format_IPA_multiple(lang, items, separator, no_count) local categories = {} separator = separator or ', ' -- Format if not items[1] then if mw.title.getCurrentTitle.nsText == "Template" then table.insert(items, {pron = "/aɪ piː ˈeɪ/"}) else table.insert(categories, "") end end local bits = {} for _, item in ipairs(items) do		local bit = export.format_IPA(lang, item.pron) if item.pretext then bit = item.pretext .. bit end if item.posttext then bit = bit .. item.posttext end

if item.q and item.q[1] or item.qq and item.qq[1] or item.qualifiers and item.qualifiers[1] or item.a and item.a[1] or item.aa and item.aa[1] then bit = require("Module:pron qualifier").format_qualifiers(item, bit) end

if item.refs or item.note then local refspecs if item.note then -- FIXME: eliminate item.note in favor of item.refs. Use tracking to find places -- that use item.note. refspecs = {item.note} track("note") else refspecs = item.refs end local refs = {} if #refspecs > 0 then for _, refspec in ipairs(refspecs) do					if type(refspec) ~= "table" then refspec = {text = refspec} end local refargs if refspec.name or refspec.group then refargs = {name = refspec.name, group = refspec.group} end table.insert(refs, mw.getCurrentFrame:extensionTag("ref", refspec.text, refargs)) end bit = bit .. table.concat(refs) end end

if item.separator then bit = item.separator .. bit end

table.insert(bits, bit) --[=[	Special:WhatLinksHere/Template:tracking/IPA/syntax-error The length or gemination symbol should not appear after a syllable break or stress symbol. ]=]		if find(item.pron, "[ˈˌ%.][ːˑ]") then track("syntax-error") end if lang then -- Add syllable count if the language's diphthongs are listed in Module:syllables. -- Don't do this if the term has spaces or a liaison mark (‿). if not no_count and mw.title.getCurrentTitle.namespace == 0 then m_syllables = m_syllables or require('Module:syllables') local langcode = lang:getCode if m_data.langs_to_generate_syllable_count_categories[langcode] then local repr = determine_repr(item.pron) local use_it if m_data.langs_to_use_phonetic_notation[langcode] then use_it = repr == "phonetic" else use_it = repr == "phonemic" end if use_it and not find(item.pron, "[ ‿]") then local syllable_count = m_syllables.getVowels(item.pron, lang) if syllable_count then table.insert(categories, "") end end end end

if lang:getCode == "en" and hasInvalidSeparators(item.pron) then table.insert(categories, "") end end end

return table.concat(bits, separator) .. table.concat(categories) end

-- Takes an IPA pronunciation and formats it and adds cleanup categories. function export.format_IPA(lang, pron, split_output) local err = {} local categories = {} -- Remove wikilinks, so that wikilink brackets are not misinterpreted as	-- indicating phonemic transcription local str_gsub = string.gsub local without_links = str_gsub(pron, '%[%^|%+|([^%]]+)%]%]', '%1') without_links = str_gsub(without_links, '%[%^%+%]%]', '%1') -- Detect whether this is a phonemic or phonetic transcription local repr, reconstructed = determine_repr(without_links) if reconstructed then pron = sub(pron, 2) without_links = sub(without_links, 2) end -- If valid, strip the representation marks if repr == "phonemic" then pron = sub(pron, 2, -2) without_links = sub(without_links, 2, -2) elseif repr == "phonetic" then pron = sub(pron, 2, -2) without_links = sub(without_links, 2, -2) elseif repr == "orthographic" then pron = sub(pron, 2, -2) without_links = sub(without_links, 2, -2) elseif repr == "rhyme" then pron = sub(pron, 2) without_links = sub(without_links, 2) else table.insert(categories, "") -- table.insert(err, "invalid representation marks") -- Removed because it's annoying when previewing pronunciation pages. end if pron == "" then table.insert(categories, "") end -- Check for obsolete and nonstandard symbols for i, symbol in ipairs(m_data.nonstandard) do		local result for nonstandard in gmatch(pron, symbol) do			if not result then result = {} end table.insert(result, nonstandard) table.insert(categories, "") end if result then table.insert(err, "obsolete or nonstandard characters (" .. table.concat(result) .. ")")			break end end -- Check for invalid symbols after removing the following:			1. wikilinks (handled above)			2. paired HTML tags			3. bolding			4. italics			5. HTML entity for space			6. asterisk at beginning of transcription			7. comma followed by spacing characters			8. superscripts enclosed in superscript parentheses local found_HTML local result = str_gsub(without_links, "<(%a+)[^>]*>([^<]+)",		function(tagName, content)			found_HTML = true			return content		end) result = str_gsub(result, "([^']*)", "%1") result = str_gsub(result, "([^']*)", "%1") result = str_gsub(result, "&[^;]+;", "") -- This may catch things that are not valid character entities. result = str_gsub(result, "^%*", "") result = gsub(result, ",%s+", "") result = gsub(result, "⁽[".. m_symbols.superscripts .. "]+⁾", "") result = gsub(result, '[' .. m_symbols.valid .. ']', '') -- VS15 local vs15_class = "[" .. m_symbols.add_vs15 .. "]"	if find(pron, vs15_class) then local vs15 = u(0xFE0E) if find(result, vs15) then result = gsub(result, vs15, "") pron = gsub(pron, vs15, "") end pron = gsub(pron, "(" .. vs15_class .. ")", "%1" .. vs15) end

if result ~= '' then local suggestions = {} mw.log(pron, result) local namespace = mw.title.getCurrentTitle.namespace local category if namespace == 0 then -- main namespace category = "IPA pronunciations with invalid IPA characters" elseif namespace == 118 then -- reconstruction namespace category = "IPA pronunciations with invalid IPA characters/reconstruction" else category = "IPA pronunciations with invalid IPA characters/non_mainspace" end for character in gmatch(result, ".") do			local suggestion = m_symbols.suggestions[character] if suggestion then table.insert(suggestions, character .. " with " .. suggestion) end table.insert(categories, "") end table.insert(err, "invalid IPA characters (" .. result .. ")")		if suggestions[1] then table.insert(err, "replace " .. table.concat(suggestions, ", ")) end end if found_HTML then table.insert(categories, "") end -- Reference inside IPA template usage -- FIXME: Doesn't work; you can't put HTML in module output. --if find(pron, ' ') then --	table.insert(categories, "") --end if repr == "phonemic" or repr == "rhyme" then if lang and m_data.phonemes[lang:getCode] then local valid_phonemes = m_data.phonemes[lang:getCode] local rest = pron local phonemes = {} while len(rest) > 0 do				local longestmatch = "" if sub(rest, 1, 1) == "(" or sub(rest, 1, 1) == ")" then longestmatch = sub(rest, 1, 1) else for _, phoneme in ipairs(valid_phonemes) do						if len(phoneme) > len(longestmatch) and sub(rest, 1, len(phoneme)) == phoneme then longestmatch = phoneme end end end if len(longestmatch) > 0 then table.insert(phonemes, longestmatch) rest = sub(rest, len(longestmatch) + 1) else local phoneme = sub(rest, 1, 1) table.insert(phonemes, "" .. phoneme .. " ") rest = sub(rest, 2) table.insert(categories, "") track("invalid phonemes/" .. phoneme) end end pron = table.concat(phonemes) end if repr == "phonemic" then pron = "/" .. pron .. "/"		else pron = "-" .. pron end elseif repr == "phonetic" then pron = "[" .. pron .. "]"	elseif repr == "orthographic" then pron = "⟨" .. pron .. "⟩"	end if reconstructed then pron = "*" .. pron end if err[1] then err = '  ' .. table.concat(err, ', ') .. ' '	else err = "" end if split_output then -- for use of IPA in links return ' ' .. pron .. ' ', table.concat(categories), err else return ' ' .. pron .. ' ' .. err .. table.concat(categories) end end

return export

title: Module:IPA


text:
Module:String utilities

local module_name = "string_utilities" local export = {}

local format_escapes = { ["op"] = "{", ["cl"] = "}", }

function export.format_fun(str, fun) return (str:gsub("{(\\?)((\\?)[^{}]*)}", function (p1, name, p2) if #p1 + #p2 == 1 then return format_escapes[name] or error(module_name .. ".format: unrecognized escape sequence '{\\" .. name .. "}'") else if fun(name) and type(fun(name)) ~= "string" then error(module_name .. ".format: '" .. name .. "' is a " .. type(fun(name)) .. ", not a string") end return fun(name) or error(module_name .. ".format: '" .. name .. "' not found in table") end end)) end

--[==[This function, unlike lua and lua, takes just two parameters—a format string and a table—and replaces all instances of lua in the format string with the table's entry for lua. The opening and closing brace characters can be escaped with  and , respectively. A table entry beginning with a slash can be escaped by doubling the initial slash.

Examples
function export.format(str, tbl) return export.format_fun(str, function (key) return tbl[key] end) end
 * lua
 * produces: lua
 * lua
 * produces: lua
 * Note that the single and double backslashes should be entered as double and quadruple backslashes when quoted in a literal string.]==]

--[==[Explodes a string into an array of UTF8 characters. Warning: this function has no safety checks for non-UTF8 byte sequences, to optimize speed and memory use. Inputs containing them therefore result in undefined behaviour.]==] function export.explode_utf8(str) local byte = string.byte local sub = string.sub local str_len = #str local text = {} local n, i, b = 1, 0 while n <= str_len do		b = byte(str, n)		i = i + 1 if b < 0xC0 then text[i] = sub(str, n, n)			n = n + 1 elseif b < 0xE0 then text[i] = sub(str, n, n + 1) n = n + 2 elseif b < 0xF0 then text[i] = sub(str, n, n + 2) n = n + 3 else text[i] = sub(str, n, n + 3) n = n + 4 end end return text end

-- A helper function which takes a string, position and type ("byte" or "char"), and returns the equivalent position for the other type (e.g. iterate_utf8("字典", 2, "char") returns 4, because character 2 of "字典" begins with byte 4). `pos` can be positive or negative, and the function will iterate over the string forwards or backwards (respectively) until it reaches the input position. Checks byte-by-byte; skipping over trailing bytes, and then calculating the correct byte trail for any leading bytes (i.e. how many trailing bytes should follow); these trailing bytes are then checked together. -- The optional parameters `init_from_type` and `init_to_type` can be used to start part-way through an iteration to improve performance, if multiple values need to be returned from the same string. For example, iterate_utf8("слова́рь", 11, "byte", 5, 3) will begin checking at byte 5/the start of character 3. Note: The function won't check if these values match each other (as the only way to do this would be to run the iteration from the beginning), so mismatched values will return incorrect results. local function iterate_utf8(text, pos, from_type, init_from_type, init_to_type) -- Position 0 is always valid and never changes. if pos == 0 then return pos end local to_type if from_type == "char" then to_type = "byte" else to_type = "char" end -- Positive positions iterate forwards; negative positions iterate backwards. local iterate_val if pos > 0 then iterate_val = 1 else iterate_val = -1 end -- Adjust init_from_type and init_to_type to the iteration before, so that matches for the position given by them will work. local trail, cp, min, b = 0 local c, leading_byte = {} c[from_type] = init_from_type and init_from_type ~= 0 and init_from_type - iterate_val or 0 c[to_type] = init_to_type and init_to_type ~= 0 and init_to_type - iterate_val or 0 while true do		if pos > 0 then b = text:byte(c.byte + 1) else b = text:byte(text:len + c.byte) end -- Position byte doesn't exist, so iterate the return value and return it. if not b then return c[to_type] + iterate_val elseif b < 0x80 then -- 1-byte codepoint, 00-7F. trail = 0 cp = b			min = 0 leading_byte = true elseif b < 0xc0 then -- A trailing byte. leading_byte = false elseif b < 0xc2 then -- An overlong encoding for a 1-byte codepoint. error("String " .. text .. " is not UTF-8.") elseif b < 0xe0 then -- 2-byte codepoint, C2-DF. trail = 1 cp = b - 0xc0 min = 0x80 leading_byte = true elseif b < 0xf0 then -- 3-byte codepoint, E0-EF. trail = 2 cp = b - 0xe0 min = 0x800 leading_byte = true elseif b < 0xf4 then -- 4-byte codepoint, F0-F3. trail = 3 cp = b - 0xf0 min = 0x10000 leading_byte = true elseif b == 0xf4 then -- 4-byte codepoint, F4. -- Make sure it doesn't decode to over U+10FFFF. if text:byte(c.byte + 2) > 0x8f then error("String " .. text .. " is not UTF-8.") end trail = 3 cp = 4 min = 0x100000 leading_byte = true else -- Codepoint over U+10FFFF, or invalid byte. error("String " .. text .. " is not UTF-8.") end -- Check subsequent bytes for multibyte codepoints. if leading_byte then local from, to			if pos > 0 then from, to = c.byte + 2, c.byte + 1 + trail else from, to = text:len + c.byte + 1, text:len + c.byte + trail end for trailing_byte = from, to do				b = text:byte(trailing_byte) if not b or b 0xbf then error("String " .. text .. " is not UTF-8.") end cp = cp * 0x40 + b - 0x80 end local next_byte = text:byte(to + 1) if next_byte and next_byte >= 0x80 and next_byte <= 0xbf then -- Too many trailing bytes. error("String " .. text .. " is not UTF-8.") elseif cp < min then -- Overlong encoding. error("String " .. text .. " is not UTF-8.") end end c.byte = c.byte + iterate_val if leading_byte then c.char = c.char + iterate_val end if c[from_type] == pos then return c[to_type] end end end

--[==[Converts a character position to the equivalent byte position.]==] function export.charsToBytes(text, pos) return iterate_utf8(text, pos, "char") end

--[==[Converts a byte position to the equivalent character position.]==] function export.bytesToChars(text, pos) local byte = text:byte(pos) if byte and byte >= 0x80 and byte <= 0xbf then error("Byte " .. pos .. " is not a leading byte.") end return iterate_utf8(text, pos, "byte") end

-- A helper function which iterates through a pattern, and returns two values: a potentially modified version of the pattern, and a boolean indicating whether the returned pattern is simple (i.e. whether it can be used with the stock string library); if not, then the pattern is complex (i.e. it must be used with the ustring library, which is much more resource-intensive). local function patternSimplifier(text, pattern, plain) pattern = tostring(pattern) -- If `plain` is set, then the pattern is treated as literal (so is always simple). Only used by find. if plain then return pattern, true --If none of these are present, then the pattern has to be simple. elseif not (		pattern:match("%[.-[\128-\255].-%]") or		pattern:match("[\128-\255][%*%+%?%-]") or		pattern:match("%%[abcdlpsuwxACDLPSUWXZ]") or		pattern:match("%[%^[^%]]+%]") or		pattern:match("%.[^%*%+%-]") or		pattern:match("%.$") or		pattern:match("%%b.?[\128-\255]") or		pattern:match("", 1, true)	) then return pattern, true end -- Otherwise, the pattern could go either way. -- Build up the new pattern in a table, then concatenate at the end. we do it this way, as occasionally entries get modified along the way. local new_pattern = {} local len, pos, b = pattern:len, 0 local char, next_char -- `escape` and `balanced` are counters, which ensure the effects of % or %b (respectively) are distributed over the following bytes. -- `set` is a boolean that states whether the current byte is in a charset. -- `capture` keeps track of how many layers of capture groups the position is in, while `captures` keeps a tally of how many groups have been detected (due to the string library limit of 32). local escape, set, balanced, capture, captures = 0, false, 0, 0, 0 while pos < len do		pos = pos + 1 b = pattern:byte(pos) if escape > 0 then escape = escape - 1 end if balanced > 0 then balanced = balanced - 1 end char = next_char or pattern:sub(pos, pos) next_char = pattern:sub(pos + 1, pos + 1) if escape == 0 then if char == "%" then -- Apply % escape. if next_char == "." or next_char == "%" or next_char == "[" or next_char == "]" then escape = 2 if balanced > 0 then balanced = balanced + 1 end -- These charsets make the pattern complex. elseif next_char:match("[acdlpsuwxACDLPSUWXZ]") then return pattern, false -- This is "%b". elseif next_char == "b" then balanced = 4 end -- Enter or leave a charset. elseif char == "[" then set = true elseif char == "]" then set = false elseif char == "(" then				capture = capture + 1			elseif char == ")" then if capture > 0 and set == false and balanced == 0 then captures = captures + 1 capture = capture - 1 end end end -- Multibyte char. if b > 0x7f then -- If followed by "*", "+" or "-", then 2-byte chars can be converted into charsets. However, this is not possible with 3 or 4-byte chars, as the charset would be too permissive, because if the trailing bytes were in a different order then this could be a different valid character. if next_char == "*" or next_char == "+" or next_char == "-" then local prev_pos = pattern:byte(pos - 1) if prev_pos > 0xc1 and prev_pos < 0xe0 then new_pattern[#new_pattern] = "[" .. new_pattern[#new_pattern] table.insert(new_pattern, char .. "]") else return pattern, false end -- If in a charset or used in "%b", then the pattern is complex. -- If followed by "?", add "?" after each byte. elseif next_char == "?" then table.insert(new_pattern, char .. "?") local check_pos, check_b, i = pos, pattern:byte(pos), #new_pattern while check_b and check_b < 0xc0 do					check_pos = check_pos - 1 check_b = pattern:byte(check_pos) i = i - 1 new_pattern[i] = new_pattern[i] .. "?"				end pos = pos + 1 next_char = pattern:sub(pos + 1, pos + 1) elseif set or balanced > 0 then return pattern, false else table.insert(new_pattern, char) end elseif char == "." then -- "*", "+", "-" are always okay after ".", as they don't care how many bytes a char has. if set or next_char == "*" or next_char == "+" or next_char == "-" or escape > 0 then table.insert(new_pattern, char) -- If followed by "?", make sure "?" is after the leading byte of the UTF-8 char pattern, then skip forward one. elseif next_char == "?" then table.insert(new_pattern, "[%z\1-\127\194-\244]?[\128-\191]*") pos = pos + 1 next_char = pattern:sub(pos + 1, pos + 1) -- If used with "%b", pattern is complex. elseif balanced > 0 then return pattern, false -- Otherwise, add the UTF-8 char pattern. else table.insert(new_pattern, "[%z\1-\127\194-\244][\128-\191]*") end -- Negative charsets are always complex, unless the text has no UTF-8 chars. elseif char == "[" and next_char == "^" and escape == 0 and text:match("[\128-\255]") then return pattern, false -- "" matches the position unless escaped or used with "%b", so always necessitates ustring (as we need it to match the char position, not the byte one). elseif char == "(" and next_char == ")" and balanced == 0 and escape == 0 and text:match("[\128-\255]") then return pattern, false else table.insert(new_pattern, char) end end if captures > 32 then return pattern, false else pattern = table.concat(new_pattern) return pattern, true end end

--[==[A version of len which uses string.len, but returns the same result as mw.ustring.len.]==] function export.len(text) text = tostring(text) local len_bytes = text:len if not text:match("[\128-\255]") then return len_bytes else return iterate_utf8(text, len_bytes, "byte") end end

--[==[A version of sub which uses string.sub, but returns the same result as mw.ustring.sub.]==] function export.sub(text, i_char, j_char) text = tostring(text) if not text:match("[\128-\255]") then return text:sub(i_char, j_char) end local i_byte, j_byte if j_char then if i_char > 0 and j_char > 0 then if j_char < i_char then return "" end i_byte = iterate_utf8(text, i_char, "char") j_byte = iterate_utf8(text, j_char + 1, "char", i_char, i_byte) - 1 elseif i_char < 0 and j_char < 0 then if j_char < i_char then return "" end j_byte = iterate_utf8(text, j_char + 1, "char") - 1 i_byte = iterate_utf8(text, i_char, "char", j_char, j_byte) -- For some reason, mw.ustring.sub with i=0, j=0 returns the same result as for i=1, j=1, while string.sub always returns "". However, mw.ustring.sub does return "" with i=1, j=0. As such, we need to adjust j_char to 1 if i_char is either 0, or negative with a magnitude greater than the length of the string. elseif j_char == 0 then i_byte = iterate_utf8(text, i_char, "char") if i_byte == 0 or -i_byte > text:len then j_char = 1 end j_byte = iterate_utf8(text, j_char + 1, "char") - 1 else i_byte = iterate_utf8(text, i_char, "char") j_byte = iterate_utf8(text, j_char + 1, "char") - 1 end else i_byte = iterate_utf8(text, i_char, "char") end return text:sub(i_byte, j_byte) end

--[==[A version of lower which uses string.lower when possible, but otherwise uses mw.ustring.lower.]==] function export.lower(text) text = tostring(text) if not text:match("[\128-\255]") then return text:lower else return mw.ustring.lower(text) end end

--[==[A version of upper which uses string.upper when possible, but otherwise uses mw.ustring.upper.]==] function export.upper(text) text = tostring(text) if not text:match("[\128-\255]") then return text:upper else return mw.ustring.upper(text) end end

--[==[A version of find which uses string.find when possible, but otherwise uses mw.ustring.find.]==] function export.find(text, pattern, init_char, plain) text = tostring(text) local simple pattern, simple = patternSimplifier(text, pattern, plain) -- If the pattern is simple but multibyte characters are present, then init_char needs to be converted into bytes for string.find to work properly, and the return values need to be converted back into chars. if simple then if not text:match("[\128-\255]") then return text:find(pattern, init_char, plain) else local init_byte = init_char and iterate_utf8(text, init_char, "char") local byte1, byte2, c1, c2, c3, c4, c5, c6, c7, c8, c9 = text:find(pattern, init_byte, plain) -- If string.find returned nil, then return nil. if not (byte1 and byte2) then return nil end -- Get first return value. If we have a positive init_char, we can save resources by resuming at that point. local char1, char2 if (not init_char) or init_char > 0 then char1 = iterate_utf8(text, byte1, "byte", init_byte, init_char) else char1 = iterate_utf8(text, byte1, "byte") end -- If byte1 and byte2 are the same, don't bother running iterate_utf8 twice. Otherwise, resume iterate_utf8 from byte1 to find char2. if byte1 == byte2 then char2 = char1 else char2 = iterate_utf8(text, byte2, "byte", byte1, char1) end return unpack{char1, char2, c1, c2, c3, c4, c5, c6, c7, c8, c9} end else return mw.ustring.find(text, pattern, init_char, plain) end end

--[==[A version of match which uses string.match when possible, but otherwise uses mw.ustring.match.]==] function export.match(text, pattern, init) text = tostring(text) local simple pattern, simple = patternSimplifier(text, pattern) if simple then if init and text:find("[\128-\255]") then init = iterate_utf8(text, init, "char") end return text:match(pattern, init) else return mw.ustring.match(text, pattern, init) end end

--[==[A version of gmatch which uses string.gmatch when possible, but otherwise uses mw.ustring.gmatch.]==] function export.gmatch(text, pattern) text = tostring(text) local simple pattern, simple = patternSimplifier(text, pattern) if simple then return text:gmatch(pattern) else return mw.ustring.gmatch(text, pattern) end end

--[==[A version of gsub which uses string.gsub when possible, but otherwise uses mw.ustring.gsub.]==] function export.gsub(text, pattern, repl, n)	text = tostring(text) local simple pattern, simple = patternSimplifier(text, pattern) if simple then return text:gsub(pattern, repl, n)	else return mw.ustring.gsub(text, pattern, repl, n)	end end

--[==[ -- Reimplementation of mw.ustring.split that includes any capturing -- groups in the splitting pattern. This works like Python's re.split -- function, except that it has Lua's behavior when the split pattern -- is empty (i.e. advancing by one character at a time; Python returns the -- whole remainder of the string). ]==] function export.capturing_split(str, pattern) local ret = {} -- (.-) corresponds to (.*?) in Python or Perl; captures the -- current position after matching. pattern = "(.-)" .. pattern .. ""	local start = 1 while true do -- Did we reach the end of the string? if start > #str then table.insert(ret, "") return ret end -- match returns all captures as multiple return values; -- we need to insert into a table to get them all. local captures = {export.match(str, pattern, start)} -- If no match, add the remainder of the string. if #captures == 0 then table.insert(ret, export.sub(str, start)) return ret end local newstart = table.remove(captures) -- Special case: If we don't advance by any characters, then advance -- by one character; this avoids an infinite loop, and makes splitting -- by an empty string work the way mw.ustring.split does. If we		-- reach the end of the string this way, return immediately, so we -- don't get a final empty string. if newstart == start then table.insert(ret, export.sub(str, start, start)) table.remove(captures, 1) start = start + 1 if start > #str then return ret end else table.insert(ret, table.remove(captures, 1)) start = newstart end -- Insert any captures from the splitting pattern. for _, x in ipairs(captures) do			table.insert(ret, x)		end end end

local function uclcfirst(text, dolower) local function douclcfirst(text) -- Actual function to re-case of the first letter. local first_letter = export.sub(text, 1, 1) first_letter = dolower and export.lower(first_letter) or export.upper(first_letter) return first_letter .. export.sub(text, 2) end -- If there's a link at the beginning, re-case the first letter of the -- link text. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local link, linktext, remainder = export.match(text, "^%[%[([^|%]]+)%|?(.-)%]%](.*)$") if link then return "" .. douclcfirst(linktext ~= "" and linktext or link) .. "" .. remainder end return douclcfirst(text) end

function export.ucfirst(text) return uclcfirst(text, false) end

function export.lcfirst(text) return uclcfirst(text, true) end

-- Almost identical to mw.text.nowiki, but with minor changes to be identical to the PHP equivalent: ";" always escapes, and colons in URI protocols without slashes only escape after a word break. Also about 2-3 times as fast. function export.nowiki(text) local data = mw.loadData("Module:string utilities/data") return ("\n" .. text) :gsub("[\"&'<=>%[%]{|};]", data.nowiki_replacements)		:gsub("[\n\r][#*: \n\r\t]", data.nowiki_replacements)		:gsub("([\n\r])%-(%-%-%-)", "%1-%2")		:gsub("__", "__")		:gsub("://", "://")		:gsub("([IP]?[MRS][BFI][CDN])([\t\n\f\r ])", function(m1, m2)			if data.magic_links[m1] then				return m1 .. data.nowiki_replacements[m2]			end		end)		:gsub("([%w_]+):", function(m1, m2)			if data.uri_schemes[m1:lower] then				return m1 .. ":"			end		end)		:sub(2) end

function export.capitalize(text) if type(text) == "table" then -- allow calling from a template text = text.args[1] end -- Capitalize multi-word that is separated by spaces -- by uppercasing the first letter of each part. -- I assume nobody will input all CAP text. w2 = {} for w in export.gmatch(text, "%S+") do		table.insert(w2, uclcfirst(w, false)) end return table.concat(w2, " ") end

function export.pluralize(text) if type(text) == "table" then -- allow calling from a template text = text.args[1] end -- Pluralize a word in a smart fashion, according to normal English rules. -- 1. If word ends in consonant + -y, replace the -y with -ies. -- 2. If the word ends in -s, -x, -z, -sh, -ch, add -es. -- 3. Otherwise, add -s. -- This handles links correctly: -- 1. If a piped link, change the second part appropriately. -- 2. If a non-piped link and rule #1 above applies, convert to a piped link --   with the second part containing the plural. -- 3. If a non-piped link and rules #2 or #3 above apply, add the plural --   outside the link. local function word_ends_in_consonant_plus_y(text) -- FIXME, a subrule of rule #1 above says the -ies ending doesn't -- apply to proper nouns, hence "the Gettys", "the public Ivys". -- We should maybe consider applying this rule here; but it may not -- be important as this function is almost always called on common nouns -- (e.g. parts of speech, place types). return text:find("[^aeiouAEIOU ]y$") end local function word_takes_es_plural(text) return text:find("[sxz]$") or text:find("[cs]h$") end local function do_pluralize(text) if word_ends_in_consonant_plus_y(text) then -- avoid returning multiple values local hack_single_retval = text:gsub("y$", "ies") return hack_single_retval elseif word_takes_es_plural(text) then return text .. "es" else return text .. "s" end end -- Check for a link. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local beginning, link, linktext = export.match(text, "^(.*)%[%[([^|%]]+)%|?(.-)%]%]$") if link then if linktext ~= "" then return beginning .. "" .. do_pluralize(linktext) .. "" end if word_ends_in_consonant_plus_y(link) then return beginning .. "" .. link:gsub("y$", "ies") .. "" end return beginning .. "" .. link .. "" .. (word_takes_es_plural(link) and "es" or "s") end return do_pluralize(text) end

function export.singularize(text) if type(text) == "table" then -- allow calling from a template text = text.args[1] end -- Singularize a word in a smart fashion, according to normal English rules. -- Works analogously to pluralize. -- NOTE: This doesn't always work as well as pluralize. Beware. It will -- mishandle cases like "passes" -> "passe", "eyries" -> "eyry". -- 1. If word ends in -ies, replace -ies with -y. -- 2. If the word ends in -xes, -shes, -ches, remove -es. [Does not affect --   -ses, cf. "houses", "impasses".] -- 3. Otherwise, remove -s. -- This handles links correctly: -- 1. If a piped link, change the second part appropriately. Collapse the --   link to a simple link if both parts end up the same. -- 2. If a non-piped link, singularize the link. -- 3. A link like "parishes" will be handled correctly because the --   code that checks for -shes etc. allows ] characters between the --   'sh' etc. and final -es. local function do_singularize(text) local sing = text:match("^(.-)ies$") if sing then return sing .. "y" end -- Handle cases like "parishes" local sing = text:match("^(.-[sc]h%]*)es$") if sing then return sing end -- Handle cases like "boxes" local sing = text:match("^(.-x%]*)es$") if sing then return sing end local sing = text:match("^(.-)s$") if sing then return sing end return text end

local function collapse_link(link, linktext) if link == linktext then return "" .. link .. "" else return "" .. linktext .. "" end end

-- Check for a link. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local beginning, link, linktext = export.match(text, "^(.*)%[%[([^|%]]+)%|?(.-)%]%]$") if link then if linktext ~= "" then return beginning .. collapse_link(link, do_singularize(linktext)) end return beginning .. "" .. do_singularize(link) .. "" end

return do_singularize(text) end

function export.add_indefinite_article(text, uppercase) local is_vowel = false -- If there's a link at the beginning, examine the first letter of the -- link text. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local link, linktext, remainder = export.match(text, "^%[%[([^|%]]+)%|?(.-)%]%](.*)$") if link then is_vowel = export.find(linktext ~= "" and linktext or link, "^[AEIOUaeiou]") else is_vowel = export.find(text, "^[AEIOUaeiou]") end return (is_vowel and (uppercase and "An " or "an ") or (uppercase and "A " or "a ")) .. text end

-- Convert risky characters to HTML entities, which minimizes interference once returned (e.g. for "sms:a", "" etc.). function export.escape_risky_characters(text) -- Spacing characters in isolation generally need to be escaped in order to be properly processed by the MediaWiki software. if not mw.ustring.match(text, "%S") then return mw.text.encode(text, "%s") else return mw.text.encode(text, "!#%%&*+/:;<=>?@[\\%]_{|}") end end

return export

title: Module:String utilities


text:
Module:IPA/data

local data = {}

--[=[ This should list the language codes of all languages that have a pronunciation page in the appendix of the form Appendix:LANG pronunciation, e.g. Appendix:Russian pronunciation. For these languages, the text "key" next to the generated pronunciation links to such pages; for other languages, it links to the "LANG phonology" page in Wikipedia (which may or may not exist). Module:IPA is responsible for this linking; see format_IPA_full. ]=] local langs_with_infopages = { "acw", "ady", "ang", "arc", "ba", "bg", "bo", "ca", "cho", "cmn", "cs", "cv", "cy", "da", "de", "dsb", "dz", "egl", "egy", "el", "en", "enm", "eo", "es", "fa", "fi", "fo", "fr", "fy", "ga", "gd", "gem-pro", "got", "he", "hi", "hu", "hy", "ii", "is", "it", "iu", "ja", "jbo", "ka", "kls", "ko", "kw", "la", "lb", "liv", "lt", "lv", "mdf", "mfe", "mic", "mk", "mns", "ms", "mt", "mul", "my", "nan", "nci", "nl", "nn", "no", "nov", "nv", "pjt", "pl", "ps", "pt", "ro", "ru", "scn", "sco", "sga", "sh", "sl", "sq", "sv", "sw", "syc", "szl", "th", "tl", "tr", "tyv", "ug", "uk", "vi", "vo", "wlm", "yi", "yue", }

data.langs_with_infopages = {}

-- Convert the list in `langs_with_infopages` to a set. for _, langcode in ipairs(langs_with_infopages) do	data.langs_with_infopages[langcode] = true end

--[=[ This should list the diphthongs of a language (in the form of Lua patterns), provided they do *NOT* contain semivowel symbols such as /j w ɰ ɥ/ or vowels with nonsyllabic diacritics such as /i̯ u̯/. For example, list /au/ or /aʊ/, but do not list /aw/ or /au̯/. The data in this table is used to count the number of syllables in a word. Module:syllables automatically knows how to correctly handle semivowel symbols and nonsyllabic diacritics.

Any language listed here will automatically have categories of the form "LANG #-syllable words" generated. In addition, any language listed below under `langs_to_generate_syllable_count_categories` will also have such categories generated.

NOTE: There are some additional languages that have these categories. For example: ]=] data.diphthongs = { ["cs"] = { -- Czech phonology "[aeo]u", },	["de"] = { "a[ɪʊ]", "ɔ[ʏɪ]", },	["en"] = { -- from Appendix:English pronunciation mostly, but /ʌɪ/ is from the OED "[aɑeɛoɔʌ][ɪi]", "[ɑɒæo]e", "[əɐ]ʉ", "[aɒəoɔæ]ʊ", "æo", "[ɛeɪiɔʊʉ]ə",	-- /iə/ is a diphthong in NZE, but a disyllabic sequence in GA. -- /ɪə/ is both a disyllabic sequence and a diphthong in old-fashioned RP. "[aʌ][ʊɪ]ə",	-- May be a disyllabic sequence in some or all dialects? },	["grc"] = { "[aeyo]i", "[ae]u", "[ɛɔa]ː[iu]", },	["is"] = {			-- Icelandic phonology "[aeø][iɪy]",	-- Wikipedia is oddly specific about the second element: ei and ai, but øɪ. "[ao]u", },	["it"] = { "[aeɛoɔu]i", "[aeɛioɔ]u", },	["la"] = { "[eaou]i", "[eao]u", "[ao]e", },	["lb"] = { "[iu]ə", "[ɜoæɑ]ɪ", "[əæɑ]ʊ", }, }
 * Thai words have these categories added by Module:th-pron.

--[=[ This should list any languages for which categories of the form "LANG #-syllable words", e.g. Category:Russian 3-syllable words, should be generated. Do not list languages here if they have an entry above under `data.diphthongs`; such languages are automatically added to this list. ]=] local langs_to_generate_syllable_count_categories = { "ar",	-- Arabic has diphthongs, but they are transcribed -- with semivowel symbols. "ary",	-- Moroccan Arabic has diphthongs, but they are transcribed -- with semivowel symbols. "ca",	-- Catalan has diphthongs, but they are generally transcribed using -- /w/ and /j/, so do not need to be listed (see Catalan language.	"es",	-- Spanish has diphthongs, but they are transcribed with i̯ etc.	"fi",	-- Finnish has diphthongs, but they are now automatically transcribed with			-- the nonsyllabic diacritic	"fr",	-- French has diphthongs, but they are transcribed			-- with semivowel symbols: French phonology.	"ka",   "kmr",	"ku",	"mk",    "mt",	-- Maltese has diphthongs, but they are transcribed			-- with semivowel symbols.	"pl",   -- No diphthongs, properly speaking; sequences of a vowel and /w/ or /j/ though.	"pt",	-- Portuguese has diphthongs, but they are transcribed with i̯ or /j/ etc.	"ru",	-- No diphthongs, properly speaking; sequences of a vowel and /j/ though.	"sk",	-- Slovak has rising diphthongs, /i̯e, i̯a, i̯u, u̯o/, which are probably always spelled with the nonsyllabic diacritic, so do not need to be listed. "sl",	-- No diphthongs, properly speaking; sequences of a vowel, /j/ and /w/ though "sq",	-- Albanian language doesn't mention anything about diphthongs. "ug",	-- No diphthongs. }

data.langs_to_generate_syllable_count_categories = {}

-- Convert the list in `langs_to_generate_syllable_count_categories` to a set. for _, langcode in ipairs(langs_to_generate_syllable_count_categories) do	data.langs_to_generate_syllable_count_categories[langcode] = true end -- Also add languages listed under `data.diphthongs`. for langcode, _ in pairs(data.diphthongs) do	data.langs_to_generate_syllable_count_categories[langcode] = true end

-- Languages to use the phonetic not phonemic notation to compute syllables counts. local langs_to_use_phonetic_notation = { "es", "mk", "ru", }

data.langs_to_use_phonetic_notation = {}

-- Convert the list in `langs_to_use_phonetic_notation` to a set. for _, langcode in ipairs(langs_to_use_phonetic_notation) do	data.langs_to_use_phonetic_notation[langcode] = true end

-- Non-standard or obsolete IPA symbols. data.nonstandard = { --	The following symbols consist of more than one character,			so we can't put them in the line below. "ɑ̢", "d̂", "t̂", "n̂", "l̂", "k̫", "ɔ̗", "ɔ̖", "[ʦʣʧʤʨʥ?ƍσƺƪƻƾƞᶀᶁᶂᶃᶄᶅᶆᶈᶇᶉᶊᶋƫᶌᶍᶎʓʆλƛłščžǰǧǯẋᵻᵿⱻʚ" .. "ɷωıȹȸ∅ØƥƭƈƙʠʇʗʖʞɩɼȣяɿʅʮʯᴀᴀᴇGRŒQȡȶȵȴKPT]" }

-- See valid IPA characters at Module:IPA/data/symbols.

data.phonemes = {} data.phonemes["dz"] = { "m", "n", "ŋ", "p", "t", "ʈ", "k", "pʰ", "tʰ", "ʈʰ", "kʰ", "t͡s", "t͡ɕ", "t͡sʰ", "t͡ɕʰ", "w", "s", "z", "ɬ", "l", "r", "ɕ", "ʑ", "j", "h", "ɑ", "e", "i", "o", "u", "ɑː", "eː", "ɛː", "iː", "oː", "øː", "uː", "yː", "ɑ˥", "e˥", "i˥", "o˥", "u˥", "ɑː˥", "eː˥", "ɛː˥", "iː˥", "oː˥", "øː˥", "uː˥", "yː˥", "m˥", "n˥", "ŋ˥", "p˥", "k˥", "k̚˥", "w˥", "l˥", "r˥", "ɕ˥", "j˥", ")˥",	"ɑ˩", "e˩", "i˩", "o˩", "u˩",	"ɑː˩", "eː˩", "ɛː˩", "iː˩", "oː˩", "øː˩", "uː˩", "yː˩",	"m˩", "n˩", "ŋ˩", "p˩", "k˩", "k̚˩", "w˩", "l˩", "r˩", "ɕ˩", "j˩", ")˩", ".", ",", "-", } data.phonemes["eo"] = { "a", "b", "d", "d͡ʒ", "d͡z", "e", "f", "h", "i", "j", "k", "l", "m", "n", "o", "p", "r", "s", "t", "t͡s", "t͡ʃ", "u", "v", "w", "x", "z", "ɡ", "ʃ", "ʒ", "ˈ", ".", " ", "-", } data.phonemes["hy"] = { "ɑ", "b", "ɡ", "d", "ɛ", "z", "ɛ", "ə", "tʰ", "ʒ", "i", "l", "χ", "t͡s", "k", "h", "d͡z", "ʁ", "t͡ʃ", "m", "j", "n", "ʃ", "ɔ", "t͡ʃʰ", "p", "d͡ʒ", "r", "s", "v", "t", "ɾ", "t͡sʰ", "v", "pʰ", "kʰ", "ɔ", "f", "ŋɡ", "ŋk", "ŋχ", "u", "ˈ", "ˌ", ".", " ", "ː", } data.phonemes["nl"] = { "m", "n", "ŋ", "p", "b", "t", "d", "k", "ɡ", "f", "v", "s", "z", "ʃ", "ʒ", "x", "ɣ", "ɦ", "ʋ", "l", "j", "r", "ɪ", "ʏ", "ɛ", "ə", "ɔ", "ɑ", "i", "iː", "y", "yː", "u", "uː", "eː", "øː", "oː", "ɛː", "œː", "ɔː", "aː", "ɛi̯", "œy̯", "ɔi̯", "ɑu̯", "ɑi̯", "iu̯", "yu̯", "ui̯", "eːu̯", "oːi̯", "aːi̯", "ˈ", "ˌ", ".", " ", "-", } data.phonemes["mt"] = { "m", "n", "p", "t", "k", "ʔ", "b", "d", "ɡ", "t͡s", "t͡ʃ", "d͡z", "d͡ʒ", "f", "s", "ʃ", "ħ", "v", "z", "ʒ", "ɣ", "l", "j", "w", "r", "ɪ", "ɛ", "ɔ", "a", "u", "ɛˤ", "ɔˤ", "aˤ", "əˤ", "ɛˤː", "ɔˤː", "aˤː", "əˤː", "ɪˤː", "iː", "ɪː", "ɛː", "ɔː", "aː", "uː", "ˈ", "ˌ", ".", " ", "‿", "-" }

return data

title: Module:IPA/data


text:
Module:IPA/data/symbols

local data = {} --[=[	Valid IPA symbols. Currently almost all values of "title" and "link" keys are just the comments that were used in Module:IPA. The "link" fields should be checked (those that start with an uppercase letter are checked). ]=]

local U = mw.ustring.char

data[1] = { -- PULMONIC CONSONANTS

-- nasal ["m"] = { title = "bilabial nasal", link = "w:Bilabial nasal", },	["ɱ"] = { title = "labiodental nasal", link = "w:Labiodental nasal", },	["n"] = { title = "alveolar nasal", link = "w:Alveolar nasal", },	["ɳ"] = { title = "retroflex nasal", link = "w:Retroflex nasal", },	["ɲ"] = { title = "palatal nasal", link = "w:Palatal nasal", },	["ŋ"] = { title = "velar nasal", link = "w:Velar nasal", },	["ɴ"] = { title = "uvular nasal", link = "w:Uvular nasal", },

-- plosive ["p"] = { title = "voiceless bilabial plosive", link = "w:Voiceless bilabial stop", },	["b"] = { title = "voiced bilabial plosive", link = "w:Voiced bilabial stop", },	["t"] = { title = "voiceless alveolar plosive", link = "w:Voiceless alveolar stop", },	["d"] = { title = "voiced alveolar plosive", link = "w:Voiced alveolar stop", },	["ʈ"] = { title = "voiceless retroflex plosive", link = "w:Voiceless retroflex stop", },	["ɖ"] = { title = "voiced retroflex plosive", link = "w:Voiced retroflex stop", },	["c"] = { title = "voiceless palatal plosive", link = "w:Voiceless palatal stop", },	["ɟ"] = { title = "voiced palatal plosive", link = "w:Voiced palatal stop", },	["k"] = { title = "voiceless velar plosive", link = "w:Voiceless velar stop", },	["ɡ"] = { title = "voiced velar plosive", link = "w:Voiced velar stop", },	["q"] = { title = "voiceless uvular plosive", link = "w:Voiceless uvular stop", },	["ɢ"] = { title = "voiced uvular plosive", link = "w:Voiced uvular stop", },	["ʡ"] = { title = "epiglottal plosive", link = "w:Epiglottal stop", },	["ʔ"] = { title = "glottal stop", link = "w:Glottal stop", },

-- fricative ["ɸ"] = { title = "voiceless bilabial fricative", link = "w:Voiceless bilabial fricative", },	["β"] = { title = "voiced bilabial fricative", link = "w:Voiced bilabial fricative", },	["f"] = { title = "voiceless labiodental fricative", link = "w:Voiceless labiodental fricative", },	["v"] = { title = "voiced labiodental fricative", link = "w:Voiced labiodental fricative", },	["θ"] = { title = "voiceless dental fricative", link = "w:Voiceless dental fricative", },	["ð"] = { title = "voiced dental fricative", link = "w:Voiced dental fricative", },	["s"] = { title = "voiceless alveolar fricative", link = "w:Voiceless alveolar fricative", },	["z"] = { title = "voiced alveolar fricative", link = "w:Voiced alveolar fricative", },	["ʃ"] = { title = "voiceless postalveolar fricative", link = "w:Voiceless palato-alveolar sibilant", },	["ʒ"] = { title = "voiced postalveolar fricative", link = "w:Voiced palato-alveolar sibilant", },	["ʂ"] = { title = "voiceless retroflex fricative", link = "w:Voiceless retroflex sibilant", },	["ʐ"] = { title = "voiced retroflex fricative", link = "w:Voiced retroflex sibilant", },	["ɕ"] = { title = "voiceless alveolo-palatal fricative", link = "w:Voiceless alveolo-palatal sibilant", },	["ʑ"] = { title = "voiced alveolo-palatal fricative", link = "w:Voiced alveolo-palatal sibilant", },	["ç"] = { title = "voiceless palatal fricative", link = "w:Voiceless palatal fricative", },	["ʝ"] = { title = "voiced palatal fricative", link = "w:Voiced palatal fricative", },	["x"] = { title = "voiceless velar fricative", link = "w:Voiceless velar fricative", },	["ɣ"] = { title = "voiced velar fricative", link = "w:Voiced velar fricative", },	["χ"] = { title = "voiceless uvular fricative", link = "w:Voiceless uvular fricative", },	["ʁ"] = { title = "voiced uvular fricative", link = "w:Voiced uvular fricative", },	["ħ"] = { title = "voiceless pharyngeal fricative", link = "w:Voiceless pharyngeal fricative", },	["ʕ"] = { title = "voiced pharyngeal fricative", link = "w:Voiced pharyngeal fricative", },	["ʜ"] = { title = "voiceless epiglottal fricative", link = "w:Voiceless epiglottal fricative", },	["ʢ"] = { title = "voiced epiglottal fricative", link = "w:Voiced epiglottal fricative", },	["h"] = { title = "voiceless glottal fricative", link = "w:Voiceless glottal fricative", },	["ɦ"] = { title = "voiced glottal fricative", link = "w:Voiced glottal fricative", },

-- approximant ["ʋ"] = { title = "labiodental approximant", link = "w:Labiodental approximant", },	["ɹ"] = { title = "alveolar approximant", link = "w:Alveolar approximant", },	["ɻ"] = { title = "retroflex approximant", link = "w:Retroflex approximant", },	["j"] = { title = "palatal approximant", link = "w:Palatal approximant", },	["ɰ"] = { title = "velar approximant", link = "w:Velar approximant", },

-- tap, flap ["ⱱ"] = { title = "labiodental tap", link = "w:Labiodental flap", },	["ɾ"] = { title = "alveolar flap", link = "w:Alveolar flap", },	["ɽ"] = { title = "retroflex flap", link = "w:Retroflex flap", },

-- trill ["ʙ"] = { title = "bilabial trill", link = "w:Bilabial trill", },	["r"] = { title = "alveolar trill", link = "w:Alveolar trill", },	["ʀ"] = { title = "uvular trill", link = "w:Uvular trill", },	["ᴙ"] = { title = "epiglottal trill", link = "w:Epiglottal trill", },

-- lateral fricative ["ɬ"] = { title = "voiceless alveolar lateral fricative", link = "w:Voiceless alveolar lateral fricative", },	["ɮ"] = { title = "voiced alveolar lateral fricative", link = "w:Voiced alveolar lateral fricative", },	 --	no precomposed Unicode character --TOMOVE --["ɬ̢"] = {title = "voiceless retroflex lateral fricative", link = "w:voiceless retroflex lateral fricative"}, -- no precomposed Unicode character --TOMOVE:3 --["ʎ̝̊"] = {title = "voiceless palatal lateral fricative", link = "w:voiceless palatal lateral fricative"}, -- no precomposed Unicode character --TOMOVE:3 --["ʟ̝̊"] = {title = "voiceless velar lateral fricative", link = "w:voiceless velar lateral fricative"}, -- no precomposed Unicode character --TOMOVE --["ʟ̝"] = {title = "voiced velar lateral fricative", link = "w:voiced velar lateral fricative"},

-- lateral approximant ["l"] = { title = "alveolar lateral approximant", link = "w:Alveolar lateral approximant", },	["ɭ"] = { title = "retroflex lateral approximant", link = "w:Retroflex lateral approximant", },	["ʎ"] = { title = "palatal lateral approximant", link = "w:Palatal lateral approximant", },	["ʟ"] = { title = "velar lateral approximant", link = "w:Velar lateral approximant", },

-- lateral flap ["ɺ"] = { title = "alveolar lateral flap", link = "w:Alveolar lateral flap", },	--["ɭ̆"] = {title = "retroflex lateral flap", link = "w:retroflex lateral flap"}, -- no precomposed Unicode character --TOMOVE --["ɺ˞"] = {title = "retroflex lateral flap", link = "w:retroflex lateral flap"}, -- no precomposed Unicode character --TOMOVE

-- NON-PULMONIC CONSONANTS

-- clicks ["ʘ"] = { title = "bilabial click", link = "w:Bilabial clicks", },	["ǀ"] = { title = "dental click", link = "w:Dental clicks", },	["ǃ"] = { title = "postalveolar click", link = "w:Alveolar clicks", },	["‼"] = {		title = "subapical retroflex", link = "w:Retroflex clicks", }, --	NOT IN X-SAMPA ["ǂ"] = { title = "palatal click", link = "w:Palatal clicks", },	["ǁ"] = { title = "alveolar lateral click", link = "w:Lateral clicks", },

-- implosives ["ɓ"] = { title = "voiced bilabial implosive", link = "w:Voiced bilabial implosive", },	["ɗ"] = { title = "voiced alveolar implosive", link = "w:Voiced alveolar implosive", },	-- NOT IN X-SAMPA ["ᶑ"] = { title = "retroflex implosive", link = "w:Voiced retroflex implosive", },	["ʄ"] = { title = "voiced palatal implosive", link = "w:Voiced palatal implosive", },	["ɠ"] = { title = "voiced velar implosive", link = "w:Voiced velar implosive", },	["ʛ"] = { title = "voiced uvular implosive", link = "w:Voiced uvular implosive", },

-- ejectives ["ʼ"] = { title = "ejective", link = "w:Ejective consonant", },

-- CO-ARTICULATED CONSONANTS ["ʍ"] = { title = "voiceless labial-velar fricative", link = "w:Voiceless labio-velar approximant", },	["w"] = { title = "labial-velar approximant", link = "w:Labio-velar approximant", },	["ɥ"] = { title = "labial-palatal approximant", link = "w:Labialized palatal approximant", },	["ɧ"] = { title = "voiceless palatal-velar fricative", link = "w:Sj-sound", },

-- should be handled in Module:IPA and not through this table -- BRACKETS --	-- ["//"] = {		title = "morphophonemic",		link = "w:morphophonemic",	},	["/"] = {		title = "phonemic",		link = "w:phonemic",	},	["["] = {		title = "phonetic",		link = "w:phonetic",	},	["["] = {		title = "phonetic",		link = "w:phonetic",	},	["〈"] = {		title = "orthographic",		link = "w:orthographic",	},	["〉"] = {		title = "orthographic",		link = "w:orthographic",	},	["⟨"] = {		title = "orthographic",		link = "w:orthographic",	},	["⟩"] = {		title = "orthographic",		link = "w:orthographic",	},

-- VOWELS

-- close ["i"] = { title = "close front unrounded vowel", link = "w:Close front unrounded vowel", },	["y"] = { title = "close front rounded vowel", link = "w:Close front rounded vowel", },	["ɨ"] = { title = "close central unrounded vowel", link = "w:Close central unrounded vowel", },	["ʉ"] = { title = "close central rounded vowel", link = "w:Close central rounded vowel", },	["ɯ"] = { title = "close back unrounded vowel", link = "w:Close back unrounded vowel", },	["u"] = { title = "close back rounded vowel", link = "w:Close back rounded vowel", },

-- near close ["ɪ"] = { title = "near-close near-front unrounded vowel", link = "w:Near-close near-front unrounded vowel", },	["ʏ"] = { title = "near-close near-front rounded vowel", link = "w:Near-close near-front rounded vowel", },	["ᵻ"] = { title = "near-close central unrounded vowel", link = "w:Near-close central unrounded vowel", },	 -- (alternative) --TOMOVE --	["ɪ̈"] = {		title = "near-close central unrounded vowel",		link = "w:near-close central unrounded vowel",	}, ["ᵿ"] = { title = "near-close central rounded vowel", link = "w:Near-close central rounded vowel", },	 --	 (alternative) TOMOVE	["ʊ̈"] = {		title = "near-close central rounded vowel",		link = "w:near-close central rounded vowel",	}, ["ʊ"] = { title = "near-close near-back rounded vowel", link = "w:Near-close near-back rounded vowel", },

--close mid ["e"] = { title = "close-mid front unrounded vowel", link = "w:Close-mid front unrounded vowel", },	["ø"] = { title = "close-mid front rounded vowel", link = "w:Close-mid front rounded vowel", },	["ɘ"] = { title = "close-mid central unrounded vowel", link = "w:Close-mid central unrounded vowel", },	["ɵ"] = { title = "close-mid central rounded vowel", link = "w:Close-mid central rounded vowel", },	["ɤ"] = { title = "close-mid back unrounded vowel", link = "w:Close-mid back unrounded vowel", },	["o"] = { title = "close-mid back rounded vowel", link = "w:Close-mid back rounded vowel", },

-- mid ["ə"] = { title = "schwa", link = "w:Schwa", },	["ɚ"] = { title = "schwa+r", link = "w:R-colored vowel", },

-- open mid ["ɛ"] = { title = "open-mid front unrounded vowel", link = "w:Open-mid front unrounded vowel", },	["œ"] = { title = "open-mid front rounded vowel", link = "w:Open-mid front rounded vowel", },	["ɜ"] = { title = "open-mid central unrounded vowel", link = "w:Open-mid central unrounded vowel", },	["ɝ"] = { title = "open-mid central unrounded vowel+r", link = "w:R-colored vowel", },	["ɞ"] = { title = "open-mid central rounded vowel", link = "w:Open-mid central rounded vowel", },	["ʌ"] = { title = "open-mid back unrounded vowel", link = "w:Open-mid back unrounded vowel", },	["ɔ"] = { title = "open-mid back rounded vowel", link = "w:Open-mid back rounded vowel", },

-- near open ["æ"] = { title = "near-open front unrounded vowel", link = "w:Near-open front unrounded vowel", },	["ɐ"] = { title = "near-open central vowel", link = "w:Near-open central vowel", },

-- open ["a"] = { title = "open front unrounded vowel", link = "w:Open front unrounded vowel", },	["ɶ"] = { title = "open front rounded vowel", link = "w:Open front rounded vowel", },	["ɑ"] = { title = "open back unrounded vowel", link = "w:Open back unrounded vowel", },	["ɒ"] = { title = "open back rounded vowel", link = "w:Open back rounded vowel", },

-- SUPRASEGMENTALS ["ˈ"] = {title = "primary stress", link = "w:Stress (linguistics)", XSAMPA = "\""},	--	["???"] = {		title = "extra stress: no Unicode char; double primary stress instead",		link = "w:extra stress: no Unicode char; double primary stress instead",		XSAMPA = ""	}, --TOMOVE:3 	["ˌ"] = {		title = "secondary stress",		link = "w:Secondary stress",	},	["ː"] = {		title = "long",		link = "w:Length (phonetics)",	},	["ˑ"] = {		title = "half long",		link = "w:Length (phonetics)",	},	["̆"] = {		title = "extra-short",		link = "w:Length (phonetics)",	},	--	["%."] = {		title = "syllable break",		link = "w:syllable break",	},		--TOMOVE	["‿"] = {		title = "linking mark (absence of a break)",		link = "w:Tie (typography)#International_Phonetic_Alphabet",	},

[" "] = {		title = "separator", link = "w:separator", },

-- TONE

-- level tones ["˥"] = {		title = "top", link = "w:Tone letter", },	["˦"] = {		title = "high", link = "w:Tone letter", },	["˧"] = {		title = "mid", link = "w:Tone letter", },	["˨"] = {		title = "low", link = "w:Tone letter", },	["˩"] = {		title = "bottom", link = "w:Tone letter", },

["̋"] = {		title = "extra high tone", link = "w:Tone letter", },	["́"] = {		title = "high tone", link = "w:Tone letter", },	["̄"] = {		title = "mid tone", link = "w:Tone letter", },	["̀"] = {		title = "low tone", link = "w:Tone letter", },	["̏"] = {		title = "extra low tone", link = "w:Tone letter", },

-- tone terracing ["ꜛ"] = { title = "upstep", link = "w:Upstep", },	["ꜜ"] = { title = "downstep", link = "w:Downstep", },

-- contour tones ["̌"] = {		title = "rising tone", link = "w:Tone (linguistics)", },	["̂"] = {		title = "falling tone", link = "w:Tone (linguistics)", },	["᷄"] = {		title = "high rising tone", link = "w:Tone (linguistics)", },	["᷅"] = {		title = "low rising tone", link = "w:Tone (linguistics)", },	["᷇"] = {		title = "high falling tone", link = "w:Tone (linguistics)", },	["᷆"] = {		title = "low falling tone", link = "w:Tone (linguistics)", },	["᷈"] = {		title = "rising falling tone (peaking)", link = "w:Tone (linguistics)", },	["᷉"] = {		title = "dipping", link = "w:Tone (linguistics)", }, -- [extrapolated from the chart -- please confirm]

-- intonation ["|"] = {		title = "minor (foot) group", link = "w:Prosodic unit", },	["‖"] = {		title = "major (intonation) group", link = "w:Prosodic unit", },	["↗"] = {		title = "global rise", link = "w:Intonation (linguistics)", },	["↘"] = {		title = "global fall", link = "w:Intonation (linguistics)", },

-- DIACRITICS

-- syllabicity & releases ["̩"] = {		title = "syllabi ", link = "w:Syllabic consonant", withdescender = "̍" }, -- (or "_="	["̯"] = {		title = "non-syllabic",		link = "w:Semivowel",		withdescender = "̑"	},	["ʰ"] = {		title = "aspirated",		link = "w:Aspirated consonant",	},	["ⁿ"] = {		title = "nasal release",		link = "w:Nasal release",	},	["ˡ"] = {		title = "lateral release",		link = "w:Lateral release (phonetics)",	},	["̚"] = {		title = "no audible release",		link = "w:No audible release",	},

-- phonation ["̥"] = {		title = "voiceless", link = "w:Voicelessness", withdescender = "̊" },	["̬"] = {		title = "voiced", link = "w:Voice (phonetics)", },	["̤"] = {		title = "breathy voice", link = "w:Breathy voice", },	["̰"] = {		title = "creaky voice", link = "w:Creaky voice", },	["᷽"] = {		title = "strident", link = "w:Strident vowel", },

-- primary articulation ["̪"] = {		title = "dental", link = "w:Dental consonant", },	["̺"] = {		title = "apical", link = "w:Apical consonant", },	["̻"] = {		title = "laminal", link = "w:Laminal consonant", },	["̟"] = {		title = "advanced", link = "w:Relative articulation#Advanced_and_retracted", withdescender = "˖" },	["̠"] = {		title = "retracted", link = "w:Relative articulation#Retracted", withdescender = "˗" },	["̼"] = {		title = "linguolabial", link = "w:Linguolabial consonant", },	["̈"] = {		title = "centralized", link = "w:Relative articulation#Centralized_vowels", XSAMPA = "_\""	},	["̽"] = {		title = "mid-centralized",		link = "Relative articulation#Mid-centralized_vowel",	},	["̞"] = {		title = "lowered",		link = "w:Relative articulation#Raised_and_lowered",		withdescender = "˕"	},	["̝"] = {		title = "raised",		link = "w:Relative articulation#Raised_and_lowered",		withdescender = "˔"	},	["͡"] = {		title = "coarticulated",		link = "w:Co-articulated consonant",	},	["͈"] = {		title = "strong articulation",		link = "w:Fortis and lenis",	},

-- secondary articulation ["ʷ"] = { title = "labialized", link = "w:Labialization", },	["ʲ"] = { title = "palatalized", link = "w:Palatalization (phonetics)", },	["ˠ"] = { title = "velarized", link = "w:Velarization", },	["ˤ"] = { title = "pharyngealized", link = "w:Pharyngealization", },	-- also see _e ["ɫ"] = { title = "velarized alveolar lateral approximant", link = "w:Alveolar lateral approximant", },	["̴"] = {		title = "velarized or pharyngealized; also see 5", link = "w:Velarization", },	["̹"] = {		title = "more rounded", link = "w:Roundedness", },	["̜"] = {		title = "less rounded", link = "w:Roundedness", },	["̃"] = {		title = "nasalization", link = "w:Nasalization", },	["˞"] = {		title = "rhotacization in vowels, retroflexion in consonants", link = "w:R-colored vowel", },	["̘"] = {		title = "advanced tongue root", link = "w:Advanced and retracted tongue root", },	["̙"] = {		title = "retracted tongue root", link = "w:Advanced and retracted tongue root", },

}

data[2] = { -- TODO --["%("] = {},	--["%)"] = {},

["ːː"] = { title = "extra long", link = "w:Length (phonetics)", },

["r̥"] = {title = "voiceless alveolar trill", link = "w:Voiceless alveolar trill"}, ["ɬ’"] = {title = "alveolar lateral ejective fricative", link = "w:Alveolar lateral ejective fricative"}, } data[3] = { ["t͡s"] = {title = "voiceless alveolar sibilant affricate", link = "w:Voiceless alveolar affricate"}, ["d͡z"] = {title = "voiced alveolar sibilant affricate", link = "w:Voiced alveolar affricate"}, ["t͡ʃ"] = {title = "voiceless palato-alveolar affricate", link = "w:Voiceless palato-alveolar affricate", descender = true}, ["d͡ʒ"] = {title = "voiced palato-alveolar affricate", link = "w:Voiced palato-alveolar affricate"}, ["ʈ͡ʂ"] = {title = "voiceless retroflex affricate", link = "w:Voiceless retroflex affricate", descender = true}, ["ɖ͡ʐ"] = {title = "voiced retroflex affricate", link = "w:Voiced retroflex affricate, descender = true"}, ["t͡ɕ"] = {title = "voiceless alveolo-palatal affricate", link = "w:Voiceless alveolo-palatal affricate"}, ["d͡ʑ"] = {title = "voiced alveolo-palatal affricate", link = "w:Voiced alveolo-palatal affricate"},

["c͡ç"] = {title = "voiceless palatal affricate", link = "w:Voiceless palatal affricate, descender = true"}, ["ɟ͡ʝ"] = {title = "voiced palatal affricate", link = "w:Voiced palatal affricate, descender = true"}, ["k͡x"] = {title = "voiceless velar affricate", link = "w:Voiceless velar affricate"}, ["ɡ͡ɣ"] = {title = "voiced velar affricate", link = "w:Voiced velar affricate, descender = true"}, } data[4] = { ["ǃ͡qʼ"] = {title = "alveolar linguo-glottalic stop", link = "w:Ejective-contour clicks, descender = true"}, ["ǁ͡χʼ"] = {title = "lateral linguo-glottalic affricate (homorganic)", link = "w:Ejective-contour clicks", descender = true}, } data[5] = { ["k͡ʟ̝̊"] = {title = "voiceless velar lateral affricate", link = "w:Voiceless velar lateral affricate"}, ["ᶢǀ͡qʼ"] = {title = "voiced dental linguo-glottalic stop", link = "w:Ejective-contour clicks"}, ["ǂ͡kxʼ"] = {title = "palatal linguo-glottalic affricate (heterorganic)", link = "w:Ejective-contour clicks"}, } data[6] = { ["k͡ʟ̝̊ʼ"] = {title = "velar lateral ejective affricate", link = "w:Velar lateral ejective affricate"}, ["ᶢʘ͡kxʼ"] = {title = "voiced labial linguo-glottalic affricate", link = "w:Ejective-contour clicks"}, }

-- acute and grave tone marks data["diacritics"] = --	grave, 		acute,		circumflex,	tilde,		macron, 	breve U(0x300) .. U(0x301) .. U(0x302) .. U(0x303) .. U(0x304) .. U(0x306) --	diaeresis,	ring above, 	double acute,	caron,		vertical line above,	double grave,	left tack ..	U(0x308) .. U(0x30A) .. U(0x30B) .. U(0x30C) .. U(0x30D) .. U(0x30F) .. U(0x318) --	right tack,	left angle,	left half ring below,	up tack below,	down tack below,	plus sign below ..	U(0x319) .. U(0x31A) .. U(0x31C) .. U(0x31D) .. U(0x31E) .. U(0x31F) --	minus sign below,	rhotic hook below,	dot below, 	diaeresis below,	ring below,	vertical line below, 	bridge below ..	U(0x320) .. U(0x322) .. U(0x323) .. U(0x324) .. U(0x325) .. U(0x329) .. U(0x32A) --	caron below, 	inverted breve below ..	U(0x32C) .. U(0x32F) --	tilde below, 	combining tilde overlay,	right half ring below,	inverted bridge below,	square below,	seagull below,	x above ..	U(0x330) .. U(0x334) .. U(0x339) .. U(0x33A) .. U(0x33B) .. U(0x33C) .. U(0x33D) --	grave tone mark,	acute tone mark,	bridge above,	equals sign below,	double vertical line below ..	U(0x340) .. U(0x341) .. U(0x346) .. U(0x347) .. U(0x348) --	left angle below,	not tilde above,	homothetic above,	almost equal above,	left right arrow below ..	U(0x349) .. U(0x34A) .. U(0x34B) .. U(0x34C) .. U(0x34D) --	upwards arrow below, 	left arrowhead below, 	right arrowhead below ..	U(0x34E) .. U(0x354) .. U(0x355) --	double rightwards arrow below,	combining Latin small letter a	..	U(0x362) .. U(0x361) --	macron–acute,	grave–macron,	macron–grave,	acute–macron,	grave–acute–grave,	acute–grave–acute ..	U(0x1DC4) .. U(0x1DC5) .. U(0x1DC6) .. U(0x1DC7) .. U(0x1DC8) .. U(0x1DC9) data["tones"] = '˥˦˧˨˩꜒꜓꜔꜕꜖꜈꜉꜊꜋꜌꜍꜎꜏꜐꜑¹²³⁴⁵⁶⁷⁸⁹⁰' data["vowels"] = 'iyɨʉɯuɪʏʊeøɘɵɤoəɚɛœɜɝɞʌɔæɐaɶɑɒäëïöüÿ' data["superscripts"] = '¹²³⁴⁵⁶⁷⁸⁹⁰ᵝʰʱʲʳʴʵʶʷʸᶣ˞ˠˡˢꟹᵄᵊᵏᵐᶬᵑᶮᶯᶰᶹˀˤⁿᵇᵈᶢᶡᵡ' data["valid"] = U(0xA0) .. ' %(%)%%{%|%}%-~⁓.◌abcdefhijklmnopqrstuvwxyz¡àáâãāăēäæçèéêëĕěħìíîïĩīĭĺḿǹńňðòóôõöōŏőœøŕùúûüũūŭűýÿŷŋ' .. 'ǀǁǂǃǎǐǒǔřǖǘǚǜǟǣǽǿȁȅȉȍȕȫȭȳɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɪɫɬɭɮɯɰɱɲɳɴɵɶɸɹɺ𝼈ɻɽɾʀʁʂʃʄʈʉʊʋṽʌʍʎ𝼆ʏʐʑʒʔʕʘʙʛʜʝʟʡʢʬʭ⁻' .. 'ʼˈˌːˑˣ˔˕ˬ͗˭ˇ˖β͜θχᴙᶑ᷽ḁḛḭḯṍṏṳṵṹṻạẹẽịọụỳỵỹ‖․‥…‼‿↑↓↗↘ⱱꜛꜜꟸ𝆏𝆑˗' .. data.diacritics .. data.tones .. data.superscripts

-- Characters to add VARIATION SELECTOR-15 (U+FE0E) after. -- These are characters with emoji variants that are used by default by some clients. -- Adding VS15 after them instructs them to draw the characters as text instead. data["add_vs15"] = "‼↗↘"

data["suggestions"] = { ["g"] = "ɡ", ["'"] = "ˈ", ["’"] = "ʼ", [""] = "",	[":"] = "ː", ["ˁ"] = "ˤ", ["ǝ"] = "ə", ["ә"] = "ə", -- Syllabic fricatives ["ɿ"] = "z̩", ["ʅ"] = "ʐ̩", ["ʮ"] = "z̩ʷ", ["ʯ"] = "ʐ̩ʷ", ["Ɂ"] = "ʔ", -- Deprecated symbols ["ɩ"] = "ɪ", ["ɷ"] = "ʊ", ["ᴜ"] = "ʊ", ["ʣ"] = "d͡z", ["ʤ"] = "d͡ʒ", ["ʥ"] = "d͡ʑ", ["ʦ"] = "t͡s", ["ʧ"] = "t͡ʃ", ["ʨ"] = "t͡ɕ", ["ʪ"] = "ɬ͡s", ["ʫ"] = "ɮ͡z", -- Greek letters ["α"] = "ɑ", ["γ"] = "ɣ", ["δ"] = "ð", ["ε"] = "ɛ", ["η"] = "ŋ", ["ι"] = "ɪ", ["λ"] = "ʎ", ["υ"] = "ʋ", ["ϕ"] = "ɸ", ["ꭓ"] = "χ", }

return data

title: Module:IPA/data/symbols


text:
Module:Parameters

local export = {}

local function track(page, calling_module, calling_function, param_name) local track = require("Module:debug/track") local tracking_page = "parameters/" .. page -- Cascades down in specificity, as each level is a prerequisite for the next. track(tracking_page) if calling_module then track(tracking_page .. "/" .. calling_module) if calling_function then track(tracking_page .. "/" .. calling_module .. "/" .. calling_function) if param_name then track(tracking_page .. "/" .. calling_module .. "/" .. calling_function .. "/" .. param_name) end end end return true end

function export.process(args, params, return_unknown, calling_module, calling_function) local args_new = {} if not calling_module then track("no calling module") end if not calling_function then track("no calling function", calling_module) end -- Process parameters for specific properties local required = {} local patterns = {} local names_with_equal_sign = {} local list_from_index = nil for name, param in pairs(params) do		if param.required then if param.alias_of then track("required alias", calling_module, calling_function, name) end required[name] = true end if name == 1 and param.no_lang_code then if not params["notlangcode"] then error("The parameter \"notlangcode\" must be enabled for this template.", 2) elseif not args["notlangcode"] and require("Module:languages").getByCode(args[name]) then error("The parameter \"" .. name .. "\" should not be a language code.", 2) end end if param.list then -- A helper function to escape magic characters in a string -- Magic characters: ^$%.[]*+-? local plain = require("Module:string/pattern_escape")

local key = name if type(name) == "string" then key = string.gsub(name, "=", "") end if param.default ~= nil then args_new[key] = {param.default, maxindex = 1} else args_new[key] = {maxindex = 0} end if type(param.list) == "string" then -- If the list property is a string, then it represents the name -- to be used as the prefix for list items. This is for use with lists -- where the first item is a numbered parameter and the -- subsequent ones are named, such as 1, pl2, pl3. if string.find(param.list, "=") then patterns["^" .. string.gsub(plain(param.list), "=", "(%%d+)") .. "$"] = name else patterns["^" .. plain(param.list) .. "(%d+)$"] = name end elseif type(name) == "number" then -- If the name is a number, then all indexed parameters from -- this number onwards go in the list. list_from_index = name else if string.find(name, "=") then patterns["^" .. string.gsub(plain(name), "=", "(%%d+)") .. "$"] = string.gsub(name, "=", "") else patterns["^" .. plain(name) .. "(%d+)$"] = name end end if string.find(name, "=") then -- DO NOT SIDE-EFFECT A TABLE WHILE ITERATING OVER IT. -- Some elements may be skipped or processed twice if you do. -- Instead, track the changes we want to make to `params`, and -- do them after the iteration over `params` is done. table.insert(names_with_equal_sign, name) end elseif param.default ~= nil then args_new[name] = param.default end end

--Process required changes to `params`. if #names_with_equal_sign > 0 then local m_params_data = calling_module and mw.loadData("Module:parameters/data")[calling_module] -- If there is a ready-made version in the data module, use that. if m_params_data and m_params_data[calling_function .. "_no_equals"] then params = m_params_data[calling_function .. "_no_equals"] -- Otherwise, shallow copy the params table and substitute the keys. else params = require("Module:table").shallowcopy(params) for _, name in ipairs(names_with_equal_sign) do				track("name with equals", calling_module, calling_function, name) params[string.gsub(name, "=", "")] = params[name] params[name] = nil end end end

-- Process the arguments local args_unknown = {} local max_index for name, val in pairs(args) do		local index = nil if type(name) == "number" then if list_from_index ~= nil and name >= list_from_index then index = name - list_from_index + 1 name = list_from_index end else -- Does this argument name match a pattern? for pattern, pname in pairs(patterns) do				index = mw.ustring.match(name, pattern) -- It matches, so store the parameter name and the -- numeric index extracted from the argument name. if index then index = tonumber(index) name = pname break end end end local param = params[name] -- If a parameter without the trailing index was found, and -- require_index is set on the param, set the param to nil to treat it -- as if it isn't recognized. if not index and param and param.require_index then param = nil end -- If no index was found, use 1 as the default index. -- This makes list parameters like g, g2, g3 put g at index 1. -- If `separate_no_index` is set, then use 0 as the default instead. index = index or (param and param.separate_no_index and 0) or 1 -- If the argument is not in the list of parameters, trigger an error. -- return_unknown suppresses the error, and stores it in a separate list instead. if not param then if return_unknown then args_unknown[name] = val else error("The parameter \"" .. name .. "\" is not used by this template.", 2) end else -- Remove leading and trailing whitespace unless allow_whitespace is true. if not param.allow_whitespace then val = mw.text.trim(val) end -- Empty string is equivalent to nil unless allow_empty is true. if val == "" and not param.allow_empty then val = nil -- Track empty parameters, unless (1) allow_empty is set or (2) they're numbered parameters where a higher numbered parameter is also in use (e.g. track, but not term). if type(name) == "number" and not max_index then -- Find the highest numbered parameter that's in use/an empty string, as we don't want parameters like 500= to mean we can't track any empty parameters with a lower index than 500. local max_contiguous_index = 0 while args[max_contiguous_index + 1] do						max_contiguous_index = max_contiguous_index + 1 end if max_contiguous_index > 0 then for name, val in pairs(args) do							if type(name) == "number" and name > 0 and name <= max_contiguous_index and ((not max_index) or name > max_index) and val ~= "" then max_index = name end end end max_index = max_index or 0 end if type(name) ~= "number" or name > max_index then track("empty parameter", calling_module, calling_function, name) end end -- Convert to proper type if necessary. if param.type == "boolean" then val = require("Module:yesno")(val, true) elseif param.type == "number" then val = tonumber(val) elseif param.type then track("unrecognized type", calling_module, calling_function, name) track("unrecognized type/" .. tostring(param.type), calling_module, calling_function, name) end -- Can't use "if val" alone, because val may be a boolean false. if val ~= nil then -- Mark it as no longer required, as it is present. required[param.alias_of or name] = nil -- Store the argument value. if param.list then -- If the parameter is an alias of another, store it as the original, -- but avoid overwriting it; the original takes precedence. if not param.alias_of then args_new[name][index] = val -- Store the highest index we find. args_new[name].maxindex = math.max(index, args_new[name].maxindex) if args_new[name][0] then args_new[name].default = args_new[name][0] args_new[name][0] = nil end elseif args[param.alias_of] == nil then if params[param.alias_of] and params[param.alias_of].list then args_new[param.alias_of][index] = val -- Store the highest index we find. args_new[param.alias_of].maxindex = math.max(index, args_new[param.alias_of].maxindex) else args_new[param.alias_of] = val end end else -- If the parameter is an alias of another, store it as the original, -- but avoid overwriting it; the original takes precedence. if not param.alias_of then args_new[name] = val elseif args[param.alias_of] == nil then if params[param.alias_of] and params[param.alias_of].list then args_new[param.alias_of][1] = val -- Store the highest index we find. args_new[param.alias_of].maxindex = math.max(1, args_new[param.alias_of].maxindex) else args_new[param.alias_of] = val end end end end end end -- The required table should now be empty. -- If any entry remains, trigger an error, unless we're in the template namespace. if mw.title.getCurrentTitle.namespace ~= 10 then local list = {} for name, param in pairs(required) do			table.insert(list, name) end if #list > 0 then error('The parameters "' .. mw.text.listToText(list, '", "', '" and "') .. '" are required.', 2) end end -- Remove holes in any list parameters if needed. for name, val in pairs(args_new) do		if type(val) == "table" and not params[name].allow_holes then args_new[name] = require("Module:parameters/remove_holes")(val) end end if return_unknown then return args_new, args_unknown else return args_new end end

return export

title: Module:Parameters


text:
Module:Debug/track

return function(key) local frame = mw.getCurrentFrame if key then if type(key) ~= "table" then key = { key } end for i, value in pairs(key) do pcall(frame.expandTemplate, frame, { title = "tracking/" .. value }) end else error("No tracking key supplied to Module:debug/track.") end return true end

title: Module:Debug/track


text:
Module:String/pattern escape

return function (str) return mw.ustring.gsub(str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1") end

title: Module:String/pattern escape


text:
User:Moodybot

I'm creating this for only learning About electricity

title: User:Moodybot


text: Category:Grain recipes

title: Category:Grain recipes


text:
Category:Recipes by dish

Category to aggregate multiple recipes for the same essential dish.

title: Category:Recipes by dish


text: Sylheti/Lessons/Food and Drink

title: Sylheti/Lessons/Food and Drink


text: Template:Sylheti/Section

title: Template:Sylheti/Section


text:
A Guide to Discord

This is a helpful guide for users who are new to the chatting application Discord.

Table of Contents

 * /Servers/
 * /Bots/
 * /Emojis/
 * /User Status/
 * /Voice chatting/
 * /Nitro/
 * /Server Boosting/
 * /Permissions/
 * /Age-Restrictions/
 * /Connections/
 * /Keyboard shortcuts/
 * /Community programs/
 * /Easter Eggs/

title: A Guide to Discord


text: Category:Book:Discord

title: Category:Book:Discord


text:
A Guide to Discord/Servers

A server is a chatroom that can only be accessed via invite. Servers can be created for a variety of topics, including clubs, study groups, fandoms, role-playing, or simply casual conversation.

Channels
Communication is conducted via channels, themselves organized by category. There are four primary types of channels: text channels, voice channels, announcement channels, and stage channels.

 * Text channels are distinguished by the "#" sign.They allow you to send messages, as well as images, videos, files, and stickers. Some Discord servers will not allow you to upload media immediately after joining until you reach a certain level. To chat, enter your message in the text box at the bottom of the screen and press "Enter" to send.
 * Voice channels allow you to communicate via voice or video. For more information, see Voice chatting.
 * Announcement channels are primarily used by the server staff to announce changes to the server or server events. Non-staff members will rarely be able to send messages in this channel. Occasionally, the channel will be used for announcements outside of the server (for example, if the server is owned by a Twitch streamer, it will be used to announce when they are streaming). Following the announcement channel will add it to another server, so you can follow the announcements in your own server.
 * Stage channels are a special type of voice channel used for audio-only conversations where users talk and others listen.

Roles
Roles are used to organize users in a server. Some roles can be earned by extensive participation in the server. These roles are normally hierarchical, meaning the highest role is the most important. Other roles are purely for cosmetic purposes.

Threads
Threads are a temporary sub-channel that can be created within text channels. They are primarily used for specific topics or focused conversation. Threads are automatically archived after a certain amount of unactivity, ranging from an hour to a week.

Creating a server
Creating a Discord server is relatively simple. Scroll down to the bottom of your server list until you see the "+" icon (this may be near the top instead if you are using a mobile device). Enter a name for the server, and upload a server icon from your files. Click "create" when you are finished.

Inviting other users
Click the drop-down menu on the top-left, then select "Invite People". You will then see a list of your friends, with an Invite button next to them. Click on the button to send them an invite link.

Creating channels
Click on the drop-down menu on the top-left, then select "Create Channel". If you're on mobile, swipe right to view the channel list, click on the server's name and choose "create channel". Enter a name for your channel, ideally reflecting its intended purpose (i.e. "#gaming", "#music", "#memes"). Click "Create Channel" when you are finished.

If you want to restrict a channel to select members, click on the "Private Channel" option when you are making the channel. Then click "Next". From here you can decide which users have access to the channel. Click "Create" when you are finished. If you have created a text channel, you will be able to see a list of members who can have access to it. To edit this list, right-click on the channel, select "Edit Channel", and head to Permissions, where you will be able to adjust viewer settings.

Server Insights
Server Insights provides valuable feedback on engagement and other metrics to help community owners understand the health and activity of their server. By analyzing Server Insights, you can gain insights into visitor numbers, communicators, and new member retention.

Here's a breakdown of the terminology used in Server Insights:

 * Visitors: Visitors are members who have clicked on a channel in the server. It tracks whether a member has checked the server by clicking on a channel, regardless of whether they actively participate in conversations.

 * Communicators: Communicators are server members who have actively engaged with the server by posting in text channels or chatting in voice channels. They contribute to the conversations and interactions within the community.

 * New Member Retention: This metric shows the percentage of new members who return to your server after a week. It indicates how well your server is able to retain new members and keep them engaged over time.

To maintain a healthy level of engagement, it is recommended to aim for roughly 50% of your members visiting the server, with 50% of those visitors actively communicating and getting involved. Discord sets a benchmark of 30% communicators as a healthy goal.

If you notice a dip in engagement for a week or two, it's important not to panic. External factors like school or holidays can influence member activity. However, regularly checking Server Insights can help you determine whether it was just a temporary slowdown or if there are recurring patterns that need attention.

To create an environment that fosters engagement, consider the following tips:

 * Ensure that your server is organized, clutter-free, and visually appealing. Cut down on excess channels or fix any issues that may hinder members' navigation. A clean and user-friendly server inspires confidence and encourages members to stay longer.
 * Use the "Engage" section of Server Insights to identify channels that generate the most activity. Spark conversations by asking leading questions or discussing topics that resonate with your community's interests. Avoid having too many channels, as it can spread conversations thin and lead to lower overall engagement.

 * Monitor your server's speaking minutes and identify the voice channels that members use the most. Engage with your members in voice channels, hang out, and be available to support and bond with them. Teach new members about voice channels and encourage their participation.

 * Hosting events related to your community's interests can foster deeper connections among members. Schedule events that allow members to bond over shared interests, showcase their work, or learn new skills. Use the "Growth and Activation" section of Server Insights to track event-related member join rates and retention.

title: A Guide to Discord/Servers


text:
Infrastructure Past, Present, and Future Casebook/Guangzhou South Railway Station

This Casebook contains a set of case studies developed by Jason Reyes, Syed Shah, Zachary Zalewski, and Mario Pineda-Diaz, students enrolled in the Infrastructure Past, Present and Future (CEIE 499: Special Topics in Civil Engineering / GOVT 490: Synthesis Seminar for Policy and Government) course taught at George Mason University's Schar School of Policy and Government and the Sid and Reva Dewberry Department of Civil, Environmental, and Infrastructure Engineering by Prof. Jonathan Gifford.

Summary

The Guangzhou South Railway Station, also known as Guangzhou Nan Railway Station, stands as a colossal transportation hub located in the southern part of Guangzhou, the capital city of Guangdong Province in southern China. Serving as a key gateway to the high-speed rail network connecting major cities, it is a modern marvel of engineering and urban planning, reflecting the rapid development and urbanization of the region. This station not only embodies China's commitment to expanding and modernizing its transportation infrastructure but also plays a pivotal role in facilitating travel, trade, and cultural exchange, both within China and beyond.

The station's design and scale are truly impressive. It features expansive concourses, multiple structures, and a complex network of tracks, allowing it to handle a substantial volume of passengers and trains. What sets it apart is the architectural design that seamlessly merges contemporary aesthetics with traditional Chinese elements, creating a visually striking and culturally rich environment for travelers. Whether you are embarking on a high-speed rail journey to other major Chinese cities, immersing yourself in Guangzhou's vibrant culture, or simply passing through, the Guangzhou South Railway Station stands as a testament to China's commitment to modern transportation infrastructure.

High-Speed Rail
Beijing-Guangzhou High-speed Railway

Guangzhou-Shenzhen-Hong Kong High-speed Railway

Guiyang-Guangzhou High-speed Railway

Inter-City Rail
Nan-Guang Railway Intercity Railway

Guangzhou-Zhuhai Intercity Railway

Guanghui Intercity Railway (under construction)

Guangzhou Metro
Metro Line 2

Metro Line 7

Metro Line 22

Foshan Metro
Metro Line 2

Floors of Station
3rd Floor - West drop-off area, entrance, security check, waiting hall, business lounge, and restaurants

2nd Floor - Platforms, railway tracks, and east drop-off area

1st Floor -Arrivals, exit, metro exit / entrance, ticket office, bus stop, taxi drop-off and pick-up, restaurants, and parking lot

Base Floor - Metro line 2 and line 7 station

Timeline

 * 30 December 2004 – Construction commences
 * 30 January 2010 – Partial opening of the station with services north to Wuhan
 * 25 September 2010 – Metro station opened
 * 7 January 2011 – Services to Zhuhai North and Xinhui commences
 * 26 December 2011 – Service to Shenzhen North commences
 * 26 December 2012 – Service to Beijing West commences
 * 26 December 2014 – Services to Nanning East and Guiyang North commences
 * 30 December 2015 – Services to Futian commences
 * 23 September 2018 – Service to Hong Kong West Kowloon commences

Technical Data
Length / width / height:  450m / 400 m / 40 m

Total area:   approx. 320,000 m²

Area base-level: approx. 160,000 m²

Area railway-level:  approx. 100,000 m²

Area entrance- and access-level:   approx. 60,000 m²

Roof area:    approx. 200,000 m²

Roof span:   50 - 100 m

Designed to accommodate 200,000 daily

Finance
The total cost of the Guangzhou South Railway Station is ¥13 billion RMB or $1.8 billion USD.

SPBs (Special-Purpose Bonds)
The primary way China finances its infrastructure projects including the Guangzhou South Railway Station is by issuing SPBs (Special-Purpose Bonds). SPBs (Special-Purpose Bonds) are bonds that local governments in China use to fund projects, especially infrastructure. The SPBs can only be used to finance the project that they were issued for. The Chinese State Railway Group Company, which is state owned, was also able to take out loans from state owned banks to finance the project. Land in China is controlled by the government therefore relocating people already living in the area of development is very cheap. The local government is also able to lease out the land around the station to gain more capital to further finance the project. By allowing local governments such as the province of Guangdong to take out bonds they are able to fund projects such as the Guangzhou South Railway Station to address the necessities of their province and region within China.

The Chinese economy is heavily reliant on infrastructure construction therefore there are a lot of incentives for the construction of mega projects like the Guangzhou South Railway Station.

Key Actors
The Guangzhou South Railway Station has many key actors; these entities are state owned companies that have rail lines that run through the Guangzhou South Railway Station and connect Guangzhou to the rest of the Pearl River Delta Metro Area as well as the rest of China.

Government of the People's Republic of China - One party government run by the Chinese Communist Party. The Chinese Communist Party has the Ministry of Railways to oversee rail across the country. Owners of the state owned railway companies.

Chinese State Railway Group Company - The state owned company that is responsible for operating the railways system across the People’s Republic of China.

Guangzhou Metro Group Company - State owned company of mass rapid transit metro system that connects the city of Guangzhou.

Guangdong Intercity Railway Operation Company - State owned company that runs rails services across the Guangdong Province

Foshan Metro Group Company - State owned company that runs mass rapid transit metro system that connects the city of Foshan.

Impact on Surrounding Area
The Guangzhou South Railway Station has allowed for Guangzhou to be one of the biggest transportation hubs in all of China. The Guangzhou South Railway station transformed much of the land around the station and has been developed to cater to passengers and businesses. The Guangzhou South Railway Station Business District has developed around the station which includes the construction of many modern and higher end offices and apartments. There is currently an emergence of schools and medical centers to cater to the influx of the new people around the station. Due to construction of the railway station. This all has attracted a large influx of people with higher education into the areas around the rail station.

Expansion Plans
There is currently construction being done in the Guangzhou South Railway Station. There is an interchange platform being created as an underground tunnel that connects Foshan Metro Line 2 platform and Guangzhou Metro Line 2 & 7. Currently, for passengers traveling between Foshan Metro and Guangzhou Metro, they need to exit the metro station and walk for about 400 meters, which takes over 10 minutes for interchange. Once completed, the interchange time would be shorten to less than 5 minutes. The former construction site will also be repurposed as a parking lot for taxi drivers.

Another expansion plan has also already begun construction. The Guangzhou Railway Station to Guangzhou South Railway Station railway will be linked together by a new train line. Currently, there is no direct railway line connecting Guangzhou Railway Station to Guangzhou South Railway Station; passengers need to switch between the two stations using Guangzhou's subway system, bus or taxi. The construction of the rail link is estimated to take four years, with the anticipated launch of operations by late 2027.

Pros
The introduction of the Guangzhou South Rail Station has aided China's strategy of spawning economic development along the Beijing-Guangzhou High-Speed Rail lane (hereafter BGHSR). Since 2012, a few months after the BGHSR line opened, the Polar-Orbiting Partnership (known locally as the Suomi-NPP) has been collecting Night-Time Light images of China using satellites. In a paper published in the Socio-Economic Planning Sciences journal, researchers from Wuhan University analyzed the Night-Time Light photographs using the Sum Light Values (SLV) method. SLV measures the light emitted at night on an image of a region over time. A higher concentration of lights per pixel on an image affirms active urban development in the region.

The researchers from Wuhan University observed a rapid increase of approximately 50% SLV pixels per image in Guangzhou between 2012 and 2014. The researchers observed similar patterns of Night-Time Light growth along the BGHSR line with various Tier 1 cities in China—including Beijing, Wuhan, and Changsha—between 2012 and 2018. This rapid growth trend, however, did not continue in the lower-tier cities. Tier 2 and Tier 3 SLV data remained relatively muted between 2012 and 2018, suggesting that new transportation infrastructure projects (the BGHSR and the South Rail Station) in Guangzhou did not ripple the growth along to the lower tiers.

Cons
Amidst the pros of the new Guangzhou South Rail Station, a potential negative externality of focusing on Tier 1 cities could be that large infrastructure projects in mega cities might leave lower-tier neighboring cities behind in the urban development race across China.

Conclusion
In summary, the Guangzhou South Railway Station is a transportation hub located in China. It showcases not only engineering and urban planning skills but also China's unwavering commitment, to improving its transportation infrastructure. This project successfully combines aesthetics with Chinese elements demonstrating the nation's dedication to progress while honoring its rich cultural heritage. The station's extensive network of rail connections plays a role in facilitating travel, trade, and cultural exchange not only within China but also on an international scale.

The financial strategies employed in the station's construction, such as issuing Special Purpose Bonds (SPBs) and utilizing state-owned loans highlight the government's belief in infrastructure as a catalyst for growth. In addition to its transportation significance, the Guangzhou South Railway Station has spurred the growth of a business district that attracts medical institutions. This development has contributed to raising standards and improving living conditions in the area.

Future expansion plans include building an interchange platform and establishing a railway link between Guangzhou Railway Station and Guangzhou South Railway Station. These initiatives underscore the station's role, in connecting cities and promoting growth. However, it is important to take into account the consequences, for cities nearby that could be overlooked as China focuses on urban development. To sum up, the Guangzhou South Railway Station represents progress. Showcases how infrastructure can drive growth and shape regions. This emphasizes the significance of considerate infrastructure development, in our world.

Discussion Questions

 * 1) How has the station adapted to the needs of travelers, such as providing amenities, services, and accessibility for people with disabilities?
 * 2) What are the challenges and opportunities in maintaining and upgrading Guangzhou South Railway Station to meet the growing demand for rail travel?