-- 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  --    Template:Example is  --    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 	-- '*' and the span in '1995'. 	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, }