মডিউল নথি[তৈরি করুন]
-- Localize an enwiki module by wrapping its returned p table.
-- The intention is that only minimal changes to the enwiki module will be needed.
-- Before the module is called, local text is converted to en.
-- After the module finishes, en text is converted to local.
--
-- The enwiki module might look like this:
--     local p = {}
--     ...
--     return p
--
-- Replace that with:
--     local p = {}
--     local modwrap = require('Module:Wrapper').getWrapper()
--     ...
--         -- Use modwrap.text2en(...) if more translations are needed.
--     ...
--     return modwrap.wrapper(p)
--
-- If needed, use the following to replace the above getWrapper line.
--     local modwrap = require('Module:Wrapper').getWrapper('Module:Example/translate')
-- where Module:Example/translate contains optional functions
-- (text2en, text2local) to convert text other than digits.
--
-- Simplifying assumptions:
--    Page has {{example|one|two|name=three}}
--    Template:Example is {{#invoke|example|anyname}}
--    Module:Example returns p where p is a table including
--        function p.anyname(frame)
--            ...
--        end
-- The wrapper translates "|one|two|name=three" from the local language
-- before calling anyname, and translates the result to the local language.

local convert = require('Module:সংখ্যা রূপান্তরকারী')
local digits2en = convert._translate2en
local digits2local = convert._translate2bn
local text2en, text2local  -- forward declarations

local function makeWrapper(f)
	local function table2en(args)
		local result = {}
		for k, v in pairs(args) do
			result[k] = text2en(v)
		end
		return result
	end
	return function (...)
		local args = {...}
		local first = args[1]
		if type(first) == 'table' and type(first.getParent) == 'function' then
			local xargs = table2en(first:getParent().args)
			args = { first:newChild({ args = xargs }):newChild({ args = first.args }) }
		end
		return text2local(f(unpack(args)))
	end
end

local function wrapper(p)
	return setmetatable({}, {
		__index = function (self, key)
			local f = p[key]
			if type(f) == 'function' then
				f = makeWrapper(f)
			end
			rawset(self, key, f)
			return f
		end
	})
end

local function exclude(translator)
	-- Return a function that translates while excluding some html such as
	-- '&#42;' and the span in '<span style="color:#888">1995</span>'.
	local tEncode = {}  -- encode digits as letters to avoid translation
	for i = 0, 9 do
		tEncode[tostring(i)] = string.char(i + 65)  -- 65 is 'A'
	end
	local nid = 0
	local text2id = {}  -- [removed_text] = replacement_id
	local id2text = {}  -- inverse
	local function marker(s)
		local sid = text2id[s]
		if not sid then
			nid = nid + 1
			sid = tostring(nid):gsub('%d', tEncode)
			text2id[s] = sid
			id2text[sid] = s
		end
		return '«÷REMOVED' .. sid .. '÷»'
	end
	local function hider(s)
		return (s
			:gsub('&#[Xx]?%x+;', marker)
			:gsub('<div%s[^>]*%d[^>]*>', marker)
			:gsub('<span%s[^>]*%d[^>]*>', marker)
		)
	end
	local function unhider(s)
		return (s:gsub('«÷REMOVED(%u+)÷»', id2text))
	end
	return function (s) return unhider(translator(hider(s))) end
end

local function getWrapper(modName)
	local year2decade
	if modName then
		local xlate = require(modName)
		year2decade = xlate.year2decade
		if xlate.text2en then
			text2en = function (text)
				return xlate.text2en(digits2en(text))
			end
		end
		if xlate.text2local then
			text2local = function (text)
				return digits2local(xlate.text2local(text))
			end
		end
	end
	text2local = exclude(text2local or digits2local)
	return {
		text2en = text2en or digits2en,
		text2local = text2local,
		wrapper = wrapper,
		year2decade = year2decade,
	}
end

return {
	getWrapper = getWrapper,
}