Jump to content

Module:Auphen/frame

From Yezur Wiki
Revision as of 01:00, 18 July 2026 by Khurouan (talk | contribs) (Load language data via require (proxy pairs fix))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This is the documentation for Module:Auphen/frame, the template-facing wrapper around Module:Auphen for the Yezur wiki. It is not normally invoked by hand: Template:Auphen calls it as {{#invoke:Auphen/frame|auphen|{{{1|}}}|{{{2|}}}|{{{3|}}}}}, so that {{auphen|word|code}} estimates a pronunciation and {{auphen|word|code|ruleset}} runs a named derivation ruleset. The wrapper holds no linguistic data of its own; it loads the per-language sound data page for the code given, builds an engine from it, runs the requested ruleset and formats the result.

Parameters

Both entry points take the same three positional parameters, each trimmed of surrounding whitespace.

Parameter Purpose
1 The word, in the language's own orthography. Required.
2 The language registry code, e.g. YBS-PJ (see Module:Languages). Required. It is upper-cased and used to load the data page Module:Auphen/CODE, so ybs-pj resolves as well.
3 The name of a ruleset in that data page's sets table, matched exactly, case included. Left empty or omitted, the module estimates pronunciation instead.

Entry points

Function Output
auphen The formatted result: an estimate wrapped as <span class="IPA">/…/</span>, a ruleset result as plain text. On failure it emits a bold inline Auphen: error message and files the calling page into Category:Auphen errors.
raw The engine's bare output, without slashes, markup or categorisation; on failure the plain text ERROR: message, again uncategorised. Used by Template:Auphen/testcases to compare output against hand-checked expectations, and by any caller that wants the segments alone.

Behaviour

The two modes read different halves of the data page. Without a ruleset the engine is built from ipacats (falling back to cats) together with ipa_rules, and the pronounce ruleset is run in the engine's sound mode: the word is lower-cased and converted through ipa_rules from spelling to sound before the rules apply, so the result is in sounds. A data page carrying no pronounce is not an error; an empty ruleset is run, leaving the output of ipa_rules alone. With a ruleset the engine is built from cats (falling back to ipacats) and no ipa_rules, and the named ruleset is run on the word as written, so the result stays in the orthography.

Data pages are pulled in with require rather than mw.loadData, because the read-only proxy mw.loadData returns does not enumerate nested tables under pairs() in Lua 5.1, which would hide the category members. Each category is copied into a plain table before it is handed to the engine.

Four conditions produce an error: an empty word, an empty code, a code whose Module:Auphen/CODE page is missing or does not return a table, and a ruleset name absent from that page's sets. The word itself is passed through untouched, so a ~ word split is resolved by the engine, not here. The engine's rule syntax, design notes and divergence log live on Module talk:Auphen; Module:Auphen/sandbox/frame is the same wrapper pointed at Module:Auphen/sandbox, for testing a candidate engine side by side with the live one.


-- Module:Auphen/frame -- template-facing wrapper around [[Module:Auphen]].
-- Backs {{auphen}}: with no ruleset it estimates pronunciation; with a named
-- ruleset it runs that derivation. p.auphen formats the result (/.../ for an
-- estimate); p.raw returns the bare engine output (used by the testcases page).
local Auphen = require('Module:Auphen')

local p = {}

-- Copy an mw.loadData category proxy into plain Lua tables for the engine.
local function plain_cats(src)
	if type(src) ~= 'table' then return nil end
	local out = {}
	for name, members in pairs(src) do
		local m = {}
		for i = 1, #members do m[i] = members[i] end
		out[name] = m
	end
	return out
end

-- Core: returns (output, isEstimation, errMessage). errMessage ~= nil on error.
local function run_core(a)
	local word = mw.text.trim(a[1] or '')
	local code = mw.text.trim(a[2] or '')
	local rs   = mw.text.trim(a[3] or '')
	if word == '' then return nil, nil, 'no word given' end
	if code == '' then return nil, nil, 'no language code given' end

	-- require (not mw.loadData): loadData's read-only proxy does not enumerate
	-- nested tables under pairs() in Lua 5.1, which would hide the categories.
	local ok, data = pcall(require, 'Module:Auphen/' .. code:upper())
	if not ok or type(data) ~= 'table' then
		return nil, nil, 'no sound data for code "' .. code .. '"'
	end

	if rs == '' then
		local eng = Auphen.new(plain_cats(data.ipacats or data.cats), data.ipa_rules)
		return eng:run(data.pronounce or '', word, true), true, nil
	else
		local ruleset = (type(data.sets) == 'table') and data.sets[rs] or nil
		if ruleset == nil then
			return nil, nil, 'unknown ruleset "' .. rs .. '" for code "' .. code .. '"'
		end
		local eng = Auphen.new(plain_cats(data.cats or data.ipacats))
		return eng:run(ruleset, word, false), false, nil
	end
end

local function err(msg)
	return '<strong class="error">Auphen: ' .. mw.text.nowiki(msg) ..
		'</strong>[[Category:Auphen errors]]'
end

-- {{#invoke:Auphen/frame|auphen | word | code | ruleset }}  (via {{auphen}})
function p.auphen(frame)
	local out, est, e = run_core(frame.args)
	if e then return err(e) end
	if est then return '<span class="IPA">/' .. out .. '/</span>' end
	return out
end

-- {{#invoke:Auphen/frame|raw | word | code | ruleset }} -- bare output, no
-- formatting (for the testcases page and callers that want the phonemes only).
function p.raw(frame)
	local out, _, e = run_core(frame.args)
	if e then return 'ERROR: ' .. e end
	return out
end

return p