Editing Module:Lang

Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
local p = {}
local p = {}
local util_module = require("Module:Utilities")
local util_module = require("Module:Utilities")
local lang_codes_set = mw.loadJsonData("Data:LangCodes.json")
 
local dictionary_module = require("Module:Dictionary")
-- Set of valid language codes
local lang_codes_set = {
en = true,
es = true,
['zh-hant'] = true
}


-- Overrides applied to searches by key. Designed to handle edge cases where
-- Overrides applied to searches by key. Designed to handle edge cases where
-- the expected key does not have a localization entry
-- the expected key does not have a localization entry
local KEY_OVERRIDES = {
local KEY_OVERRIDES = {
BurnDurationBase_label = 'AfterburnDurationBase_label',
BurnDurationBase_postfix = 'AfterburnDurationBase_postfix',
     MoveSlowPercent_label = 'MovementSlow_label',
     MoveSlowPercent_label = 'MovementSlow_label',
     BonusHealthRegen_label = 'HealthRegen_label',
     BonusHealthRegen_label = 'HealthRegen_label',
Line 19: Line 22:
     EvasionChance_label = 'EvasionChance_Label',
     EvasionChance_label = 'EvasionChance_Label',
     DelayBetweenShots_label = 'DelayBetweenShots_Label',
     DelayBetweenShots_label = 'DelayBetweenShots_Label',
    MoveSlowDuration_postfix = 'EnemyMoveSlowDuration_postfix',
    StaminaRecoveryDisabledDuration_postfix = 'AbilityDuration_postfix',
    PostInvisBuffDuration_label = 'BuffDuration_label',
    PostInvisBuffDuration_postfix = 'BuffDuration_postfix',
    ProjectileFuse_label = 'BellLifetime_label',
    ProjectileFuse_postfix = 'BellLifetime_postfix',
    SelfBuffDuration_label = 'BuffDuration_label',
    SelfBuffDuration_postfix = 'BuffDuration_postfix',
    LifeStealPercentOnHit_label = 'LifestealPercentOnHit_label',
    LifeStealPercentOnHit_postfix = 'LifestealPercentOnHit_postfix',
    AuraFireRateBonus_label = 'FireRateBonus_label',
    AuraFireRateBonus_postfix = 'FireRateBonus_postfix',
    MoveSlowDuration_label = 'SlowDuration_label',
    MoveSlowDuration_postfix = 'SlowDuration_postfix',
DashRange_label = 'TargetDashRadius_label',
DashRange_postfix = 'TargetDashRadius_postfix',
SpeedOnLandDuration_label = 'BuffDuration_label',
SpeedOnLandDuration_postfix = 'BuffDuration_postfix',
SummonCount_label = 'GhoulCount_label',
TetherDuration_label = 'ImmobilizeTrap_CurseDuration_label'
}
}


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


local function process_newlines(text)
-- Get a localized string by the raw key
    if not text or type(text) ~= "string" then return text end
p.get_string = function(frame)
    -- Replace "n with newline character
local key = frame.args[1]
    return text:gsub('"n', '<br/>')
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_OVERRIDES[key] or key]
if (label == nil) then
return ''
end
return label
end
end


local function process_html_tags(text, frame)
-- Get a localized string by the raw key, return fallback string if unable to be localized
    if not text or type(text) ~= "string" then return text end
p.get_string_fallback = function(frame)
   
