This module is not to be directly used. It is used by Template:an-pr, see there for usage.
--Adapted from ] by ]
local export = {}
-- Standard MediaWiki module dependencies
local m_IPA = require("Module:IPA")
local m_table = require("Module:table")
local m_audio -- Lazily required
local m_put_utils = require("Module:parse utilities")
local links_module = require("Module:links")
local parameters_module = require("Module:parameters")
local pron_qualifier_module -- Lazily required
local references_module -- Lazily required
local rhymes_module -- Lazily required
local hyphenation_module -- Lazily required
local homophones_module -- Lazily required
local force_cat = false -- for testing
local lang = require("Module:languages").getByCode("an")
-- ustring aliases
local u = mw.ustring.char
local rfind = mw.ustring.find
-- local rsubn_mw = mw.ustring.gsub
local rmatch = mw.ustring.match
local rsplit = mw.text.split
local ulower = mw.ustring.lower
local uupper = mw.ustring.upper
local usub = mw.ustring.sub
local ulen = mw.ustring.len
local unfd = mw.ustring.toNFD
local unfc = mw.ustring.toNFC
local ustring = mw.ustring
local ugsub = mw.ustring.gsub
local AC = u(0x0301)
local GR = u(0x0300)
local CFLEX = u(0x0302)
local TILDE = u(0x0303)
local DIA = u(0x0308)
local SYLDIV = u(0xFFF0)
local vowel = "aeiouüyAEIOUÜY"
local V = ""
local accent = AC .. GR .. CFLEX
local accent_c = ""
local stress = AC .. GR
local stress_c = ""
local ipa_stress = "ˈˌ"
local ipa_stress_c = ""
local sylsep = "%-." .. SYLDIV
local sylsep_c = ""
local wordsep = "# "
local separator_not_wordsep = accent .. ipa_stress .. sylsep
local separator = separator_not_wordsep .. wordsep
local separator_c = ""
local C = ""
local C_NOT_H = ""
local C_OR_WORDSEP = ""
local T = ""
local unstressed_words = m_table.listToSet({
"o", "ro", "a", "ra", "os", "as", "ros", "ras",
"un", "una", "uns", "unas",
"de", "a", "en", "con", "por", "per", "pa", "ta",
"y", "e", "u",
"que",
"me", "te", "se", "lo", "la", "li", "nos", "vos", "los", "las", "lis",
"en", "ne", "bi", "hi"
})
local function rsub(term, foo, bar)
local retval = ugsub(term, foo, bar)
return retval
end
local function rsubb(term, foo, bar)
local retval, nsubs = ugsub(term, foo, bar)
return retval, nsubs > 0
end
local function rsub_repeatedly(term, foo, bar)
while true do
local new_term = rsub(term, foo, bar)
if new_term == term then
return term
end
term = new_term
end
end
local function decompose(text)
text = unfd(text)
text = rsub(text, ".", {
= "ñ",
= "Ñ",
= "ü",
= "Ü",
})
return text
end
local function split_on_comma_func(term)
if not term then return nil end
if not m_put_utils then m_put_utils = require("Module:parse utilities") end
if term:find(",%s") then
return m_put_utils.split_on_comma(term)
elseif term:find(",") then
return rsplit(term, ",")
else
return {term}
end
end
local function convert_to_raw_text(text)
text = rsub(text, "<.->", "")
if not links_module then links_module = require("Module:links") end
if text:find("%[%[") then
text = links_module.remove_links(text)
end
return text
end
local function textual_len(text)
return ulen(convert_to_raw_text(text))
end
local function syllabify_from_spelling_or_pronun(text, is_spelling)
text = rsub_repeatedly(text, "(" .. V .. accent_c .. "*)(" .. C_NOT_H .. V .. ")", "%1.%2")
text = rsub_repeatedly(text, "(" .. V .. accent_c .. "*" .. C .. "+)(" .. C .. V .. ")", "%1.%2")
local cluster_r = is_spelling and "rɾ" or "ɾ"
text = rsub(text, "()%.()", ".%1%2")
text = ugsub(text, "d%.()", ".d%1")
text = rsub(text, "()%.h", ".%1h")
text = rsub(text, "r%.r", ".rr")
text = rsub(text, "t%.z", ".tz")
text = rsub_repeatedly(text, "(" .. accent_c .. "*)(h?)", "%1.%2")
text = rsub_repeatedly(text, "(" .. accent_c .. "*)(h?" .. V .. stress_c .. ")", "%1.%2")
text = rsub(text, "(" .. stress_c .. ")(h?)", "%1.%2")
text = rsub_repeatedly(text, "(" .. stress_c .. ")(h?" .. V .. stress_c .. ")", "%1.%2")
text = rsub_repeatedly(text, "(" .. accent_c .. "*)(h?i)", "%1.%2")
text = rsub_repeatedly(text, "(" .. accent_c .. "*)(h?u)", "%1.%2")
return text
end
local function syllabify_from_spelling(text)
text = decompose(text)
local TEMP_I = u(0xFFF1); local TEMP_U = u(0xFFF2); local TEMP_Y_CONS = u(0xFFF3)
local TEMP_QU = u(0xFFF4); local TEMP_QU_CAPS = u(0xFFF5); local TEMP_GU = u(0xFFF6)
local TEMP_GU_CAPS = u(0xFFF7); local TEMP_H = u(0xFFF8); local TEMP_NY = u(0xFFF9)
local TEMP_NY_CAPS = u(0xFFFA); local TEMP_LL = u(0xFFFB); local TEMP_LL_CAPS = u(0xFFFC)
text = rsub(text, "ny", TEMP_NY); text = rsub(text, "Ny", TEMP_NY_CAPS)
text = rsub(text, "ll", TEMP_LL); text = rsub(text, "Ll", TEMP_LL_CAPS)
text = ugsub(text, "", SYLDIV)
text = rsub(text, "y(" .. V .. ")", TEMP_Y_CONS .. "%1")
text = ugsub(text, "^(es)h", "%1" .. TEMP_H)
text = ugsub(text, "(es)h", "%1" .. TEMP_H)
text = rsub(text, "qu(" .. V .. ")", TEMP_QU .. "%1"); text = rsub(text, "Qu(" .. V .. ")", TEMP_QU_CAPS .. "%1")
text = rsub(text, "gu(" .. V .. ")", TEMP_GU .. "%1"); text = rsub(text, "Gu(" .. V .. ")", TEMP_GU_CAPS .. "%1")
local vowel_to_glide_temp = { = TEMP_I, = TEMP_U }
text = rsub_repeatedly(text, "(.*" .. V .. accent_c .. "*)(h?)()(" .. V .. ")",
function (v1, h, iu, v2) return v1 .. "." .. h .. vowel_to_glide_temp .. v2 end
)
text = syllabify_from_spelling_or_pronun(text, "is spelling")
text = ugsub(text, SYLDIV, "."); text = ugsub(text, TEMP_I, "i"); text = ugsub(text, TEMP_U, "u")
text = ugsub(text, TEMP_Y_CONS, "y"); text = ugsub(text, TEMP_QU, "qu"); text = ugsub(text, TEMP_QU_CAPS, "Qu")
text = ugsub(text, TEMP_GU, "gu"); text = ugsub(text, TEMP_GU_CAPS, "Gu"); text = ugsub(text, TEMP_H, "h")
text = ugsub(text, TEMP_NY, "ny"); text = ugsub(text, TEMP_NY_CAPS, "Ny")
text = ugsub(text, TEMP_LL, "ll"); text = ugsub(text, TEMP_LL_CAPS, "Ll")
text = unfc(text)
return text
end
-- Generate the IPA of a given respelling
function export.IPA(text)
-- start at FFF1 because FFF0 is used for SYLDIV
local TEMP_Y = u(0xFFF1)
local TEMP_W = u(0xFFF2)
text = ulower(text or mw.title.getCurrentTitle().text)
-- decompose everything but ñ and ü
text = decompose(text)
-- convert commas and en/en dashes to IPA foot boundaries
text = rsub(text, "%s*%s*", " | ")
-- question mark or exclamation point in the middle of a sentence -> IPA foot boundary
text = rsub(text, "()%s*%s*()", "%1 | %2")
-- canonicalize multiple spaces and remove leading and trailing spaces
local function canon_spaces(text)
text = rsub(text, "%s+", " ")
text = rsub(text, "^ ", "")
text = rsub(text, " $", "")
return text
end
text = canon_spaces(text)
-- Make prefixes unstressed unless they have an explicit stress marker; also make certain
-- monosyllabic words (e.g. ], ], ], ], etc.) without stress marks be
-- unstressed.
local words = rsplit(text, " ")
for i, word in ipairs(words) do
if rfind(word, "%-$") and not rfind(word, accent_c) or unstressed_words then
-- add CFLEX to the last vowel not the first one, or we will mess up 'que' by
-- adding the CFLEX after the 'u'
words = rsub(word, "^(.*" .. V .. ")", "%1" .. CFLEX)
end
end
text = table.concat(words, " ")
-- Convert hyphens to spaces, to handle ], ], etc; with the exception of verbal clitics (with the temporary symbol @)
text = rsub(text, "-se", "@se")
text = rsub(text, "-te", "@te")
text = rsub(text, "-me", "@me")
text = rsub(text, "-tos", "@tos")
text = rsub(text, "-vos", "@vos")
text = rsub(text, "-nos", "@nos")
text = rsub(text, "-mos", "@mos")
text = rsub(text, "-lo", "@lo")
text = rsub(text, "-el", "@el")
text = rsub(text, "-los", "@los")
text = rsub(text, "-es", "@es")
text = rsub(text, "-la", "@la")
text = rsub(text, "-las", "@las")
text = rsub(text, "-le", "@le")
text = rsub(text, "-li", "@li")
text = rsub(text, "-les", "@les")
text = rsub(text, "-lis", "@lis")
text = rsub(text, "-en", "@en")
text = rsub(text, "-ne", "@ne")
text = rsub(text, "-i", "@i")
text = rsub(text, "-bi", "@bi")
text = rsub(text, "%-", " ")
text = rsub(text, "@", "-")
-- canonicalize multiple spaces again, which may have been introduced by hyphens
text = canon_spaces(text)
-- now eliminate punctuation
text = rsub(text, "", "")
-- put # at word beginning and end and double ## at text/foot boundary beginning/end
text = rsub(text, " | ", "# | #")
text = "##" .. rsub(text, " ", "# #") .. "##"
--glides
text = rsub(text, "#y" .. CFLEX, "#i" .. CFLEX) -- conjunction
text = rsub(text, "ny", "ɲ")
text = rsub(text, "y", "ʝ")
text = rsub(text, "hi()", "ʝ%1")
-- handle certain combinations; sh handling needs to go before x handling to avoid issues with ]
text = rsub(text, "ch", "ĉ") --not the real sound
text = rsub(text, "ll", "ʎ")
text = rsub(text, "#ps", "#s") -- ]
text = rsub(text, "x", "ʃ")
--c, g, q
text = rsub(text, "c()", "θ%1")
text = rsub(text, "z", "θ")
text = rsub(text, "g()", "x%1")
text = rsub(text, "gu()", "g%1")
text = rsub(text, "gü()", "gu%1")
text = rsub(text, "qü()", "ku%1")
text = rsub(text, "ng()", "n%1") -- TODO is this really needed?
text = rsub(text, "qu()", "k%1")
text = rsub(text, "q", "k") -- ]
text = rsub(text, "()iʃ", "%1Iʃ")
-- map various consonants to their phoneme equivalent
text = rsub(text, "", {="k", ="x", ="ɲ", ="ɾ", ="b"})
--pronunciation of <r>/<rr>
text = rsub(text, "ɾɾ", "r")
text = rsub(text, "()ɾ", "%1r")
text = rsub(text, "ɾ#", "R#")
text = rsub(text, "ɾ%-", "R-")
-- voiceless stop to voiced before obstruent or nasal (see Basic Grammar of Aragonese)
local voice_stop = { = "b", = "d", = "g" }
text = rsub(text, "()(" .. separator_c .. "*" .. T .. ")",
function(stop, after) return voice_stop .. after end)
text = rsub(text, "!", "t")
text = rsub(text, "n(*)", "m%1")
-- remove silent h and · before syllable division
text = rsub(text, "h", "")
text = rsub(text, "·", ".")
-- convert i/u between vowels to glide
local vowel_to_glide = { = "j", = "w" }
text = rsub_repeatedly(text, "(.*" .. V .. accent_c .. "*h?)()(" .. V .. ")",
function (v1, iu, v2) return v1 .. vowel_to_glide .. v2 end
)
--syllable division
text = syllabify_from_spelling_or_pronun(text, false)
--diphthongs; do not include TEMP_Y here
text = rsub(text, "i()", "j%1")
text = rsub(text, "u()", "w%1")
local accent_to_stress_mark = { = "ˈ", = "ˌ", = "" }
local function accent_word(word, syllables)
-- Now stress the word. If any accent exists in the word (including ^ indicating an unaccented word),
-- put the stress mark(s) at the beginning of the indicated syllable(s). Otherwise, apply the default
-- stress rule.
if rfind(word, accent_c) then
for i = 1, #syllables do
syllables = rsub(syllables, "^(.*)(" .. accent_c .. ")(.*)$",
function(pre, accent, post) return accent_to_stress_mark .. pre .. post end
)
end
else
-- Default stress rule. Words without vowels (e.g. IPA foot boundaries) don't get stress.
if #syllables > 1 and (rfind(word, "#") or rfind(word, C .. "#")) or #syllables == 1 and rfind(word, V) then
syllables = "ˈ" .. syllables
elseif #syllables > 1 and rfind(word, "") then
syllables = "ˈ" .. syllables
elseif #syllables > 1 then
syllables = "ˈ" .. syllables
end
end
end
local words = rsplit(text, " ")
for j, word in ipairs(words) do
-- accentuation
local syllables = rsplit(word, "%.")
if rfind(word, "ment#") then
local mente_syllables
-- Words ends in -ment (converted above to mént); add a stress to the preceding portion
mente_syllables = {}
mente_syllables = table.remove(syllables)
mente_syllables = table.remove(syllables)
accent_word(table.concat(syllables, "."), syllables)
accent_word(table.concat(mente_syllables, "."), mente_syllables)
table.insert(syllables, mente_syllables)
table.insert(syllables, mente_syllables)
else
accent_word(word, syllables)
end
-- Reconstruct the word.
words = table.concat(syllables, ".")
end
text = table.concat(words, " ")
text = rsub(text, "%-", "")
-- suppress syllable mark before IPA stress indicator
text = rsub(text, "%.(" .. ipa_stress_c .. ")", "%1")
--make all primary stresses but the last one be secondary
text = rsub_repeatedly(text, "ˈ(.+)ˈ", "ˌ%1ˈ")
--other conversions, silent letters
text = rsub(text, "R", "(ɾ)")
text = rsub(text, "tθ#", "θ#")
text = rsub(text, "()t#", "%1#")
text = rsub(text, "nd#", "n#")
text = rsub(text, "ɾs#", "s#")
--semivowel symbols
text = rsub(text, "()", "%1̯")
text = rsub(text, "()", "%1̯")
--value of conjunction <y>
text = rsub(text, "(*)#i#(*)", "%1#ʝ#‿%2")
text = rsub(text, "i̯(*)#i#(*)", "i̯%1#ʝ#‿%2")
text = rsub(text, "u̯(*)#i#(*)", "u̯%1#ʝ#‿%2")
text = rsub(text, "#i#(*)", "#j#‿%1")
text = rsub(text, "(*)#i#", "%1‿#i̯#")
-- convert fake symbols to real ones
local final_conversions = {
= "t͡ʃ", -- fake "ch" to real "ch"
= "ɡ", -- U+0067 LATIN SMALL LETTER G → U+0261 LATIN SMALL LETTER SCRIPT G
= "(i̯)",
}
text = rsub(text, "", final_conversions)
-- remove # symbols at word and text boundaries
text = rsub(text, "#", "")
text = rsub(text, "‿ ", "‿")
text = rsub(text, " ‿", "‿")
text = rsub(text, "()‿ˈ", "ˈ%1‿")
text = rsub(text, "()‿ˌ", "ˌ%1‿")
text = unfc(text)
local ret = {
text = text,
}
return ret
end
local function generate_term_pronunciation_variants(term_text, pagename_val_unused, parse_err_func_unused, frame_args)
local variants = {}
local standard_ipa_obj = export.IPA(term_text)
local standard_ipa_str = standard_ipa_obj.text
local standard_variant_label = nil -- Default label for the standard IPA
local ben_param_value = frame_args and frame_args.ben
local benasque_ipa_to_add
local add_benasque_line_flag = true
-- Determine benasque_ipa_to_add and add_benasque_line_flag
if ben_param_value then
local lower_ben_param = ulower(ben_param_value)
if lower_ben_param == "0" then
add_benasque_line_flag = false
elseif ben_param_value ~= "" then
local ipa_result_from_ben_override = export.IPA(ben_param_value)
local ipa_from_ben_form_override = ipa_result_from_ben_override.text
if rfind(ipa_from_ben_form_override, "θ") then
benasque_ipa_to_add = ugsub(ipa_from_ben_form_override, "θ", "s")
else
benasque_ipa_to_add = ipa_from_ben_form_override
end
else -- ben_param_value is "" (empty string)
if rfind(standard_ipa_str, "θ") then
benasque_ipa_to_add = ugsub(standard_ipa_str, "θ", "s")
else
add_benasque_line_flag = false
end
end
else -- ben_param_value is nil
if rfind(standard_ipa_str, "θ") then
benasque_ipa_to_add = ugsub(standard_ipa_str, "θ", "s")
else
add_benasque_line_flag = false
end
end
if add_benasque_line_flag and benasque_ipa_to_add then
-- A Benasquese variant will be added. Label the standard IPA accordingly.
-- standard_variant_label = "(Most dialects)"
table.insert(variants, { ipa = standard_ipa_str, label = standard_variant_label })
table.insert(variants, {
ipa = benasque_ipa_to_add,
label = "]"
})
else
-- No Benasquese variant to add (or it was suppressed). Add only the standard IPA.
-- standard_variant_label will be nil here, unless overridden by other q parameters later.
table.insert(variants, { ipa = standard_ipa_str, label = standard_variant_label })
end
return variants, standard_ipa_str
end
local function express_all_styles(dodialect_func_param_with_args)
local ret_data_struct = { pronun = {}, expressed_styles = {} }
dodialect_func_param_with_args(ret_data_struct)
table.insert(ret_data_struct.expressed_styles, { styles = {{pronun = ret_data_struct.pronun, tag = nil}} })
return ret_data_struct
end
local function format_all_styles(list_of_pron_variant_lists_for_term_group, format_style_func_ref, p_args_formatting)
if list_of_pron_variant_lists_for_term_group and #list_of_pron_variant_lists_for_term_group > 0 then
return format_style_func_ref(nil, list_of_pron_variant_lists_for_term_group, true, p_args_formatting)
end
return "", 0
end
local function dodialect_pronun(args_for_dialect_pron, ret_data_for_dialect, top_level_args)
ret_data_for_dialect.pronun = {}
for i, term_obj in ipairs(args_for_dialect_pron.terms) do
local current_term_text = term_obj.term
local pagename_for_ipa = args_for_dialect_pron.pagename or current_term_text
local variants_for_this_term, standard_ipa_str_for_other_uses =
generate_term_pronunciation_variants(current_term_text, pagename_for_ipa, args_for_dialect_pron.parse_err, top_level_args)
local mIPA_items_for_this_term = {}
for _, variant in ipairs(variants_for_this_term) do -- 'variant' is {ipa = "...", label = "..."}
-- Initialize with general per-term display properties
local current_item_q = term_obj.q -- User-defined qualifiers before IPA (from <q:...>)
local current_item_qq = term_obj.qq -- User-defined qualifiers after IPA (from <qq:...>)
local current_item_a = term_obj.a
local current_item_aa = term_obj.aa
local current_item_refs = nil -- Specifically handle refs below
if variant.label then
-- This is one of our automatically generated labeled variants (e.g., Benasquese).
-- Its label should go into 'qq' (qualifier after), overriding any user <qq:...>.
current_item_qq = {variant.label}
-- For these auto-labeled lines, suppress other per-term display annotations
-- to keep the output clean and focused on the dialectal variant.
current_item_a = nil
current_item_aa = nil
-- Refs are also typically for the main entry, not repeated for each dialect line here.
-- current_item_refs remains nil as it's handled below (will not be set if variant.label exists)
end
-- Handle references: populate 'refs' only if there's no specific variant.label
-- (i.e., it's a base pronunciation) AND the term_obj has references.
-- This maintains the original logic where refs were cleared if variant.label was present.
if not variant.label and term_obj.ref then
if not references_module then references_module = require("Module:references") end
local collected_refs = {}
if type(term_obj.ref) == "table" then
for _, refspec_str in ipairs(term_obj.ref) do
local parsed_refs_from_spec = references_module.parse_references(refspec_str)
for _, single_ref_obj in ipairs(parsed_refs_from_spec) do
table.insert(collected_refs, single_ref_obj)
end
end
end
if #collected_refs > 0 then
current_item_refs = collected_refs
end
end
local item = {
phonemic = variant.ipa,
q = current_item_q, -- Qualifiers from <q:...> always appear before
qq = current_item_qq, -- Dialect label (if any) or <qq:...> appears after
a = current_item_a,
aa = current_item_aa,
refs = current_item_refs
}
table.insert(mIPA_items_for_this_term, item)
end
ret_data_for_dialect.pronun = mIPA_items_for_this_term
if term_obj then
term_obj.pronun = { pronun = { phonemic = standard_ipa_str_for_other_uses } }
end
end
end
local function generate_pronun(parsed_resp_group_obj, top_level_args)
local function dodialect_pronun_wrapper(ret_data_wrapper)
dodialect_pronun(parsed_resp_group_obj, ret_data_wrapper, top_level_args)
end
local ret_data_from_express = express_all_styles(dodialect_pronun_wrapper)
local function format_style(tag_style_group_unused, list_of_mIPA_items_for_terms, is_first_style_group_flag, p_args_formatting_options)
local final_formatted_text_parts_for_all_terms_in_group = {}
local total_approx_len_for_group = 0
for term_idx, mIPA_items_for_this_term in ipairs(list_of_mIPA_items_for_terms) do
-- mIPA_items_for_this_term is a list of pronunciation objects for the current term.
-- e.g., { std_variant_details, benasque_variant_details }
local combined_text_for_len_calc_for_this_term = {} -- For length calculation
local formatted_content_for_each_variant = {} -- Store formatted content of each variant (IPA + qualifiers)
-- Step 1: Get the formatted content for each variant
for variant_idx, pron_object_item in ipairs(mIPA_items_for_this_term) do
local phonemic_val = pron_object_item.phonemic or ""
local current_pron_str = "/" .. (phonemic_val:gsub("%.", "")) .. "/"
local single_item_list_for_mIPA_call = {
{
pron = current_pron_str,
q = pron_object_item.q,
qq = pron_object_item.qq,
a = pron_object_item.a,
aa = pron_object_item.aa,
refs = pron_object_item.refs
}
}
local mIPA_options_for_single_variant = {
lang = lang,
items = single_item_list_for_mIPA_call,
no_cat = force_cat
}
table.insert(formatted_content_for_each_variant, m_IPA.format_IPA_full(mIPA_options_for_single_variant))
-- Update text for length calculation
if pron_object_item.q then
for _, q_val_item in ipairs(pron_object_item.q) do
table.insert(combined_text_for_len_calc_for_this_term, q_val_item)
end
end
table.insert(combined_text_for_len_calc_for_this_term, current_pron_str)
if variant_idx < #mIPA_items_for_this_term then
table.insert(combined_text_for_len_calc_for_this_term, " ")
end
end
-- Step 2: Assemble the final lines, each with its own bullet, and apply pre/post text
local final_bulleted_lines_for_this_term = {}
local base_bullet_string = ustring.rep("*", p_args_formatting_options.bullets or 1) .. " "
for i, variant_content_string in ipairs(formatted_content_for_each_variant) do
local line_parts = {}
table.insert(line_parts, base_bullet_string)
-- Apply 'pre' text to the first variant line of the first term in the group
if i == 1 and term_idx == 1 and is_first_style_group_flag and p_args_formatting_options.pre then
table.insert(line_parts, p_args_formatting_options.pre .. " ")
end
table.insert(line_parts, variant_content_string)
-- Apply 'post' text to the last variant line of the first term in the group
if i == #formatted_content_for_each_variant and term_idx == 1 and is_first_style_group_flag and p_args_formatting_options.post then
table.insert(line_parts, " " .. p_args_formatting_options.post)
end
table.insert(final_bulleted_lines_for_this_term, table.concat(line_parts))
end
-- Join these fully-formed, bulleted lines with a newline character.
local complete_ipa_block_for_this_term = table.concat(final_bulleted_lines_for_this_term, "\n")
table.insert(final_formatted_text_parts_for_all_terms_in_group, complete_ipa_block_for_this_term)
total_approx_len_for_group = total_approx_len_for_group + textual_len(table.concat(combined_text_for_len_calc_for_this_term))
end
return table.concat(final_formatted_text_parts_for_all_terms_in_group, ", "), total_approx_len_for_group
end
if ret_data_from_express.expressed_styles and
ret_data_from_express.expressed_styles and
ret_data_from_express.expressed_styles.styles and
ret_data_from_express.expressed_styles.styles then
ret_data_from_express.text, ret_data_from_express.text_len = format_all_styles(
ret_data_from_express.expressed_styles.styles.pronun,
format_style,
parsed_resp_group_obj
)
else
ret_data_from_express.text = "(Error: Pronunciation data structure issue in generate_pronun)"
ret_data_from_express.text_len = 0
mw.log("Module:an-pron ERROR: ret_data_from_express.expressed_styles structure not as expected in generate_pronun.")
end
return ret_data_from_express
end
-- Simplified parse_respelling as raw input is no longer specially handled
local function parse_respelling(respelling_text, pagename_val, parse_err_func, top_level_args_unused_here)
if respelling_text == "+" then
if not pagename_val or pagename_val == "" then
parse_err_func("Cannot use '+' for respelling as page name is not available.")
return { term = "" , raw = false, q = {"(Error: No pagename for '+')"}}
end
respelling_text = pagename_val
end
return {term = respelling_text, raw = false}
end
local function get_num_syl_from_phonemic(phonemic_str)
if not phonemic_str or phonemic_str == "" then return 0 end
phonemic_str = rsub(phonemic_str, "|", " ")
local words_list = rsplit(phonemic_str, " +")
local total_syllables = 0
for i, single_word in ipairs(words_list) do
single_word = rsub(single_word, "(.)(.)", "%1.%2")
single_word = rsub(single_word, "", "")
total_syllables = total_syllables + ulen(rsub(single_word, "", "")) + 1
end
return total_syllables > 0 and total_syllables or 1
end
local function convert_phonemic_to_rhyme(phonemic_str)
return rsub(rsub(phonemic_str, ".*", ""), "^*", ""):gsub("", ""):gsub("t͡ʃ", "tʃ")
end
local function split_syllabified_spelling(spelling_str)
return rsplit(spelling_str, "%.")
end
local function align_syllabification_to_spelling(syllab_str, spelling_str)
local result_chars = {}
local syll_chars_list = rsplit(decompose(syllab_str), "")
local spelling_chars_list = rsplit(decompose(spelling_str), "")
local i_syll = 1
local j_spell = 1
while i_syll <= #syll_chars_list or j_spell <= #spelling_chars_list do
local char_i = syll_chars_list
local char_j = spelling_chars_list
if char_i == char_j then
table.insert(result_chars, char_i)
i_syll = i_syll + 1
j_spell = j_spell + 1
elseif char_i == "." then
table.insert(result_chars, char_i)
i_syll = i_syll + 1
elseif char_i == AC or char_i == GR or char_i == CFLEX then
i_syll = i_syll + 1
elseif char_j == AC or char_j == GR or char_j == CFLEX then
j_spell = j_spell + 1
else
return nil
end
end
if i_syll <= #syll_chars_list or j_spell <= #spelling_chars_list then
return nil
end
return unfc(table.concat(result_chars))
end
local function generate_hyph_obj(term_str)
return {syllabification = term_str, hyph = split_syllabified_spelling(term_str)}
end
local function word_has_vowels(word_str)
return rfind(word_str, V)
end
local function all_words_have_vowels(term_str)
local words_list = rsplit(decompose(term_str), "")
for _, single_word in ipairs(words_list) do
if single_word ~= "" and not word_has_vowels(single_word) then
return false
end
end
return true
end
local function should_generate_rhyme_from_respelling(term_str)
local words_list = rsplit(decompose(term_str), " +")
return #words_list == 1 and
not words_list:find("%.%-%..") and
not words_list:find("%-$") and
not (words_list:find("^%-") and words_list:find(CFLEX)) and
word_has_vowels(words_list)
end
local function should_generate_rhyme_from_ipa(ipa_str)
return not ipa_str:find("%s") and word_has_vowels(decompose(ipa_str))
end
local function dodialect_specified_rhymes(rhymes_list, hyphs_list, parsed_respelling_groups_list_arg, rhyme_ret_table)
rhyme_ret_table.pronun = rhyme_ret_table.pronun or {}
for _, rhyme_obj in ipairs(rhymes_list) do
local num_syl_val = rhyme_obj.num_syl
local no_num_syl_flag = false
if not num_syl_val or #num_syl_val == 0 then
num_syl_val = {}
if hyphs_list and #hyphs_list > 0 then
for _, hyph_item in ipairs(hyphs_list) do
if hyph_item.syllabification and should_generate_rhyme_from_respelling(hyph_item.syllabification) then
local this_syl_count = 1 + ulen(rsub(hyph_item.syllabification, "", ""))
m_table.insertIfNot(num_syl_val, this_syl_count)
else
no_num_syl_flag = true; break
end
end
else
no_num_syl_flag = true
end
if no_num_syl_flag or #num_syl_val == 0 then num_syl_val = nil end
end
if not no_num_syl_flag and (not num_syl_val or #num_syl_val == 0) then
num_syl_val = {}
for _, parsed_item in ipairs(parsed_respelling_groups_list_arg) do
for _, term_obj_item_wrapper in ipairs(parsed_item.terms or {}) do
local term_obj_item = (type(term_obj_item_wrapper) == "table" and term_obj_item_wrapper) or term_obj_item_wrapper
local std_ipa_for_rhyme
if term_obj_item.raw then
std_ipa_for_rhyme = term_obj_item.raw_phonemic
elseif term_obj_item.term then
local ipa_result = export.IPA(term_obj_item.term)
std_ipa_for_rhyme = ipa_result.text
end
if std_ipa_for_rhyme and type(std_ipa_for_rhyme) == "string" then
if not should_generate_rhyme_from_ipa(std_ipa_for_rhyme) then
no_num_syl_flag = true; break
end
local this_syl_count = get_num_syl_from_phonemic(std_ipa_for_rhyme)
m_table.insertIfNot(num_syl_val, this_syl_count)
else
no_num_syl_flag = true; break
end
end
if no_num_syl_flag then break end
end
if no_num_syl_flag or #num_syl_val == 0 then num_syl_val = nil end
end
table.insert(rhyme_ret_table.pronun, {
rhyme = rhyme_obj.rhyme,
num_syl = num_syl_val,
qualifiers = rhyme_obj.qualifiers,
})
end
end
local function parse_rhyme(arg_str, parse_err_func)
local function gen_obj(term_str, p_err) return {rhyme = term_str} end
local p_mods = {
s = {
item_dest = "num_syl",
convert = function(val_str, p_err)
local ns_list = rsplit(val_str, ",")
for i_val, ns_val in ipairs(ns_list) do
if not ns_val:find("^+$") then
p_err("Number of syllables '" .. ns_val .. "' should be numeric")
end
ns_list = tonumber(ns_val)
end
return ns_list
end,
},
}
return parse_pron_modifier(arg_str, parse_err_func, gen_obj, p_mods)
end
local function parse_hyph(arg_str, parse_err_func)
local p_mods = {}
return parse_pron_modifier(arg_str, parse_err_func, generate_hyph_obj, p_mods)
end
local function parse_homophone(arg_str, parse_err_func)
local function gen_obj(term_str, p_err) return {term = term_str} end
local p_mods = {
t = { item_dest = "gloss" },
gloss = {item_dest = "gloss"},
pos = {}, alt = {}, lit = {}, id = {},
g = { item_dest = "genders", convert = function(val) return rsplit(val, ",") end },
}
return parse_pron_modifier(arg_str, parse_err_func, gen_obj, p_mods)
end
local function generate_audio_obj(audio_arg_str, parse_err_func)
local file_part, gloss_part
if audio_arg_str:find("#") then
file_part, gloss_part = audio_arg_str:match("^(.-)%s*#%s*(.*)$")
elseif audio_arg_str:find(";") then
file_part, gloss_part = audio_arg_str:match("^(.-)%s*;%s*(.*)$")
end
if not file_part then
file_part = audio_arg_str
gloss_part = "Audio"
elseif gloss_part == "" then
gloss_part = "Audio"
end
return {file = file_part, gloss = gloss_part}
end
local function parse_audio(arg_str, parse_err_func)
local p_mods = {}
return parse_pron_modifier(arg_str, parse_err_func, generate_audio_obj, p_mods, "no split on comma")
end
-- External entry point for {{an-pr}} or {{an-IPA}}.
function export.show_pr(frame)
if not parameters_module then parameters_module = require("Module:parameters") end
if not m_put_utils then m_put_utils = require("Module:parse utilities") end
if not m_audio then m_audio = require("Module:audio") end
if not hyphenation_module then hyphenation_module = require("Module:hyphenation") end
if not homophones_module then homophones_module = require("Module:homophones") end
if not rhymes_module then rhymes_module = require("Module:rhymes") end
if not m_table then m_table = require("Module:table") end
if not ustring then ustring = mw.ustring end
local params_spec = {
= {list = true, default = "+"},
= {default = nil},
= {type = "string", default = nil},
= {type = "string", default = nil},
= {type = "string", default = nil},
= {list = true, default = nil},
= {type = "string", default = nil},
= {list = true, default = nil},
= {list = true, default = nil},
= {list = true, default = nil},
= {list = true, default = nil},
= {list = true, default = nil}
}
local effective_args_table
if frame:getParent() and frame:getParent().args then
effective_args_table = frame:getParent().args
elseif frame.args then
effective_args_table = frame.args
else
effective_args_table = {}
end
local args_processed = parameters_module.process(effective_args_table, params_spec)
local pagename_val = args_processed.pagename or mw.title.getCurrentTitle().subpageText or mw.title.getCurrentTitle().text or ""
local respelling_input_list = args_processed
local parsed_respelling_groups_list = {}
local function overall_parse_err_callback(error_msg, arg_name_str, original_val_str)
error(error_msg .. ": " .. arg_name_str .. "= " .. original_val_str)
end
local overall_rhyme_parsed_data = args_processed.rhyme and
parse_rhyme(args_processed.rhyme, function(msg) overall_parse_err_callback(msg, "rhyme", args_processed.rhyme) end) or nil
local overall_hyph_parsed_data = args_processed.hyph and
parse_hyph(args_processed.hyph, function(msg) overall_parse_err_callback(msg, "hyph", args_processed.hyph) end) or nil
local overall_hmp_parsed_data = args_processed.hmp and
parse_homophone(args_processed.hmp, function(msg) overall_parse_err_callback(msg, "hmp", args_processed.hmp) end) or nil
local overall_audio_parsed_data
if args_processed.audio and #args_processed.audio > 0 then
overall_audio_parsed_data = {}
for _, audio_str_item in ipairs(args_processed.audio) do
local parsed_audio_items_list = parse_audio(audio_str_item, function(msg) overall_parse_err_callback(msg, "audio", audio_str_item) end)
for _, pa_obj_item in ipairs(parsed_audio_items_list) do
table.insert(overall_audio_parsed_data, pa_obj_item)
end
end
end
for i_resp, respelling_str_item in ipairs(respelling_input_list) do
if respelling_str_item:find("<") then
local inline_mods_spec = {
pre = { overall = true }, post = { overall = true },
bullets = {
overall = true,
convert = function(b_val, p_err)
if not b_val:find("^+$") then p_err("Modifier 'bullets' needs a number, saw '" .. b_val .. "'") end
return tonumber(b_val)
end,
},
rhyme = { overall = true, store = "insert-flattened", convert = parse_rhyme },
hyph = { overall = true, store = "insert-flattened", convert = parse_hyph },
hmp = { overall = true, store = "insert-flattened", convert = parse_homophone },
audio = { overall = true, store = "insert-flattened", convert = parse_audio },
ref = { store = "insert" }, q = { store = "insert" }, qq = { store = "insert" },
a = { store = "insert" }, aa = { store = "insert" },
}
local parsed_group_container = m_put_utils.parse_inline_modifiers(respelling_str_item, {
paramname = "respelling group " .. i_resp,
param_mods = inline_mods_spec,
generate_obj = function(term_val, p_err)
return parse_respelling(term_val, pagename_val, p_err, args_processed)
end,
splitchar = ",",
outer_container = { terms = {}, audio = {}, rhyme = {}, hyph = {}, hmp = {} }
})
if not parsed_group_container.bullets then parsed_group_container.bullets = 1 end
table.insert(parsed_respelling_groups_list, parsed_group_container)
else
local term_obj_list_for_group = {}
local function current_term_parse_err_callback(error_msg)
error(error_msg .. " for respelling string: '" .. respelling_str_item .. "'")
end
for _, term_part_val in ipairs(split_on_comma_func(respelling_str_item)) do
table.insert(term_obj_list_for_group, parse_respelling(term_part_val, pagename_val, current_term_parse_err_callback, args_processed))
end
table.insert(parsed_respelling_groups_list, {
terms = term_obj_list_for_group,
audio = {}, rhyme = {}, hyph = {}, hmp = {},
bullets = 1,
pagename = pagename_val,
parse_err = current_term_parse_err_callback
})
end
end
if not (overall_hyph_parsed_data and #overall_hyph_parsed_data > 0) then
if respelling_input_list and #respelling_input_list == 1 and respelling_input_list == "+" then
if pagename_val and pagename_val ~= "" and all_words_have_vowels(pagename_val) then
local syllabified_pagename = syllabify_from_spelling(pagename_val)
if syllabified_pagename then
overall_hyph_parsed_data = {generate_hyph_obj(syllabified_pagename)}
end
end
end
end
for resp_group_idx, resp_group_data in ipairs(parsed_respelling_groups_list) do
resp_group_data.pronun_display_details = generate_pronun(resp_group_data, args_processed)
if #resp_group_data.hyph == 0 and not (overall_hyph_parsed_data and #overall_hyph_parsed_data > 0) then
if resp_group_data.terms and #resp_group_data.terms > 0 then
local first_term_obj_for_hyph_wrapper = resp_group_data.terms
local first_term_obj_for_hyph = (type(first_term_obj_for_hyph_wrapper) == "table" and first_term_obj_for_hyph_wrapper) or first_term_obj_for_hyph_wrapper
if first_term_obj_for_hyph and not first_term_obj_for_hyph.raw and
first_term_obj_for_hyph.term and first_term_obj_for_hyph.term ~= "" and
all_words_have_vowels(first_term_obj_for_hyph.term) then
local syllabified_term_str = syllabify_from_spelling(first_term_obj_for_hyph.term)
if syllabified_term_str then
m_table.insertIfNot(resp_group_data.hyph, generate_hyph_obj(syllabified_term_str))
end
end
end
end
local no_auto_rhyme_flag = false
if resp_group_data.terms then
for term_idx, term_obj_wrapper in ipairs(resp_group_data.terms) do
local term_obj_for_rhyme_check = (type(term_obj_wrapper) == "table" and term_obj_wrapper) or term_obj_wrapper
local ipa_to_check_for_rhyme
if term_obj_for_rhyme_check.raw then
ipa_to_check_for_rhyme = term_obj_for_rhyme_check.raw_phonemic
elseif resp_group_data.pronun_display_details and
resp_group_data.pronun_display_details.pronun and
resp_group_data.pronun_display_details.pronun and
#resp_group_data.pronun_display_details.pronun > 0 then
ipa_to_check_for_rhyme = resp_group_data.pronun_display_details.pronun.phonemic
end
if not ipa_to_check_for_rhyme or not should_generate_rhyme_from_ipa(ipa_to_check_for_rhyme) then
no_auto_rhyme_flag = true; break
end
end
else
no_auto_rhyme_flag = true
end
if #resp_group_data.rhyme == 0 and not overall_rhyme_parsed_data and not no_auto_rhyme_flag then
local rhyme_ret_for_group_auto = { pronun = {} }
if resp_group_data.terms then
for term_idx_auto, term_obj_wrapper_auto in ipairs(resp_group_data.terms) do
local term_obj_for_rhyme_auto = (type(term_obj_wrapper_auto) == "table" and term_obj_wrapper_auto) or term_obj_wrapper_auto
local std_ipa_for_rhyme_auto
if term_obj_for_rhyme_auto.raw then
std_ipa_for_rhyme_auto = term_obj_for_rhyme_auto.raw_phonemic
elseif resp_group_data.pronun_display_details and
resp_group_data.pronun_display_details.pronun and
resp_group_data.pronun_display_details.pronun and
#resp_group_data.pronun_display_details.pronun > 0 then
std_ipa_for_rhyme_auto = resp_group_data.pronun_display_details.pronun.phonemic
end
if std_ipa_for_rhyme_auto then
local num_syl_val = get_num_syl_from_phonemic(std_ipa_for_rhyme_auto)
local rhyme_str = convert_phonemic_to_rhyme(std_ipa_for_rhyme_auto)
local saw_rhyme_already = false
for _, existing_rhyme_obj in ipairs(rhyme_ret_for_group_auto.pronun) do
if existing_rhyme_obj.rhyme == rhyme_str then
saw_rhyme_already = true
m_table.insertIfNot(existing_rhyme_obj.num_syl, num_syl_val)
break
end
end
if not saw_rhyme_already then
table.insert(rhyme_ret_for_group_auto.pronun, { rhyme = rhyme_str, num_syl = {num_syl_val} })
end
end
end
end
if #rhyme_ret_for_group_auto.pronun > 0 then
resp_group_data.rhyme = rhyme_ret_for_group_auto.pronun
end
elseif #resp_group_data.rhyme > 0 then
local temp_rhyme_ret = { pronun = {} }
dodialect_specified_rhymes(resp_group_data.rhyme, resp_group_data.hyph or {}, {resp_group_data}, temp_rhyme_ret)
resp_group_data.rhyme = temp_rhyme_ret.pronun
end
end
local first_hyph_data_display, first_hmp_data_display, first_audio_data_display, first_rhyme_data_display
local all_hyph_groups_eq_display, all_hmp_groups_eq_display, all_audio_groups_eq_display, all_rhyme_groups_eq_display = true, true, true, true
if #parsed_respelling_groups_list > 0 then
first_hyph_data_display = parsed_respelling_groups_list.hyph
first_hmp_data_display = parsed_respelling_groups_list.hmp
first_audio_data_display = parsed_respelling_groups_list.audio
first_rhyme_data_display = parsed_respelling_groups_list.rhyme
if #parsed_respelling_groups_list > 1 then
for i_grp = 2, #parsed_respelling_groups_list do
if not m_table.deepEquals(parsed_respelling_groups_list.hyph, first_hyph_data_display) then all_hyph_groups_eq_display = false end
if not m_table.deepEquals(parsed_respelling_groups_list.hmp, first_hmp_data_display) then all_hmp_groups_eq_display = false end
if not m_table.deepEquals(parsed_respelling_groups_list.audio, first_audio_data_display) then all_audio_groups_eq_display = false end
if not m_table.deepEquals(parsed_respelling_groups_list.rhyme, first_rhyme_data_display) then all_rhyme_groups_eq_display = false end
end
end
else
all_hyph_groups_eq_display, all_hmp_groups_eq_display, all_audio_groups_eq_display, all_rhyme_groups_eq_display = false, false, false, false
end
local output_text_parts = {}
local min_num_bullets_val = math.huge
for j_grp, resp_group_data in ipairs(parsed_respelling_groups_list) do
local current_grp_bullets = resp_group_data.bullets or 1
if current_grp_bullets < min_num_bullets_val then min_num_bullets_val = current_grp_bullets end
if j_grp > 1 then table.insert(output_text_parts, "\n") end
if resp_group_data.pre then table.insert(output_text_parts, resp_group_data.pre .. " ") end
if resp_group_data.pronun_display_details and resp_group_data.pronun_display_details.text then
table.insert(output_text_parts, resp_group_data.pronun_display_details.text)
else
local err_msg_pron = "(Pronunciation formatting error for group " .. j_grp .. ")"
table.insert(output_text_parts, ustring.rep("*", current_grp_bullets) .. " " .. err_msg_pron)
end
if resp_group_data.post then table.insert(output_text_parts, " " .. resp_group_data.post) end
local accessory_bullet_lvl = current_grp_bullets + (#parsed_respelling_groups_list > 1 and 1 or 0)
if not all_audio_groups_eq_display and not overall_audio_parsed_data and resp_group_data.audio and #resp_group_data.audio > 0 then
for _, audio_obj_item in ipairs(resp_group_data.audio) do
table.insert(output_text_parts, "\n" .. ustring.rep("*", accessory_bullet_lvl) .. " " .. m_audio.format_audio(audio_obj_item))
end
end
if not all_hyph_groups_eq_display and not overall_hyph_parsed_data and resp_group_data.hyph and #resp_group_data.hyph > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", accessory_bullet_lvl) .. " " .. hyphenation_module.format_hyphenations{ lang = lang, hyphs = resp_group_data.hyph, caption = "Syllabification" })
end
if not all_hmp_groups_eq_display and not overall_hmp_parsed_data and resp_group_data.hmp and #resp_group_data.hmp > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", accessory_bullet_lvl) .. " " .. homophones_module.format_homophones{ lang = lang, homophones = resp_group_data.hmp })
end
if not all_rhyme_groups_eq_display and not overall_rhyme_parsed_data and resp_group_data.rhyme and #resp_group_data.rhyme > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", accessory_bullet_lvl) .. " " .. rhymes_module.format_rhymes{ lang = lang, rhymes = resp_group_data.rhyme, caption = "Rhymes" })
end
end
local overall_display_bullet_lvl_final_val = min_num_bullets_val == math.huge and 1 or min_num_bullets_val
if overall_audio_parsed_data and #overall_audio_parsed_data > 0 then
for _, audio_overall_item in ipairs(overall_audio_parsed_data) do
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. m_audio.format_audio(audio_overall_item))
end
elseif all_audio_groups_eq_display and first_audio_data_display and #first_audio_data_display > 0 then
for _, audio_first_grp_item in ipairs(first_audio_data_display) do
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. m_audio.format_audio(audio_first_grp_item))
end
end
if overall_hyph_parsed_data and #overall_hyph_parsed_data > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. hyphenation_module.format_hyphenations{ lang = lang, hyphs = overall_hyph_parsed_data, caption = "Syllabification" })
elseif all_hyph_groups_eq_display and first_hyph_data_display and #first_hyph_data_display > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. hyphenation_module.format_hyphenations{ lang = lang, hyphs = first_hyph_data_display, caption = "Syllabification" })
end
if overall_hmp_parsed_data and #overall_hmp_parsed_data > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. homophones_module.format_homophones{ lang = lang, homophones = overall_hmp_parsed_data })
elseif all_hmp_groups_eq_display and first_hmp_data_display and #first_hmp_data_display > 0 then
table.insert(output_text_parts, "\n" .. string.rep("*", overall_display_bullet_lvl_final_val) .. " " .. homophones_module.format_homophones{ lang = lang, homophones = first_hmp_data_display })
end
if overall_rhyme_parsed_data and #overall_rhyme_parsed_data > 0 then
local overall_rhyme_output_final = { pronun = {} }
local all_hyphs_for_overall_rhyme = overall_hyph_parsed_data or (all_hyph_groups_eq_display and first_hyph_data_display) or {}
dodialect_specified_rhymes(overall_rhyme_parsed_data, all_hyphs_for_overall_rhyme, parsed_respelling_groups_list, overall_rhyme_output_final)
if overall_rhyme_output_final.pronun and #overall_rhyme_output_final.pronun > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. rhymes_module.format_rhymes{ lang = lang, rhymes = overall_rhyme_output_final.pronun, caption = "Rhymes" })
end
elseif all_rhyme_groups_eq_display and first_rhyme_data_display and #first_rhyme_data_display > 0 then
table.insert(output_text_parts, "\n" .. ustring.rep("*", overall_display_bullet_lvl_final_val) .. " " .. rhymes_module.format_rhymes{ lang = lang, rhymes = first_rhyme_data_display, caption = "Rhymes" })
end
if #output_text_parts == 0 and #respelling_input_list > 0 and respelling_input_list == "+" and (pagename_val == "" or not pagename_val) then
return "<strong class=\"error\">Module:an-pron: No page name available for default pronunciation ('+'). Please specify a term or use on a content page.</strong>"
end
return table.concat(output_text_parts)
end -- End of export.show_pr
return export