Jump to content

Module:Translations: Difference between revisions

From Yezur Wiki
Thiorosan (talk | contribs)
Translations box for English lemma sections: grouped by family via the registry; display-only per the Cargo ruling
 
Thiorosan (talk | contribs)
Order families by code letter and languages by era letter (chronological) then name; emit per-family colour classes (operator request)
 
Line 20: Line 20:


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


function p.render(frame)
function p.render(frame)
Line 48: Line 47:
name  = l and l.name or code,
name  = l and l.name or code,
family = l and (l.family or ISOLATES) or nil,
family = l and (l.family or ISOLATES) or nil,
-- 2nd code letter = family, 3rd = era (P proto < Q ancient
-- < R medieval < S modern — alphabetical IS chronological);
-- the family letter also picks the colour class.
famkey = code:sub(2, 2):upper(),
erakey = code:sub(3, 3):upper(),
known  = l ~= nil,
known  = l ~= nil,
text  = table.concat(words, ", "),
text  = table.concat(words, ", "),
Line 56: Line 60:
if #rows == 0 and gloss == "" then return "" end
if #rows == 0 and gloss == "" then return "" end


-- group by family, families alphabetical (Isolates last), languages
-- families in code-letter order (A Herta-Olaic, B Njeshan, C Andusian,
-- alphabetical within each
-- D Tacchoan, E Shung-Worrehan; X isolates last), then era, then name
table.sort(rows, function(a, b)
table.sort(rows, function(a, b)
local fa = (a.family == ISOLATES) and ISOLATES_SORT or (a.family or ISOLATES_SORT)
if a.famkey ~= b.famkey then return a.famkey < b.famkey end
local fb = (b.family == ISOLATES) and ISOLATES_SORT or (b.family or ISOLATES_SORT)
if a.erakey ~= b.erakey then return a.erakey < b.erakey end
if fa ~= fb then return fa < fb end
if a.name ~= b.name then return a.name < b.name end
if a.name ~= b.name then return a.name < b.name end
return a.code < b.code
return a.code < b.code
Line 81: Line 84:
if r.family ~= fam then
if r.family ~= fam then
if fam ~= false then table.insert(out, '</ul>') end
if fam ~= false then table.insert(out, '</ul>') end
table.insert(out, '<div class="translations-family">' .. r.family .. '</div>')
local cls = ' tfam-' .. r.famkey
table.insert(out, '<div class="translations-family' .. cls .. '">' .. r.family .. '</div>')
fam = r.family
fam = r.family
table.insert(out, '<ul class="translations-list">')
table.insert(out, '<ul class="translations-list' .. cls .. '">')
end
end
table.insert(out, '<li>' .. r.name .. ": " .. r.text .. '</li>')
table.insert(out, '<li>' .. r.name .. ": " .. r.text .. '</li>')

Latest revision as of 12:20, 3 August 2026

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

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,
				-- 2nd code letter = family, 3rd = era (P proto < Q ancient
				-- < R medieval < S modern — alphabetical IS chronological);
				-- the family letter also picks the colour class.
				famkey = code:sub(2, 2):upper(),
				erakey = code:sub(3, 3):upper(),
				known  = l ~= nil,
				text   = table.concat(words, ", "),
			})
		end
	end

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

	-- families in code-letter order (A Herta-Olaic, B Njeshan, C Andusian,
	-- D Tacchoan, E Shung-Worrehan; X isolates last), then era, then name
	table.sort(rows, function(a, b)
		if a.famkey ~= b.famkey then return a.famkey < b.famkey end
		if a.erakey ~= b.erakey then return a.erakey < b.erakey 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
				local cls = ' tfam-' .. r.famkey
				table.insert(out, '<div class="translations-family' .. cls .. '">' .. r.family .. '</div>')
				fam = r.family
				table.insert(out, '<ul class="translations-list' .. cls .. '">')
			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