Module:GameText

From Terraria Wiki
Jump to navigation Jump to search
Lua.svg Documentation The documentation below is transcluded from Module:GameText/doc. (edit | history)

This module provides the functionality of the {{gameText}} template.

The module can be called from wikitext with the following functions:

Displays the string associated with the given key. If the given key refers to a group of strings (e.g. WorldGeneration), then it displays all strings in that group separated by the character . This is the most basic function and is used by {{gameText}}.
  • {{#invoke:GameText| getRaw | <key> | prefix = <output prefix> | postfix = <output postfix> | <placeholder replacements> | lang = <language> }}
Displays the string exactly as it is defined in the source language JSON file. The get function wraps its output in <span class="gameText"> and replaces linebreaks (\n) with HTML linebreaks (<br/>) for a more intuitive output. This function does not do that.
  • {{#invoke:GameText| listAll | <key> | lang = <language> }}
Displays all keys and their strings that are in the group of the given key (e.g. WorldGeneration), separated by the character ¦. The separator between each key and string is . If no key is provided, then merely lists all keys in the entire database.
  • {{#invoke:GameText| listKeys | <key> | lang = <language> }}
Similar to the listAll function, except that only the keys are displayed in any case, never the strings.
  • {{#invoke:GameText| printTable | lang = <language> }}
Displays a tabular visualization of the entire database, where the left column is the key and the right column is the string. The keys are ordered alphabetically.

The module can be called from another module with the following functions:

Returns the string associated with the given key.
Transforms the replacement arguments into a table and returns it.

local trim = mw.text.trim

local args_table -- cache
-- helper function
local getArg = function(key)
	local value = trim(args_table[key] or '')
	return (value ~= '') and value or nil
end

local concatTable = function(tbl, sep)
	local arr = {}
	for _, v in pairs(tbl) do
		arr[#arr+1] = v
	end
	return table.concat(arr, sep)
end

local db = {}
local loadDatabase = function(lang)
	if not db[lang] then
		local status, result = xpcall(
			function() return mw.loadData("Module:GameText/loaddata-"..lang) end, -- try to load database for that language
			function() return mw.loadData("Module:GameText/loaddata-en") end -- if it doesn't exist, load en database as fallback
		)
		db[lang] = result or {}
	end
	return db[lang]
end

-- key: e.g.  "BuffName.ManaRegeneration".
-- return string or table, nil when key or data is invalid.
local get -- for recursion
get = function(key, lang)
	local data = db[lang] or loadDatabase(lang or 'en')
	local key = trim(key)
	local pos = 1
	for st,sp in function() return string.find(key, '.', pos, true) end do
		index = string.sub(key, pos, st-1)
		data = data[tonumber(index) or index] -- convert to number for pure number index.
		if not data then
			return nil
		end
		pos = sp + 1
	end
	if pos ~= 0 then 
		key = string.sub(key, pos)
	end
	local result = data[tonumber(key) or key]
	if result and type(result) == 'string' then
		-- for ref marks such as {$CommonItemTooltip.RightClickToOpen}
		result = string.gsub(result, "({%$(.-)})", function(_, ref) return get(ref, lang) end)
	end
	return result
end

-- args: replacement table, e.g.: { ["{0}"] = "Party Girl", ["<right>"] = "Right click" }
local getText = function(key, lang, args)
	if not key then
		return
	end
	local str = get(key, lang) or get(key, 'en')
	if not str then
		return
	end
	str = string.gsub(str, "{%?.-}", "") -- strip condition marks, e.g.: "{?Homeless}"" -> ""
	if args then
		str = string.gsub(str, "%b{}", args)
		str = string.gsub(str, "%b<>", args)
	end
	return str
end

-- bulid replacement table from template arguments.
-- e.g.: |x_0=Party Girl|y_right=Right click -> { ["{0}"] = "Party Girl", ["<right>"] = "Right click" }
local replacementArgs = function(argsTable)
	local args = {}
	local flag = false
	for k, v in pairs(argsTable) do
		string.gsub(k, '^x_(.+)', function(n)
			args['{'..n..'}'] = v
			flag = true
		end)
		string.gsub(k, '^y_(.+)', function(n)
			args['<'..n..'>'] = v
			flag = true
		end)
	end
	return flag and args or nil
end

local getSectionList = function()
	local data = db['en'] or loadDatabase('en')
	local arr = {}
	for k, v in pairs(data) do
		arr[#arr + 1] = k
	end
	return arr
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

return {
	---------- for template ----------------
	get = function(frame)
		args_table = frame:getParent().args -- cache
		local str = getText(getArg(1), getArg('lang') or frame.args['lang'], replacementArgs(args_table))
		if str then
			return '<span class="gameText">' .. string.gsub(str, '\n', '<br/>') .. '</span>'
		end
	end,

	getRaw = function(frame)
		return (frame.args['prefix'] or '')
		     ..(getText(frame.args[1], frame.args['lang'] or frame:expandTemplate{title = 'lang'}, replacementArgs(frame.args)) or '')
		     ..(frame.args['postfix'] or '')
	end,

	-- export a section as an Array of Extension:ArrayFunctions
	getSection = function(frame)
		args_table = frame.args -- cache
		return mw.af.export(get(getArg(1), getArg('lang')))
	end,
	
	getSectionList = function(frame)
		args_table = frame.args -- cache
		return mw.af.export(getSectionList())
	end,

	listAll = function(frame)
		local lang = frame.args['lang'] or 'en'
		loadDatabase(lang)
		local arr = {}
		if frame.args[1] then
			if not db[lang][frame.args[1]] then
				return
			end
			for k, v in pairs(db[lang][frame.args[1]]) do
				arr[#arr + 1] = k .. '₪' .. v
			end

		else
			for k, v in pairs(db[lang]) do
				arr[#arr + 1] = k
			end
		end
		return table.concat(arr, '¦')
	end,

	listKeys = function(frame)
		local lang = frame.args['lang'] or 'en'
		loadDatabase(lang)
		local arr = {}
		for k, v in pairs(frame.args[1] and (db[lang][frame.args[1]] or {}) or db[lang]) do
			arr[#arr + 1] = k
		end
		return table.concat(arr, '¦')
	end,

	printTable = function(frame)
		local lang = frame.args['lang'] or 'en'
		local data = loadDatabase(lang)

		local all_keys = {}
		local all_values = {}
		function recurse(datatable, previous_key)
			for this_subkey, data in pairs(datatable) do
				local next_key
				if previous_key ~= '' then
					next_key = previous_key .. '.' .. this_subkey
				else
					next_key = this_subkey
				end
				if type(data) ~= 'table' then
					table.insert(all_keys, next_key)
					all_values[next_key] = data
				else
					recurse(data, next_key)
				end
			end
		end
		recurse(data, '')
		table.sort(all_keys)

		local output = {'<table class="wikitable"><tr><th>Key</th><th>String</th></tr>'}
		for i = 1, #all_keys do
			local key = all_keys[i]
			local keyCell = '<td><code>' .. key .. '</code></td>'
			local valueCell = '<td><span class="gameText">' .. string.gsub(all_values[key], '\n', '<br/>') .. '</span></td>'
			table.insert(output, '<tr>' .. keyCell .. valueCell .. '</tr>')
		end
		table.insert(output, '</table>')
		return table.concat(output)
	end,
	

	-- purge database cache
	-- from template: {{#invoke:gameText|purge|lang=<lang>}}
	-- from module: require('Module:gameText').purge(<lang>)
	purge = function(frame)
		local lang
		if frame == mw.getCurrentFrame() then
			lang = frame.args['lang']
		else
			lang = frame
		end
		lang = lang or 'en'
		require('Module:GameText/loaddata').purge(lang)
	end,
	

	---------- for module ----------------
	getText = getText,
	getData = get,
	getSections = getSectionList,
}