(tweak i18n.) |
(move plural processing outside from module.) |
||
Line 2: | Line 2: | ||
------- l10n info -------------- |
------- l10n info -------------- |
||
local l10n_info = mw.loadData('Module:Item/l10n') |
local l10n_info = mw.loadData('Module:Item/l10n') |
||
− | |||
− | -- l10n function to get plural form, it may be different for each language. If function for target language does not exist, the EN version is used. |
||
− | -- about the function itself: |
||
− | -- return plural form, nil if no pluralism processing occurs. |
||
− | -- _arg1 is the original text(without auto translation), _arg2 is custom text(without auto translation) or plural postfix, may be s/es/ies/ves (for english). |
||
− | -- the retruned result will be auto translated. |
||
− | local plural = { |
||
− | -- for English (en) |
||
− | ['en'] = function(_arg1, _arg2) |
||
− | -- intuitive pluralism |
||
− | -- The comparisons are performed in order, so putting the more common ones in front gives the best performance. |
||
− | if _arg2 == 's' then |
||
− | local suffix1 = _arg1:sub(-1) -- cache for better performance. |
||
− | local suffix2 = _arg1:sub(-2) -- cache for better performance. |
||
− | if suffix1 == 'y' then |
||
− | if suffix2 == 'ay' or suffix2 == 'ey' or suffix2 == 'iy' or suffix2 == 'oy' or suffix2 == 'uy' then |
||
− | return _arg1 .. 's' -- eg. ray->rays |
||
− | else |
||
− | return _arg1:sub(1, -2) .. 'ies' -- eg. firefly->fireflies |
||
− | end |
||
− | end |
||
− | if suffix2 == 'fe' and string.lower(_arg1) ~= 'safe' then |
||
− | return _arg1:sub(1, -3) .. 'ves' -- eg. knife->knives |
||
− | end |
||
− | if suffix1 == 'f' and suffix2 ~= 'ff' then |
||
− | return _arg1:sub(1, -2) .. 'ves' -- eg. wolf->wolves, leaf->leaves, but buff->buffs |
||
− | else |
||
− | return _arg1 .. 's' |
||
− | end |
||
− | end |
||
− | |||
− | if _arg2 == 'es' then |
||
− | return _arg1 .. 'es' |
||
− | end |
||
− | |||
− | if _arg2 == 'ies' then |
||
− | return _arg1:sub(1, -2) .. 'ies' |
||
− | end |
||
− | |||
− | if _arg2 == 'ves' then |
||
− | if _arg1:sub(-2) == 'fe' then |
||
− | return _arg1:sub(1, -3) .. 'ves' --replace last 2 letters, e.g. knife->knives |
||
− | end |
||
− | if _arg1:sub(-1) == 'f' or _arg1:sub(-2) ~= 'ff' then |
||
− | return _arg1:sub(1, -2) .. 'ves' --replace last letter, e.g. wolf-wolves, leaf->leaves, but buff->buffs |
||
− | end |
||
− | end |
||
− | end, |
||
− | |||
− | -- example: for Chinese (zh) |
||
− | -- ['zh'] = function(_arg1, _arg2) |
||
− | -- -- there is no plural form in chinese. |
||
− | -- if _arg2 == 's' or _arg2 == 'es' or _arg2 == 'ies' or _arg2 == 'ves' then |
||
− | -- return _arg1 |
||
− | -- end |
||
− | -- return nil |
||
− | -- end, |
||
− | |||
− | -- default function for all laguages not defined. |
||
− | ['others'] = function(_arg1, _arg2) |
||
− | -- no plural form process. |
||
− | if _arg2 == 's' or _arg2 == 'es' or _arg2 == 'ies' or _arg2 == 'ves' then |
||
− | return _arg1 |
||
− | end |
||
− | return nil |
||
− | end, |
||
− | } |
||
− | |||
------- The following is not related to l10n. -------------- |
------- The following is not related to l10n. -------------- |
||
Line 75: | Line 7: | ||
local trim = mw.text.trim |
local trim = mw.text.trim |
||
local cargo = mw.ext.cargo |
local cargo = mw.ext.cargo |
||
− | local |
+ | local eicons = require('Module:Exclusive').simpleEicons |
− | local eicons = module_exclusive.simpleEicons |
||
local currentFrame |
local currentFrame |
||
Line 98: | Line 29: | ||
end |
end |
||
return value |
return value |
||
− | end |
||
− | |||
− | local function getText(_arg1, _arg2) |
||
− | if not _arg2 then |
||
− | return currentFrame:expandTemplate{ title = 'tr', args = {_arg1, lang=lang} } -- auto translate |
||
− | end |
||
− | local plural_function = plural[lang] or plural['others'] or function() end |
||
− | return currentFrame:expandTemplate{ title = 'tr', args = {plural_function(_arg1, _arg2) or _arg2, lang=lang} } -- auto translate |
||
end |
end |
||
Line 308: | Line 231: | ||
local _link, _eicons_link = getArg('link'), nil |
local _link, _eicons_link = getArg('link'), nil |
||
if _link then -- override _nolink = y |
if _link then -- override _nolink = y |
||
− | _eicons_link = _link |
+ | _eicons_link = _link -- _eicontr does not affect _link |
else |
else |
||
if _nolink then |
if _nolink then |
||
_link = '' |
_link = '' |
||
− | if |
+ | if getArg('eicontr') then |
− | _eicons_link = frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} } |
+ | _eicons_link = getArg('trname') or frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} } |
else |
else |
||
_eicons_link = _arg1 |
_eicons_link = _arg1 |
||
Line 319: | Line 242: | ||
else |
else |
||
-- no link=<link> input, use _arg1 with auto link translation. |
-- no link=<link> input, use _arg1 with auto link translation. |
||
− | _link = frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} } |
+ | _link = getArg('trname') or frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} } |
− | if |
+ | if getArg('eicontr') then |
_eicons_link = _link -- reuse |
_eicons_link = _link -- reuse |
||
else |
else |
||
Line 329: | Line 252: | ||
-- now _link == '' means nolink. |
-- now _link == '' means nolink. |
||
− | local text = |
+ | local text = getArg(2) or '' |
local class = 'item-link' |
local class = 'item-link' |
Revision as of 17:49, 17 May 2019
Documentation The documentation below is transcluded from Module:Item/doc. (edit | history)
This module is intended to provide functionality to the {{item}} template.
------- l10n info --------------
local l10n_info = mw.loadData('Module:Item/l10n')
------- The following is not related to l10n. --------------
local trim = mw.text.trim
local cargo = mw.ext.cargo
local eicons = require('Module:Exclusive').simpleEicons
local currentFrame
local args_table
local lang
local l10n_table
local image_for_cargo
local l10n = function(key)
return l10n_table[key] or l10n_info['en'][key]
end
local getArg = function(key)
local value = args_table[key]
if not value then
return nil
end
value = trim(value)
if value == '' then
return nil
end
return value
end
-- credit: http://richard.warburton.it
-- this version is with trim.
local function explode(div,str)
if (div=='') then return false end
local pos,arr = 0,{}
-- for each divider found
for st,sp in function() return string.find(str,div,pos,true) end do
table.insert(arr,trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider
pos = sp + 1 -- Jump past current divider
end
table.insert(arr, trim(string.sub(str,pos))) -- Attach chars right of last divider
return arr
end
local function parseSize(size)
if not size then return end
local basescale, width, height
size, basescale = unpack(explode('*', size))
if size ~= '' then
width, height = unpack(explode('x', string.gsub(size, 'px', '')))
width, height = tonumber(width), tonumber(height)
if width == 0 then width = nil end
if height == 0 then height = nil end
end
return basescale, width, height
end
local function getInfoFromCargo(image)
-- try to get from cargo cache
local result = mw.ext.cargo.query('Imageinfo', 'width, height, cached', {
where = 'image='.. "'"..image:gsub("'", "\\'"):gsub("'", "\\'").."'",
orderBy = "cached DESC",
limit = 1,
})
for _, row in ipairs(result) do
return tonumber(row['width']), tonumber(row['height']), row['cached']
end
end
local function storeInfoToCargo(image)
local width, height
width = tonumber(currentFrame:callParserFunction( '#imgw', image))
if width and width ~= 0 then -- save one expensive call when the file is not a valid image.
height = tonumber(currentFrame:callParserFunction( '#imgh', image))
if height and height ~= 0 then
currentFrame:callParserFunction('#cargo_store:_table=Imageinfo',{
image = image,
width = width,
height = height,
cached = os.time(),
})
end
end
return width, height
end
local function getSizeInfo(image)
local width, height, cached = getInfoFromCargo(image)
-- cache missed, init cache
if not cached then
width, height = storeInfoToCargo(image)
end
if width == 0 then width = nil end
if height == 0 then height = nil end
return width, height
end
local function getImageSize(image, width, height, scale, maxwidth, maxheight)
-- get size info from image file itself (may be expensive)
local w, h = getSizeInfo(image) -- store data to cache
if not width and not height and (scale or maxwidth or maxheight) then
width, height = w, h
end
-- apply scale to width/height if needed
if scale then
if width then width = width * scale end
if height then height = height * scale end
end
-- apply maxwidth/maxheight.
if maxwidth then
if width then
if width > maxwidth then width = maxwidth end
else
if height then width = maxwidth end
end
end
if maxheight then
if height then
if height > maxheight then height = maxheight end
else
if width then height = maxheight end
end
end
-- rounding
if width then width = math.ceil(width) end
if height then height = math.ceil(height) end
return width, height
end
local function parseMaxSize(maxsize)
if not maxsize then return end
local maxwidth, maxheight = unpack(explode('x', string.gsub(maxsize, 'px', '')))
maxwidth, maxheight = tonumber(maxwidth), tonumber(maxheight)
if maxwidth == 0 then maxwidth = nil end
if maxheight == 0 then maxheight = nil end
return maxwidth, maxheight
end
local function imagecode(image, link, text, size, scale, maxsize)
local image_output = '[[File:' .. image .. '|link='.. link .. '|' .. text
if size or scale or maxsize then
local basescale, width, height = parseSize(size) -- width,height: number or nil
scale = (tonumber(scale) or 1) * (tonumber(basescale) or 1)
if scale == 0 or scale == 1 then
scale = nil
end
local maxwidth, maxheight = parseMaxSize(maxsize)
width, height = getImageSize(image, width, height, scale, maxwidth, maxheight) -- can be 0
if width or height then
return image_output .. '|' .. (width or '') .. 'x' .. (height or '') .. 'px]]'
else
return image_output .. ']]'
end
else
return image_output .. ']]'
end
end
local function images(image, link, text, size, scale, maxsize)
if not image:find('/') then
image_for_cargo = image
return imagecode(image, link, text, size, scale, maxsize)
end
image = explode('/', image)
local result = ''
if size and size:find('/') then
size = explode('/', size)
for i, v in ipairs(image) do
result = result .. imagecode(v, link, text, size[i], scale, maxsize)
end
else
for i, v in ipairs(image) do
result = result .. imagecode(v, link, text, size, scale, maxsize)
end
end
return result
end
local getIdText = function(_type)
_type = _type:lower()
local id_text, needcargo
if _type == 'item' then -- a shortcut for faster
id_text = l10n('id_text_item')
needcargo = true
elseif _type == 'tile' then
id_text = l10n('id_text_tile')
elseif _type == 'wall' then
id_text = l10n('id_text_wall')
elseif _type == 'npc' then
id_text = l10n('id_text_npc')
elseif _type == 'mount' then
id_text = l10n('id_text_mount')
elseif _type == 'buff' or _type == 'debuff' then
id_text = l10n('id_text_buff')
elseif _type == 'projectile' then
id_text = l10n('id_text_projectile')
elseif _type == 'armor' then
id_text = l10n('id_text_armor')
else
id_text = l10n('id_text_item')
needcargo = true
end
return id_text, needcargo
end
-----------------------------------------------------------------
-- main return object
return {
go = function(frame, args)
-- init cache
currentFrame = frame
args_table = args or frame.args
lang = getArg('lang') or 'en'
l10n_table = l10n_info[lang] or l10n_info['en']
local _arg1 = getArg(1) or ''
local _nolink = getArg('nolink')
-- link target and eicons target
local _link, _eicons_link = getArg('link'), nil
if _link then -- override _nolink = y
_eicons_link = _link -- _eicontr does not affect _link
else
if _nolink then
_link = ''
if getArg('eicontr') then
_eicons_link = getArg('trname') or frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} }
else
_eicons_link = _arg1
end
else
-- no link=<link> input, use _arg1 with auto link translation.
_link = getArg('trname') or frame:expandTemplate{ title = 'tr', args = {_arg1, link = 'y', lang=lang} }
if getArg('eicontr') then
_eicons_link = _link -- reuse
else
_eicons_link = _arg1
end
end
end
-- now _link == '' means nolink.
local text = getArg(2) or ''
local class = 'item-link'
local output_image, output_text, output_table = true, true, false
local _mode = getArg('mode')
if _mode then
if _mode == 'image' or _mode == 'imageonly' or _mode =='onlyimage' then
output_text = false
elseif _mode == 'text' or _mode == 'noimage' then
output_image = false
elseif _mode == 'table' or _mode == '2-cell' then
output_table = true
end
end
local image_output, text_output
if output_image then
image_output = images(getArg('image') or (_arg1 .. '.' .. (getArg('ext') or 'png')), _link, text, getArg('size'), getArg('scale'), getArg('maxsize'))
else
image_output = ''
end
if output_text then
local _note, _note2, _id = getArg('note'), getArg('note2'), getArg('id')
local _wrap
if _id or _note2 then
_wrap = false
else
_wrap = getArg('wrap')
end
if _link ~= '' then
if text == _link then
text = '[['..text..']]'
else
text = '[['.._link..'|'..text..']]'
end
end
local _icon, icon = getArg('icons'), nil
if _icon == 'n' or _icon == 'no' or _icon == 'off' then
icon = ''
else
icon = eicons(_eicons_link, lang, (_id or _note2 or _wrap or getArg('small')) and 'y')
end
local content = '<span>' .. text .. '</span>' -- item name link text first.
-- '-w' class means 'wrapmode', optimized for multiple lines of text. But it should be disabled for single line text.
if _wrap then
-- eicons in the same line
if icon ~= '' then
class = class .. ' -w'
content = content .. icon
end
-- note in next line
if _note then
class = class .. ' -w'
content = content .. '<span class="note">' .. _note .. '</span>'
end
else
-- note first
if _note then
content = content .. '<span class="note">' .. _note .. '</span>'
end
if icon ~= '' then
content = content .. icon
end
if _note2 then
class = class .. ' -w'
content = content .. '<div class="note">' .. _note2 .. '</div>'
end
if _id then
class = class .. ' -w'
local id_text, needcargo = getIdText(getArg('type') or 'item')
if needcargo and image_for_cargo then
frame:expandTemplate{ title = 'Item/cargo', args = {name=_arg1, image=image_for_cargo, id=_id} }
end
content = content .. '<div class="id">' .. id_text .. _id .. '</div>'
end
end
text_output = '<span>' .. content .. '</span>'
else
text_output = ''
end
local _class, _css = getArg('class'), getArg('css')
if _class then
class = class .. ' ' .. _class
end
local attr = {class = class}
if _css then
attr.style = _css
end
if getArg('anchor') then
text_output = text_output .. '<div class="anchor" id="' .. frame:callParserFunction('anchorencode', _arg1) .. '"></div>'
end
if output_table then
attr.class = class .. ' block aligncenter'
local result = mw.text.tag('span', attr, image_output) .. '||'
attr.class = class .. ' block alignleft'
return result .. mw.text.tag('span', attr, text_output)
else
return mw.text.tag('span', attr, image_output .. text_output)
end
end,
}