--[[ -- This module is a replacement for  and all lang-x templates. -- It wraps text in an HTML tag containing a lang attribute with a specific -- language code. This often makes no visible changes to the text, but can help -- web browsers choose the right font, screen readers use the right -- pronunciation and more. The plain function wraps the text in the HTML tag, -- but does not otherwise change the output. The named function adds the name of -- the language before the text. --]]  -- Load required modules. local mLanguageName = require("Module:Language/name") local yesno = require("Module:Yesno") local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local data = mw.loadData("Module:Language/data/wp languages")  -- Lazily initialise Module:Arguments, as we will only need it sometimes. -- Not loading it when we don't have to will keep its transclusion count down, -- which helps to reduce load on the job queue. local mArguments  -- The p table contains functions that will be available from #invoke and that -- will be available to other Lua modules (including for use in the test cases). -- The f table contains functions linking #invoke functions to Lua functions. local p, f = {}, {}  function f.plain(code, text, options) 	checkType("plain", 1, code, "string") 	checkType("plain", 2, text, "string") 	checkType("plain", 3, options, "table", true) 	options = options or {} 	local name = p._fetchLanguageName(code) 	if not name then 		return nil 	end 	return p._createElement(code, text, name, options) end  function f.named(code, text, options) 	checkType("named", 1, code, "string") 	checkType("named", 2, text, "string") 	checkType("named", 3, options, "table", true) 	options = options or {} 	local name = p._fetchLanguageName(code) 	if not name then 		return nil 	end 	return string.format( 		"%s: %s", 		name, 		name, 		p._createElement(code, text, name, options) 	) end  function p._fetchLanguageName(code) 	-- Fetches a language name, given a language code. If no name can be 	-- found, returns nil. 	if not code then 		return nil 	end 	local name = mLanguageName.fuzzy{code = code} 	if name and name ~= "" then 		return name 	end 	return nil end  function p._createElement(code, text, name, options) 	-- Creates the HTML element. 	-- Check whether a preferred code is specified in the Wikipedia language 	-- data for the input code we are given. 	code = data[code] and data[code][2]	or code 	local tag = options.tagName or "span" 	local root = mw.html.create(tag) 	root 		:attr("lang", code) 		:wikitext(text .. p._categorise(code, name, options)) 	return tostring(root) end  function p._categorise(code, name, options) 	-- Generates the tracking category.  	local function makeCategory(cat) 		-- Makes a category wikilink. 		return string.format("%s:%s", mw.site.namespaces[14].name, cat) 	end  	local function makeTitle(...) 		-- Get a title object, using pcall to call mw.title.new to 		-- avoid producing script errors. mw.title.new will result 		-- in a script error if we are over the expensive function count 		-- limit, among other fun and exciting scenarios. 		local success, title = pcall(mw.title.new, ...) 		if success then 			return title 		else 			return nil 		end 	end  	-- Don't categorise if nocat is set. 	if yesno(options.nocat, true) then 		return "" 	end  	--[[ 	-- Don't categorise if we are not on a content page. 	-- Allow specification of options.page so that this function can be 	-- tested as if it were being run on different pages. This option 	-- isn't provided for Lua functions as it would probably not be used 	-- and would decrease performance slightly. 	--]] 	local titleObj = options.page 		and makeTitle(options.page) 		or mw.title.getCurrentTitle() 	if not titleObj or not titleObj.isContentPage then 		return "" 	end  	-- Assemble the category. 	if code == "en" or code == "eng" then 		return makeCategory( 			"Articles containing explicitly cited English-language text" 		) 	else 		local categoryName = "Articles containing " 			.. name 			.. "-language text" 		local categoryTitle = makeTitle(categoryName, 14) 		if categoryTitle and categoryTitle.exists then 			return makeCategory(categoryName) 		else 			return makeCategory( 				"Articles containing non-English-language text" 			) 		end 	end end  --[=[ -- Make the #invoke functions. The function names are taken from the f table. -- The #invoke function is named p.funcName, and the function it calls is named -- f.funcName. If the result of f.funcName(args) is nil, then p.funcName -- returns the blank string. This allows for use of both Lua-like and -- wikitext-like idioms should any of the validation checks fail. We use -- Module:Arguments to get the arguments from the frame object. We also -- make the f.funcName functions available to other Lua modules under the name -- p._funcName. --]=] for funcName, func in pairs(f) do 	p[funcName] = function (frame) 		mArguments = require("Module:Arguments") 		local args = mArguments.getArgs(frame) 		-- Get the code and text variables. 		local code = args.code 		local text = args.text 		if not code or not text then 			-- Give up gracefully if we don't have the required input. 			return text or "" 		end 		-- Pass values through to the options table. 		local options = {} 		options.tagName = args.type 		options.nocat = args.nocat 		return f[funcName](code, text, options) or "" 	end 	-- Create the function to access from other Lua modules. 	p["_" .. funcName] = func end  return p