Jump to content

Module:Translations

From Yezur Wiki
Revision as of 11:52, 3 August 2026 by Thiorosan (talk | contribs) (Translations box for English lemma sections: grouped by family via the registry; display-only per the Cargo ruling)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This is the documentation for Module:Translations, the translations-box renderer for the Yezur wiki. It is not called directly: Template:Translations invokes it with {{#invoke:Translations|render}} and the module reads the parameters given to that template. One box covers one English sense and lists the words the world's languages use for it, grouped by macro-family; boxes sit under a ====Translations==== heading following that sense's definitions, inside the English section of a Dictionary entry. Worked examples are at Template:Translations/testcases.

Parameters

Parameter Purpose
gloss The sense being translated, shown in italics after Translations and an em dash in the box heading. Required: a headword with several senses carries one box per sense, and the gloss is what keeps them apart. When it is omitted the heading reads no gloss given in the error style instead.
CODE A registry code from Module:Languages used as the parameter name — YAQ-HE, YBS-PJ, YCQ-BE — with that language's word for the sense as the value. Any number may be given. A single value may hold several synonyms separated by commas, each of which is linked separately.

Every named parameter other than gloss is read as a language code; codes are matched case-insensitively. Parameters with an empty value are skipped, as are positional parameters. A gloss given on its own still renders the heading and an otherwise empty box; the module returns nothing at all when it is given neither a gloss nor any language parameter.

Grouping and order

Each word is linked to its Dictionary entry through Module:Languages, which anchors the link to the language's section heading and prefixes an asterisk for reconstructed languages — the star comes from the registry, not from the wikitext. Group headings are the registry's family field; known codes carrying no family are gathered under Isolates.

Rows are sorted by the second letter of the code, which is the family, then by the third, which is the era (P proto, Q ancient, R medieval, S modern, so alphabetical order is also chronological), then by language name, then by the code itself. The second letter likewise picks the colour class, tfam- followed by that letter. Colours and layout come from Template:Translations/styles.css, which the module loads through TemplateStyles; it defines tfam-A to tfam-E for the five families and tfam-X for the isolate codes.

A code the registry does not know is not silently dropped. Its words are left unlinked and printed after all the family groups as unrecognized code CODE: word in red, so that a typo or a language missing from the registry shows on the page.

The box is display-only: it stores nothing and is hand-curated per sense, in the same way as the family Members tables.


-- Module:Translations — the translations box for English lemma sections.
-- Backs Template:Translations. Collects, for ONE English sense, the words the
-- world's languages use for it, and renders them grouped by macro-family
-- (per the `family` field of Module:Languages; languages with no family are
-- gathered under "Isolates").
--
-- Called with |gloss= (the sense being translated — REQUIRED, so that a page
-- with several senses carries several boxes, one per sense) plus any number
-- of |<CODE>=word parameters, e.g. |YBS-PJ=tuku. A value may hold several
-- synonyms separated by commas; each is linked to its Dictionary entry,
-- starred automatically for reconstructed languages. Unknown codes render
-- visibly as errors rather than being dropped.
--
-- Display-only by design: no Cargo. The box is hand-curated per sense, like
-- the family Members tables (see the Cargo ruling of 2026-07-30).

local Languages = require('Module:Languages')

local p = {}

local ISOLATES = "Isolates"          -- display bucket for family-less codes
local ISOLATES_SORT = "\255"         -- sorts after every real family name

function p.render(frame)
	local args = frame:getParent().args
	local gloss = mw.text.trim(args.gloss or "")

	-- collect rows: one per language code given (named params only)
	local rows = {}
	for k, v in pairs(args) do
		v = mw.text.trim(v or "")
		if type(k) == "string" and k ~= "gloss" and v ~= "" then
			local code = k
			local l = Languages._get(code)
			local words = {}
			for w in mw.text.gsplit(v, ",") do
				w = mw.text.trim(w)
				if w ~= "" then
					if l then
						table.insert(words, Languages._build_link(w, l))
					else
						table.insert(words, w)
					end
				end
			end
			table.insert(rows, {
				code   = code,
				name   = l and l.name or code,
				family = l and (l.family or ISOLATES) or nil,
				known  = l ~= nil,
				text   = table.concat(words, ", "),
			})
		end
	end

	if #rows == 0 and gloss == "" then return "" end

	-- group by family, families alphabetical (Isolates last), languages
	-- alphabetical within each
	table.sort(rows, function(a, b)
		local fa = (a.family == ISOLATES) and ISOLATES_SORT or (a.family or ISOLATES_SORT)
		local fb = (b.family == ISOLATES) and ISOLATES_SORT or (b.family or ISOLATES_SORT)
		if fa ~= fb then return fa < fb end
		if a.name ~= b.name then return a.name < b.name end
		return a.code < b.code
	end)

	local out = {}
	table.insert(out, '<div class="translations">')
	local head = "Translations"
	if gloss ~= "" then
		head = head .. ' — <span class="translations-gloss">' .. gloss .. '</span>'
	else
		head = head .. ' — <span class="translations-error">no gloss given</span>'
	end
	table.insert(out, '<div class="translations-head">' .. head .. '</div>')

	local fam = false
	for _, r in ipairs(rows) do
		if r.known then
			if r.family ~= fam then
				if fam ~= false then table.insert(out, '</ul>') end
				table.insert(out, '<div class="translations-family">' .. r.family .. '</div>')
				fam = r.family
				table.insert(out, '<ul class="translations-list">')
			end
			table.insert(out, '<li>' .. r.name .. ": " .. r.text .. '</li>')
		end
	end
	if fam ~= false then table.insert(out, '</ul>') end
	for _, r in ipairs(rows) do
		if not r.known then
			table.insert(out, '<div class="translations-error">unrecognized code ' ..
				r.code .. ': ' .. r.text .. '</div>')
		end
	end
	table.insert(out, '</div>')

	return frame:extensionTag{ name = "templatestyles", args = { src = "Template:Translations/styles.css" } }
		.. table.concat(out, "\n")
end

return p