Module:Lang

From The Deadlock Wiki
Revision as of 16:05, 22 September 2024 by Saag (talk | contribs) (Return empty string if key not found)
Jump to navigation Jump to search

Overview

This module serves as the primary interface for retrieving and formatting localized game text from the Data:Lang_*.json files. It handles variable substitution by fetching data from Module:ItemData, automatically applies rich text formatting for game-specific keywords (adding icons, colors, and links), and provides robust fallback mechanisms for missing translations.

Functions

get_string

Localizes a given string key to the current language, i.e. Data:Lang_en.json for English. This function also automatically processes game-specific formatting tags (see "Automatic Text Formatting" section below).

Note: If you need to get a string that uses a value referenced from another Data page, pass the item_name parameter to get_string.

Parameters

  • key - Key string to localize.
  • lang_code_override (OPTIONAL) - Overrides the current language to a specific language code.
  • fallback_str (OPTIONAL) - Specifies behavior when a key is not found in the target language.
    • Passing en causes it to return the English localization.
    • Passing any other string causes it to return that string.
    • Both of the above options have Template:MissingValveTranslationTooltip appended.
    • Passing dictionary causes it to return a translation via Module:Dictionary without the tooltip.
    • Use this often, as some keys are not yet localized in every language by the game. If parsing the fallback_str from Lua is computationally expensive, consider using the fallback outside this function so it only computes when needed.
  • remove_var_index (OPTIONAL) - Removes %variables% from the resulting string. -1 also removes the character prefixing %variables%, while 1 removes the postfixed character, and 0 removes only the %variables%.
  • item_name (OPTIONAL) - Required for strings containing {s:variable} placeholders. It will fetch the corresponding property from Module:ItemData to fill in the variable.

NOTE: When calling from wikitext via #invoke, parameters can be named. When calling from another Lua module, parameters must be passed in order (e.g., p.get_string(key, nil, 'en')).

Internal Logic & Fallbacks

The function includes several automatic behaviors to handle inconsistencies in the source data:

  • Key Overrides: It checks a hardcoded list of overrides for known edge cases. For example, if the key MoveSlowPercent_label is requested, the module will internally use the value for MovementSlow_label to handle this known inconsistency.
  • Post-value Label Fallback: If a key ending in _label is not found, it will automatically try again with a key ending in _postvalue_label.
  • String Parsing: If a retrieved string contains | or #, the function will automatically use only the text that comes after the final instance of that character.

Examples

Invokes from wikitext:

