模組解[]
-- vi:set sw=4 ts=4 ai sm:
---- 呢個模組係用來處理[[天佑吾王]]呢篇文可能不時要轉男女嘅問題,
---- 將男女兩個情形寫嗮出來,然後用一個模控制出男定出女,以避免
---- 改來改去會好容易改錯嘅問題

require ('strict');
local p = {};

local debug = require('模組:書名');
local WikidataIB = require('Module:WikidataIB');


--- Auxiliaries ---------------------------------------------------------------

local pronouns = {
	['en'] = {
		['n'] = {'King', 'Queen'};
		['pron nom'] = {'he', 'she'};
		['pron gen'] = {'him', 'her'};
		['pron acc'] = {'his', 'her'};
		['pron poss'] = {'his', 'hers'};
	};
	['yue'] = {
		['n'] = {'國王', '女王'};
		['pron nom'] = {'he', 'she'};
		['pron gen'] = {'him', 'her'};
		['pron acc'] = {'his', 'her'};
		['pron poss'] = {'his', 'hers'};
	};
};

local personages = {
	-- sorted by item number
	['加拿大總督'] = { item = 'Q390776', property = 'P1308' };
	['英國君主']   = { item = 'Q739941', property = 'P1308' };
}

-- 呢段係抄 / Adapted from Citation/CS1/Configuration
local df_template_patterns = {													-- table of redirects to {{Use dmy dates}} and {{Use mdy dates}}
	'{{ *([男女])性君主 *[|}]',
};

local function get_date_format ()
	local title_object = mw.title.getCurrentTitle();
	local it;
--	if title_object.namespace == 10 then										-- not in template space so that unused templates appear in unused-template-reports; 
--		return nil;																-- auto-formatting does not work in Template space so don't set global_df
--	end
	local content = title_object:getContent() or '';							-- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625
	for _, pattern in ipairs (df_template_patterns) do							-- loop through the patterns
		local match = mw.ustring.match(content, pattern);
		if match then
			it = match;															-- no need to get an actual template
		end
	if it then break end;
	end
	return it;
end

-- 抄 模組:書名
-- Return a sanitized version of an argument value
local function sanitize( arg )
	if arg ~= nil and arg:match('^{{{%w-}}}$') then
		arg = nil
	end
	return arg;
end

--- Exported, invocable functions ---------------------------------------------

-- Entry point
p.gendered = function( frame )
	local parent = frame:getParent();
	local it;
	local alt = '';
	local styles;
	local lang;
	local pos;
	local gender = p.global_df;
	local who;
	local item_number;
	local property_number;

	-- figure out what is actually being marked up as a citable
	local parts = {};
	for _, candidate in pairs({frame, parent}) do
		for k, v in pairs(candidate.args) do
			local ps = ' (參數明細:' .. debug.cvs(candidate.args) .. ')';
			v = sanitize(v);
			if debug.ref(k) == 'number' then
				assert(v ~= nil);
				table.insert(parts, v);
			elseif k == 'personage' or k == '人物' then
				who = v;
			elseif k == 'item' then
				item_number = v;
			elseif k == 'property' then
				property_number = v;
			elseif k == 'gender' or k == '性別' then
				gender = mw.ustring.match(v, '^([男女])[人性]?$');
				if not gender then
					error(name..'唔知 「'..k..'」 係乜性別'..ps);
				end
			elseif k == 'lang' or k == '話' then
				lang = v;
				if not pronouns[lang] then
					error(name..'唔識叫 「'..k..'」 嘅話'..ps);
				end
			elseif k == 'pos' then
				pos = v;
			else
				error(name..'遇到不明參數 「' .. k .. '」'..ps);
			end
		end
	end
	if who then
		if personages[who] then
			item_number = personages[who].item;
			property_number = personages[who].property;
		else
			error('呢個模組唔識 「' .. who .. '」 係邊個');
		end
	end
	if item_number and property_number then
		local item = mw.wikibase.getEntity(item_number);
		if not item then
			error('維基數據搵唔到 ' .. item_number);
		end
		local property = item:getBestStatements(property_number);
		if not property then
			error('維基數據嘅 ' .. item_number .. ' 搵唔到 ' .. property_number);
		end
		if property_number ~= 'P21' then	-- gender
			local new_item_number = property[1].mainsnak.datavalue.value.id;	-- (empirical) you can't make this stuff up
			item = mw.wikibase.getEntity(new_item_number);
			if not item then
				error('維基數據搵唔到 ' .. new_item_number);
			end
			property = item:getBestStatements('P21');	-- gender
			if not property then
				error('維基數據嘅 ' .. new_item_number .. ' 搵唔到 P21');
			end
		end
		local det = property[1].mainsnak.datavalue.value.id;
		if det then
			if det == 'Q6581097' then
				gender = '男';
			elseif det == 'Q6581072' then
				gender = '女';
			else
				error('維基數據話人物 「' .. who .. '」 嘅性別屬性搵到係 ' .. det .. ',屬未知性別');
			end
		else
			error('無法由指定嘅 item 同 property 斷定係男定女');
		end
	elseif item_number then
		error('指定咗 item,但係冇指定 property');
	elseif property_number then
		error('指定咗 property,但係冇指定 item');
	end
	if #parts == 2 then
		--
	elseif not lang then
		error('冇指定乜話');
	elseif pos then
		if not pronouns[lang][pos] then
			error('「' .. lang .. '」 冇 「' .. pos .. '」 呢種情況');
		end
		parts = pronouns[lang][pos];
	else
		error('指明嘅情況唔係男同女兩種情況(parts='..debug.cvs(parts)..')');
	end

	-- build it
	if gender == '男' then
		it = parts[1];
	elseif gender == '女' then
		it = parts[2];
	else
		error('模組邏輯出錯,唔知點解唔知係男定女(gender='..debug.cvs(gender)..')');
	end

	-- request our style sheet
--	it = table.concat ({
--			frame:extensionTag ('templatestyles', '', {src=styles}),
--			it
--		});
	return it;
end

p.test = function ()
	assert(p.gendered({
		['getParent'] = function ()
			return {
				args= { '王子', '公主', gender = '男人' };
			};
		end;
		args = {
		};
	}) == '王子');

	assert(p.gendered({
		['getParent'] = function ()
			return {
				args= { '先生', '女士', gender = '女性' };
			};
		end;
		args = {
		};
	}) == '女士');

	-- XXX as of 2023-10-22
	assert(p.gendered({
		['getParent'] = function ()
			return {
				args= { item = 'Q739941', property = 'P1308', '英王', '女王' };
			};
		end;
		['args'] = {
		};
	}) == '英王');

	-- XXX as of 2023-10-22
	assert(p.gendered({
		['getParent'] = function ()
			return {
				args= { personage = '英國君主', '英王', '女王' };
			};
		end;
		['args'] = {
		};
	}) == '英王');

	-- XXX as of 2023-10-22
	assert(p.gendered({
		['getParent'] = function ()
			return {
				args= { personage = '加拿大總督', 'gouverneur général', 'gouverneure générale' };
			};
		end;
		['args'] = {
		};
	}) == 'gouverneure générale');

end


--- Non-invocable internal functions exported for other modules to use --------

p.global_df = get_date_format();
return p;