local key = frame.args[1]
    local replacements = {
local fallback = frame.args[2]
    BonusFireRate = {icon='{{Icon/Brown|[[File:Fire_Rate.png|link=Fire Rate|20px]]}}', label_color='#ffefd7', link='Fire Rate'},
    BonusMoveSpeed = {icon='{{Icon/Green|[[File:Move_speed.png|link=Move speed|20px]]}}', label_color='#ffefd7', link='Move speed'},
     local lang_code = get_lang_code()
    BonusSprintSpeed = {icon='{{Icon/Green|[[File:Move_speed.png|link=Sprint speed|20px]]}}', label_color='#ffefd7', link='Sprint speed'},
    BonusSpiritDamage = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', label_color='#bc8ee8', link='Spirit Damage'},
local data = get_lang_file(lang_code)
    BonusWeaponDamage = {icon='{{Icon/NoColor|[[File:Bullet Damage.png|link=Weapon Damage|20px]]}}', label_color='#ec981a', link='Weapon Damage'},
if (data == nil) then
    bullet_armor_up = {icon='{{Icon/White|[[File:Barrier.png|link=Barrier|20px]]}}', label_color='#ffefd7', link='Barrier'},
return string.format("Lang code '%s' does not have a json file", lang_code)
    bullet_damage = {icon='{{Icon/NoColor|[[File:Bullet_damage.png|link=Weapon Damage|20px]]}}', label_color='#ec981a', link='Weapon Damage'},
end
    BulletResist = {icon='{{Icon/Brown|[[File:Bullet_Armor.png|link=Damage_Resistance|20px]]}}', label_color='#ec981a', link='Damage_Resistance'},
    cast = {icon='{{Icon/White|[[File:Cast.png|link=|20px]]}}', label_color='#ffefd7', link=''},
    CombatBarrier = {icon='{{Icon/White|[[File:Bullet Armor (item).png|link=Damage_Resistance|20px]]}}', label_color='#ffefd7', link='Barrier'},
    cooldown = {icon='{{Icon/White|[[File:AttributeIconTechDuration.png|link=Ability Cooldown|20px]]}}', label_color='#ffefd7', link='Ability Cooldown'},
    damage = {icon='{{Icon/NoColor|[[File:Damage heart.png|link=Damage|20px]]}}', label_color='#ec981a', link='Damage'},
    DamageAmp = {icon='{{Icon/White|[[File:Damage heart.png|link=Damage Amp|20px]]}}', label_color='#ffefd7', link='Damage Amp'},
    FireRate = {icon='{{Icon/White|[[File:Fire_Rate.png|link=Fire Rate|20px]]}}', label_color='#ffefd7', link='Fire Rate'},
    fire_rate = {icon='{{Icon/White|[[File:Fire_Rate.png|link=Fire Rate|20px]]}}', label_color='#ffefd7', link='Fire Rate'},
    Heal = {icon='{{Icon/Green|[[File:Healing.png|link=Health_Regen|20px]]}}', label_color='#13f278', link='Health_Regen'},
    Healing = {icon='{{Icon/Green|[[File:Healing.png|link=Healing|20px]]}}', label_color='#13f278', link='Healing'},
    Immobilize = {icon='{{Icon/White|[[File:Immobilize.png|link=Status Effects#Immobilized|20px]]}}', label_color='#ffefd7', link='Status Effects#Immobilized'},
    invisible = {icon='{{Icon/White|[[File:Invisible.png|link=|20px]]}}', label_color='#ffefd7', link=''},
    KnockBack = {icon='{{Icon/NoColor|[[File:Displacement.png|link=|20px]]}}', label_color='#ffefd7', link='Status_Effects'},
    KnockUp =  {icon='{{Icon/NoColor|[[File:Displacement.png|link=|20px]]}}', label_color='#ffefd7', link='Status_Effects'},
    MaxHealth = {icon='{{Icon/Green|[[File:Healing.png|link=Health|20px]]}}', label_color='#13f278', link='Health'},
    MeleeDamage = {icon='{{Icon/Brown|[[File:Melee damage.png|link=Melee Damage|20px]]}}', label_color='#ec981a', link='Melee Damage'},
    MoveSpeed = {icon='{{Icon/Green|[[File:Move_speed.png|link=Move speed|20px]]}}', label_color='#ffefd7', link='Move speed'},
    move_speed = {icon='{{Icon/Green|[[File:Move_speed.png|link=Move speed|20px]]}}', label_color='#ffefd7', link='Move speed'},
    Pull =      {icon='{{Icon/NoColor|[[File:Displacement.png|link=|20px]]}}', label_color='#ffefd7', link='Status_Effects'},
    Pulling =  {icon='{{Icon/NoColor|[[File:Displacement.png|link=|20px]]}}', label_color='#ffefd7', link='Status_Effects'},
    Pulls =    {icon='{{Icon/NoColor|[[File:Displacement.png|link=|20px]]}}', label_color='#ffefd7', link='Status_Effects'},
    PureDamage = {icon='{{Icon/NoColor|[[File:Damage.png|link=Pure Damage|20px]]}}', label_color='#ffefd7', link='Pure Damage'},
    ReducedFireRate = {icon='{{Icon/Brown|[[File:Fire_Rate.png|link=Fire Rate|20px]]}}', label_color='#ffefd7', link='Fire Rate'},
    Regen = {icon='{{Icon/Green|[[File:Healing.png|link=Health_Regen|20px]]}}', label_color='#13f278', link='Health_Regen'},
    revealed = {icon='{{Icon/White|[[File:Revealed.png|link=|20px]]}}', label_color='#ffefd7', link=''},
    silence = {icon='{{Icon/White|[[File:Silence.png|link=|20px]]}}', label_color='#ffefd7', link=''},
    Silence = {icon='{{Icon/Purple|[[File:Silence.png|link=Silence|20px]]}}', label_color='#bc8ee8', link='Silence'},
    Slow = {icon='{{Icon/White|[[File:MoveSlow.png|link=Movement_Slow|20px]]}}', label_color='#ffefd7', link='Movement_Slow'},
    slow = {icon='{{Icon/White|[[File:MoveSlow.png|link=Movement_Slow|20px]]}}', label_color='#ffefd7', link='Movement_Slow'},
    SlowResistance = {icon='{{Icon/White|[[File:MoveSlow.png|link=Movement_Slow#Movement_Slow_Resist|20px]]}}', label_color='#ffefd7', link='Movement_Slow#Movement_Slow_Resist'},
    Spirit = {icon='{{Icon/NoColor|[[File:Spirit_icon.png|link=Spirit Power|20px]]}}', label_color='#bc8ee8', link='Spirit Power'},
    SpiritDamage = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', label_color='#bc8ee8', link='Spirit Damage'},
    SpiritDPS = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', label_color='#bc8ee8', link='Spirit Damage'},
    SpiritIcon = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', link='Spirit Damage'},
    SpiritResist = {icon='{{Icon/Purple|[[File:Spirit_Armor.png|link=Damage_Resistance|20px]]}}', label_color='#bc8ee8', link='Damage_Resistance'},
    StatDesc_TechPower = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', label_color='#bc8ee8', link='Spirit Damage'},
    Stun = {icon='{{Icon/White|[[File:Status_Stun.png|link=Stun|20px]]}}', link='Stun'},
    stun = {icon='{{Icon/White|[[File:Stun.png|link=|20px]]}}', label_color='#ffefd7', link=''},
    tech_armor_up = {icon='{{Icon/White|[[File:Barrier.png|link=Barrier|20px]]}}', label_color='#ffefd7', link='Barrier'},
    tech_damage = {icon='{{Icon/NoColor|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}', link='Spirit Damage'},
    WeaponDamage = {icon='{{Icon/NoColor|[[File:Bullet Damage.png|link=Weapon Damage|20px]]}}', label_color='#ec981a', link='Weapon Damage'},
    Heal = {icon='{{Icon/Green|[[File:Healing.png|link=Healing|20px]]}}', label_color='#13f278', link='Healing'},
    Heals = {icon='{{Icon/Green|[[File:Healing.png|link=Healing|20px]]}}', label_color='#13f278', link='Healing'},
}
 
    -- Process HTML spans
    text = text:gsub('<span class="highlight">(.-)</span>', "<span style= font-weight:bold>%1</span>")
    text = text:gsub('<span class="highlight_spirit">(.-)</span>', '<span style="font-weight:bold; color:#bc8ee8">%1</span>')
    text = text:gsub('<span class="highlight_courage">(.-)</span>', '<span style="font-weight:bold; color:#ec981a">%1</span>')
    text = text:gsub('<span class="diminish">(.-)</span>', '<span style="font-style: italic;color:#C0C0C0">%1</span>')
    text = text:gsub('<span class=".-">(.-)</span>', '%1')
    text = text:gsub('<Panel class=\"AbilityPropertyIcon StatDesc_TechPower\">', '{{Icon/Purple|[[File:Spirit damage.png|link=Spirit Damage|20px]]}}')
    text = text:gsub('</Panel>', '')
   
    -- Process panel tags