{{#invoke:Lang|get_string|CitadelHeroStats_Weapon_Falloff}}

Falloff Range


{{#invoke:Lang|get_string|CitadelHeroStats_Weapon_Falloff|lang_code_override=es}}

Falloff Range

Strings with Variables

For strings containing {s:variable}, provide the item_name:

Example: {{#invoke:Lang|get_string|upgrade_target_stun_desc|item_name=Knockdown}} → Apply a Stun after {s:StunDelay}s. Stun duration is increased against airborne targets.

Increases the target's gravity for the duration of the stun.

Without item_name, variables won't be filled: {{#invoke:Lang|get_string|upgrade_target_stun_desc}} → Apply a Stun after {s:StunDelay}s. Stun duration is increased against airborne targets.

Increases the target's gravity for the duration of the stun.


Examples for fallback_str

{{#invoke:Lang|get_string|StatDesc_CritDamageBonusScale|lang_code_override=es}}

Crit Bonus Scale


{{#invoke:Lang|get_string|StatDesc_CritDamageBonusScale|lang_code_override=es|fallback_str=en}}

Crit Bonus Scale


{{#invoke:Lang|get_string|StatDesc_CritDamageBonusScale|lang_code_override=es|fallback_str=Crit Damage Bonus Scale}}

Crit Bonus Scale


{{#invoke:Lang|get_string|Tech Items|fallback_str=dictionary}}


Examples for remove_var_index

{{#invoke:Lang|get_string|Citadel_HeroBuilds_DefaultHeroBuild}}

Default %hero_name% Build

TODO: Debug why is =0 still removing that extra space? Doesn't matter yet I suppose, no use cases for 0 yet {{#invoke:Lang|get_string|Citadel_HeroBuilds_DefaultHeroBuild|remove_var_index=0}}

Default %hero_name% Build


{{#invoke:Lang|get_string|Citadel_HeroBuilds_DefaultHeroBuild|remove_var_index=-1}}

Default %hero_name% Build

Automatic Text Formatting

When a string is retrieved by get_string, it undergoes several automatic transformations to convert in-game formatting tags into rich wikitext.

  • Newlines: "n is converted to a line break (
    ).
  • HTML Spans: Tags like ... are converted into styled text (e.g., bolded and colored purple).
  • Game Attribute Icons: Special tags like <Panel class="AbilityPropertyIcon prop_cooldown"> or {g:citadel_inline_attribute:'SpiritDamage'} are replaced with formatted wikitext that includes an icon, a colored label, and a wiki link. If a keyword is not recognized, it will be highlighted in red.
  • Keybinds: Tags like {g:citadel_binding:'Ability1'} are replaced with their respective text string (e.g., Ability 1). A replacement can be added to the list in case of tags that don't match their string name (e.g. AltCast > alt_cast). The module also cleans up spacing around these replacements for better readability. (Note: If we want to add additional text to the string like "[Ability] button" this needs to be supported by localizations)

search_string

Searches for the unlocalized key corresponding to a given English string, then localizes it to the current language. NOTE: Use sparingly. This function is much slower than get_string and should be avoided when the key is known. For use in other Lua modules, see _search_string.

Parameters

  • string - English string to search for.
  • lang_code_override (OPTIONAL) - Overrides the current language to a specific language code.

Examples

From wikitext:

{{#invoke:Lang|search_string|Abrams}}

Abrams

_search_string

This is the internal version of search_string, intended for use by other Lua modules. It provides the core search logic without the wikitext frame overhead or final text processing.

NOTE: This function returns the raw localized string. Unlike the invoked search_string, it does not process newlines ("n). The calling module is responsible for any further processing.

Parameters

  • label (string) - The English string to search for.
  • lang_code_override (string, optional) - The language code to translate to.

Example (from another Lua module)

local lang_module = require("Module:Lang")
-- Searches for the Spanish localization of the string "Abrams"
local localized_name = lang_module._search_string("Abrams", "es")

get_lang_code

Outputs the language subpage of the current page (e.g., "en", "es"). Defaults to "en" if the page is not a language subpage.

{{#invoke:Lang|get_lang_code}}

Script error: The function "get_lang_code" does not exist.


local p = {}

function get_lang_file(lang_code)
	local file_name = string.format("Data:Lang_%s.json", lang_code)
    local success, data = pcall(mw.loadJsonData, file_name)
    if success then
        return data
    else
        return nil
    end
end

-- Get a localized string by the raw key
p.get_string = function(frame)
	local key = frame.args[1]
	local lang_code_override = frame.args[2]

	local lang_code = lang_code_override
	if (lang_code == '' or lang_code == nil) then
    	lang_code = get_lang_code()
	end

	local data = get_lang_file(lang_code)
	if (data == nil) then
		return string.format("Lang code '%s' does not have a json file", lang_code)	
	end
	
	local label = data[key]
	if (label == nil) then 
		return ''
	end
	
	return label
end

-- get_string, but for internal use by other modules
p._get_string = function(key)
	lang_code = get_lang_code()

	local data = get_lang_file(lang_code)
	if (data == nil) then
		return nil
	end
	
	local label = data[key]
	if (label == nil) then 
		return nil
	end
	
	return label
end

-- Search for a localized string using its English label
p.search_string = function(frame)
	local label = frame.args[1]
	local lang_code_override = frame.args[2]

	local lang_code = lang_code_override
	if (lang_code == '' or lang_code == nil) then
    	lang_code = get_lang_code()
	end
	
	-- Load the language files
	local data_en = get_lang_file('en')  -- English data
	local data_lang = get_lang_file(lang_code)  -- Target language data

	if (data_lang == nil) then
		return string.format("Lang code '%s' does not have a json file", lang_code)	
	end
	
	-- Search for the key in the English data
	local key = nil
	for k, v in pairs(data_en) do
		if v == label then
			key = k  -- Find the key corresponding to the label
			break
		end
	end

	if (key == nil) then
		return string.format("English label '%s' not found", label)
	end
	
	if (data_lang[key] == nil) then
		return string.format("Key '%s' not found in for lang code '%s'", key, lang_code)
	end

	return data_lang[key]
end

-- search_string, but for internal use by other modules
p._search_string = function(label)
	lang_code = get_lang_code()

	-- Load the language files
	local data_en = get_lang_file('en')  -- English data
	local data_lang = get_lang_file(lang_code)  -- Target language data

	if (data_lang == nil) then
		return string.format("Lang code '%s' does not have a json file", lang_code)	
	end
	
	-- Search for the key in the English data
	local key = nil
	for k, v in pairs(data_en) do
		if v == label then
			key = k  -- Find the key corresponding to the label
			break
		end
	end

	if (key == nil) then
		return string.format("English label '%s' not found", label)
	end
	
	if (data_lang[key] == nil) then
		return string.format("Key '%s' not found in for lang code '%s'", key, lang_code)
	end

	return data_lang[key]
end

function get_lang_code()
    local title = mw.title.getCurrentTitle()
    local lang_code = title.fullText:match(".*/(.*)$")
	
	-- if the last part the url is not two letters, then its not a lang code,
	-- so default to english
	if (lang_code == nil or string.len(lang_code) ~= 2) then
		return 'en'	
	end
		
    return lang_code
end

return p