Module:Dictionary: Difference between revisions

mNo edit summary
No edit summary
 
Line 1: Line 1:
local p = {}
local p = {}
-- Localize core functions to bypass global table lookups (_G)
local type = type
local tonumber = tonumber
local string_format = string.format
local string_gsub = string.gsub
-- Load data data sets once at module initialization
local dictionary_data = mw.loadJsonData("Data:Dictionary")
local dictionary_data = mw.loadJsonData("Data:Dictionary")
local lang_codes_set = mw.loadJsonData("Data:LangCodes.json")
local lang_codes_set = mw.loadJsonData("Data:LangCodes.json")
-- Persistent cache across multiple #invoke calls on the same page
local cached_lang_code = nil
local current_frame = nil
-- Forward declare local function for speed and scope
local function get_lang_code()
if cached_lang_code then
return cached_lang_code
end
-- mw.title.getCurrentTitle() is expensive; we cache the result
local title = mw.title.getCurrentTitle()
local lang_code = title.fullText:match(".*/(.-)$")
if not lang_code or not lang_codes_set[lang_code] then
cached_lang_code = 'en'
else
cached_lang_code = lang_code
end
return cached_lang_code
end
-- Used by [[Template:Translate]]
-- Used by [[Template:Translate]]
-- Original author User:sur v2 User:mgpt
-- Get a localized string by the raw key
p.translate = function(key, lang_code_override, fallback_str, vars)
p.translate = function(key, lang_code_override, fallback_str, vars)
-- If called internally (direct Lua call), args will be passed directly.
local is_frame = false
    -- If called from wikitext, "key" will be the "frame" object, and we get args from "frame.args".
local args


    -- Handle the case where it's called via #invoke (i.e., from wikitext)
-- Handle the case where it's called via #invoke (i.e., from wikitext)
    if type(key) == "table" and key.args then
if type(key) == "table" and key.args then
        local frame = key
is_frame = true
        local args = frame.args
current_frame = key
        key = frame.args[1]
args = current_frame.args
        lang_code_override = frame.args["lang_code_override"]
key = args[1]
        fallback_str = frame.args["fallback_str"]
lang_code_override = args["lang_code_override"]
        vars = {}
fallback_str = args["fallback_str"]
        local i = 2
end
        while args[i] do
            table.insert(vars, args[i])
            i = i + 1
        end
    end


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


local translations = dictionary_data[key]
local translations = dictionary_data[key]
if (translations == nil) then return string.format("Key '%s' is not in Data:Dictionary", key) end
if not translations then  
return string_format("Key '%s' is not in Data:Dictionary", key or 'nil')  
end


local translation = translations[lang_code]
local translation = translations[lang_code]


if (translation == nil) then
if not translation then
-- Determine the appended tooltip
-- Determine the appended tooltip
local needs_translation_expand = ''
local needs_translation_expand = ''
if (key ~= 'MissingValveTranslationTooltip' and key ~= 'NeedsTranslationTooltip' and key ~= 'NotesNeedsTranslation') then
if key ~= 'MissingValveTranslationTooltip' and key ~= 'NeedsTranslationTooltip' and key ~= 'NotesNeedsTranslation' then
local template_args = {}
local template_args = {}
if key == 'Notes' then
if key == 'Notes' then
template_args[1] = 'NotesNeedsTranslation'
template_args[1] = 'NotesNeedsTranslation'
end
end
needs_translation_expand = mw.getCurrentFrame():expandTemplate{title = 'NeedsTranslationTooltip', args=template_args}
-- Reuse the frame context to avoid unnecessary boundary shifts
if not current_frame then
current_frame = mw.getCurrentFrame()
end
needs_translation_expand = current_frame:expandTemplate{title = 'NeedsTranslationTooltip', args = template_args}
end
end


-- Determine the fallback string to use
-- Determine the fallback string to use
-- Default to english fallback if none specified or if en specified
if fallback_str == 'en' or not fallback_str then
if (fallback_str == 'en' or fallback_str == nil) then
translation = translations["en"]
translation = translations["en"]
else
else
translation = fallback_str
translation = fallback_str
 
-- If english translation is missing, default to the key instead of blank string
-- Only fallback to key if explicit fallback_str fails
if (translation == nil) then
if not translation then
translation = key
translation = key
end
end
Line 60: Line 90:


-- Add the tooltip
-- Add the tooltip
if (translation ~= '' and translation ~= nil) then
if translation and translation ~= '' then
translation = translation .. needs_translation_expand
translation = translation .. needs_translation_expand
end
end
end
end


if vars ~= nil then
-- Variable Substitution Optimization
for i, v in ipairs(vars) do
if translation then
if translation ~= nil then
if is_frame then
translation = translation:gsub("{{{" .. i .. "}}}", v or "")
-- Single-pass regex replacement directly from frame arguments (Zero allocations)
end
translation = string_gsub(translation, "{{{(%d+)}}}", function(n)
return args[tonumber(n) + 1] or ""
end)
elseif vars then
-- Single-pass regex replacement for standard Lua table arrays
translation = string_gsub(translation, "{{{(%d+)}}}", function(n)
return vars[tonumber(n)] or ""
end)
end
end
end
end


return translation
return translation
end
function get_lang_code()
    local title = mw.title.getCurrentTitle()
    local lang_code = title.fullText:match(".*/(.*)$")
-- Not a lang code, default to english
if (lang_code == nil or lang_codes_set[lang_code] == nil) then
return 'en'
end
    return lang_code
end
end


return p
return p