text = text:gsub('<Panel class=\"AbilityPropertyIcon prop_(.-)\">', function(key)
    local replacement = replacements[key]
    if replacement then
        local label_color = replacement.label_color or 'inherit'
        local icon = replacement.icon or ''
        local link = replacement.link or ''
        -- pre-process string, then check to omit link if the string is empty
        local translated = frame:preprocess('{{#invoke:Lang|get_string|InlineAttribute_' .. key .. '}}')
       
        if translated == '' then
            return string.format('<span class="no-blue-link" style="text-wrap:nowrap; font-weight:bold; color:%s;">%s</span>', label_color, icon)
        else
            return string.format('<span class="no-blue-link" style="text-wrap:nowrap; font-weight:bold; color:%s;">%s [[%s|%s]]</span>',
                label_color,
                icon,
                link,
                translated)
        end
    else
        return '<span style="color:red;font-weight:bold;border-bottom:1px dotted red;" title="Missing attribute definition - Add \''..key..'\' to local replacements in [Module:Lang]">['..key..']</span>'
    end
end)
   
     -- Process citadel_inline_attribute tags
text = text:gsub("{g:citadel_inline_attribute:'(.-)'}", function(key)
    local replacement = replacements[key]
    if replacement then
        local label_color = replacement.label_color or 'inherit'
        local icon = replacement.icon or ''
        local link = replacement.link or ''
        -- pre-process string, then check to omit link if the string is empty
        local translated = frame:preprocess('{{#invoke:Lang|get_string|InlineAttribute_' .. key .. '}}')
       
        if translated == '' then
            return string.format('<span class="no-blue-link" style="text-wrap:nowrap; font-weight:bold; color:%s;">%s</span>', label_color, icon)
        else
            return string.format('<span class="no-blue-link" style="text-wrap:nowrap; font-weight:bold; color:%s;">%s [[%s|%s]]</span>',
                label_color,
                icon,
                link,
                translated)
        end
    else
        return '<span style="color:red;font-weight:bold;border-bottom:1px dotted red;" title="Missing attribute definition - Add \''..key..'\' to local replacements in [Module:Lang]">['..key..']</span>'
    end
end)
   
    -- List for keybinds with mismatched names. Replace with the correct name under "citadel_keybind_[key]" in Data:Lang
    keybinds = {
        MoveForward = "forward",
        AltCast = "alt_cast",
        }
   
    -- Process citadel_binding/citadel_keybind tags to replace with keybind strings/templates
text = text:gsub("{g:citadel_binding:'(.-)'}", function(key)
  -- convert key to lowercase
        local lower_key = key:lower()
        -- look up key with Module:Lang. check if it has a replacement key first
        local replacement = keybinds[key] or lower_key
        local translated = frame:preprocess('{{#invoke:Lang|get_string|citadel_keybind_'.. replacement ..'}}')
  if translated ~= nil and translated ~= '' then
        return "'''" .. translated .. "'''"
        else
            return '<span style="color:red;font-weight:bold;border-bottom:1px dotted red;" title="Missing keybind - Add \''..key..'\' to local replacements in [Module:Lang]">['..key..']</span>'
        end
end)
    -- Force spaces around keybinds where the source data omits them
local label = data[key]
    text = text:gsub("'''([a-zA-Z])", "''' %1")
if (label == nil) then
return fallback
end
return label
end


    -- Clean up extra spaces between a keybind and following punctuation
--Get a localized string by the raw key, and remove %variable% from key
    text = text:gsub("'''%s+:", "''':")
p.get_string_remove_var = function(frame)
 
local key = frame.args[1]
return frame:preprocess(text)
local spaces = frame.args[2]
local lang_code = get_lang_code()
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]
label = util_module.remove_var(label, spaces)
return label
end
end


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


function p.get_string(key, lang_code_override, fallback_str, remove_var_index, item_name)
local data = get_lang_file(lang_override or lang_code)
    -- Get frame object (either passed directly or via first argument)
if (data == nil) then
    local frame
return nil
    if type(key) == "table" and key.args then
end
        frame = type(key.preprocess) == "function" and key or mw.getCurrentFrame()
       
local label = data[KEY_OVERRIDES[key] or key]
        local args = key.args
if (label == nil) then
        key = args[1]
return nil
        lang_code_override = args["lang_code_override"]
end
        fallback_str = args["fallback_str"]
        remove_var_index = args["remove_var_index"]
return label
        item_name = args["item_name"]
end
    else
        frame = mw.getCurrentFrame()
    end


    -- Determine lang_code if not overridden
-- Search for a localized string using its English label
    local lang_code = lang_code_override
p.search_string = function(frame)
    if (lang_code == '' or lang_code == nil) then
local label = frame.args[1]
        lang_code = p.get_lang_code()
local lang_code_override = frame.args[2]
    end


    -- Retrieve lang data
local lang_code = lang_code_override
    local data = get_lang_file(lang_code)
if (lang_code == '' or lang_code == nil) then
    if (data == nil) then
    lang_code = get_lang_code()
        return string.format("Lang code '%s' does not have a json file", lang_code)  
end
    end
   
-- Load the language files
    -- Localize
local data_en = get_lang_file('en')  -- English data
    local label = data[KEY_OVERRIDES[key] or key]
local data_lang = get_lang_file(lang_code)  -- Target language data


-- Some labels use key with "_postvalue_label" instead, so check this if previous search failed
if (data_lang == nil) then
if label == nil and key ~= nil and key:sub(-6) == '_label' then
return string.format("Lang code '%s' does not have a json file", lang_code)
    local postvalue_key = key:sub(1, -7) .. '_postvalue_label'
    label = data[postvalue_key]
end
end
    if (label == nil) then
-- Search for the key in the English data
        -- Apply fallback (without HTML processing for fallback)
local key = nil
        local fallback_tooltip = frame:expandTemplate{title = "MissingValveTranslationTooltip"}
for k, v in pairs(data_en) do
        local fallback
if v == label then
        if (fallback_str == 'en') then
key = -- Find the key corresponding to the label
            fallback = p.get_string(key, 'en', key .. fallback_tooltip, remove_var_index, item_name)
break
        elseif fallback_str == 'dictionary' then
end
            return dictionary_module.translate(key, lang_code_override)
end
        elseif fallback_str ~= nil then
            fallback = fallback_str
        else
            return ''
        end
        return fallback .. fallback_tooltip
    end
   
    -- Always retrieve the last parameter if string contains "|"
    if type(label) == "string" and label:find("|") then
        local parts = mw.text.split(label, "|")
        label = parts[#parts]
    end
   
  -- Remove hashtags
  if type(label) == "string" and label:find("#") then
        local parts = mw.text.split(label, "#")
        label = parts[#parts]
    end


    -- Apply remove_var
if (key == nil) then
    if (remove_var_index ~= nil) then  
return string.format("English label '%s' not found", label)
        label = util_module.remove_var(label, remove_var_index)
end
    end
   
if (data_lang[key] == nil) then
    -- Process variables if item_name is provided
return string.format("Key '%s' not found in for lang code '%s'", key, lang_code)
    if item_name and item_name ~= '' then
end
        local item_data_module = require('Module:ItemData')
        label = label:gsub("{s:([^}]+)}", function(variable_name)
            -- Get the value from ItemData
            local value = item_data_module.get_prop({args = {item_name, variable_name}})
           
            -- If value exists, remove non-number symbols (but keep + and -)
            if value then
                value = value:gsub("[^0-9+-.]", "")
                -- Return empty string if nothing left, otherwise return the filtered value
                return value ~= "" and value or variable_name
            else
                return variable_name -- Fallback to variable name if value not found
            end
        end)
    end
   
    -- Process HTML and return as "raw" HTML
    label = process_newlines(label)
    label = process_html_tags(label, frame)
    -- Create HTML object for safe output
    local html = mw.html.create()
    html:wikitext(label)
    return tostring(html)
end


-- Search for a localized string using its English label
return data_lang[key]
p.search_string = function(frame)
    local label = frame.args[1]
    local lang_code_override = frame.args[2]
 
    local result = p._search_string(label, lang_code_override)
    result = process_newlines(result)
    return result
end
end


-- search_string, but for internal use by other modules
-- search_string, but for internal use by other modules
p._search_string = function(label, lang_code_override)
p._search_string = function(label)
    lang_code = lang_code_override
lang_code = get_lang_code()
    if (lang_code == '' or lang_code == nil) then
        lang_code = p.get_lang_code()
    end


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


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


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


    return data_lang[key]
return data_lang[key]
end
end


p.get_lang_code = function()
function get_lang_code()
     local title = mw.title.getCurrentTitle()
     local title = mw.title.getCurrentTitle()
     local lang_code = title.fullText:match(".*/(.*)$")
     local lang_code = title.fullText:match(".*/(.*)$")
   
    if lang_code == nil or lang_codes_set[lang_code] == nil then
if lang_code == nil or lang_codes_set[lang_code] == nil then
        return 'en'  
return 'en'
    end
end
       
     return lang_code
     return lang_code
end
end


return p
return p
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template