Module:Convert: Difference between revisions

nswiki>Union of Christian States
(Created page with "-- Convert a value from one unit of measurement to another. -- Example: {{convert|123|lb|kg}} --> 123 pounds (56 kg) -- See en:Template:Convert/Transwiki guide if copying...")
(update from sandbox per Template talk:Convert#Module version 4)
Line 15:
-- Conversion data and message text are defined in separate modules.
local config, maxsigfig
local numdot -- must be '.' or ',' or a character which works in a regex as used here
local numsep, numsep_remove, numsep_remove2
local default_exceptions, link_exceptions, all_units
local text_code
Line 23:
local to_en_table -- to translate an input string of digits in local language to en
-- Use translation_table in convert/text to change the following.
local en_default -- true uses lang=en unless convert has lang=local or local digits
local group_method = 3 -- code for how many digits are in a group
local per_word = 'per' -- for units like "liters per kilometer"
local plural_suffix = 's' -- only other useful value is probably '' to disable plural unit names
local omitsep -- true to omit separator before local symbol/name
 
-- All units should be defined in the data module. However, to cater for quick changes
Line 53 ⟶ 55:
-- and no separators (they have to be removed here to handle cases like
-- numsep = '.' and numdot = ',' with input "1.234.567,8").
if numsep_remove ~= ''to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
return text
end
 
local function decimal_mark(text)
-- Return ',' if text probably is using comma for decimal mark, or has no decimal mark.
-- Return '.' if text probably is using dot for decimal mark.
-- Otherwise return nothing (decimal mark not known).
if not text:find('[.,]') then return ',' end
text = text:gsub('^%-', ''):gsub('%+%d+/%d+$', ''):gsub('[Ee]%-?%d+$', '')
local decimal =
text:match('^0?([.,])%d+$') or
text:match('%d([.,])%d?%d?$') or
text:match('%d([.,])%d%d%d%d+$')
if decimal then return decimal end
if text:match('%.%d+%.') then return ',' end
if text:match('%,%d+,') then return '.' end
end
 
local add_warning, with_separator -- forward declarations
local function to_en_with_check(text, parms)
-- Version of to_en() for a wiki using numdot = ',' and numsep = '.' to check
-- text (an input number as a string) which might have been copied from enwiki.
-- For example, in '1.234' the '.' could be a decimal mark or a group separator.
-- From viwiki.
if to_en_table then
text = ustring.gsub(text, '%d', to_en_table)
end
if decimal_mark(text) == '.' then
local original = text
text = text:gsub(',', '') -- for example, interpret "1,234.5" as an enwiki value
if parms then
add_warning(parms, 0, 'cvt_enwiki_num', original, with_separator({}, text))
end
else
if numsep_remove then
text = text:gsub(numsep_remove, '')
end
if numsep_remove2 then
text = text:gsub(numsep_remove2, '')
end
if numdot ~= '.' then
text = text:gsub(numdot, '.')
end
end
return text
end
 
local function want_separator(id)
-- Return true if id (a unit symbole or name) should be proceeded by a separator.
-- For zhwiki, there should be no separator if id uses local characters.
-- The following kludge should be a sufficient test.
if id:sub(1, 2) == '-{' then -- for "-{...}-" content language variant
return false
end
if id:byte() > 127 then
local first = usub(id, 1, 1)
if first ~= 'Å' and first ~= '°' and first ~= 'µ' then
return false
end
end
return true
end
 
Line 97 ⟶ 162:
numdot = translation.numdot
numsep = translation.numsep
if numdot == ',' and numsep == '.' then
if text_code.all_messages.cvt_enwiki_num then
to_en = to_en_with_check
end
end
if translation.group then
group_method = translation.group
Line 123 ⟶ 193:
to_en_table = translation.to_en
end
if translation.lang == 'en default' then
en_default = true -- for hiwiki
end
omitsep = translation.omitsep -- for zhwiki
end
numdot = config.numdot or numdot or '.' -- decimal mark before fractional digits
Line 128 ⟶ 202:
-- numsep should be ',' or '.' or '' or ' ' or a Unicode character.
-- numsep_remove must work in a regex to identify separators to be removed.
numsep_removeif = (numsep =~= '.') and '%.' or numsepthen
numsep_remove = (numsep == '.') and '%.' or numsep
end
if numsep ~= ',' and numdot ~= ',' then
numsep_remove2 = ',' -- so numbers copied from enwiki will work
end
end
 
Line 246 ⟶ 325:
end
 
local function add_warning(parms, level, mcodekey, texttext1, text2) -- for forward declaration above
-- If enabled, add a warning that will be displayed after the convert result.
-- To reduce output noise, only the first warning is displayed.
Line 252 ⟶ 331:
if level <= (tonumber(config.warnings) or 1) then
if parms.warnings == nil then
parms.warnings = message({ mcodekey, texttext1, text2 })
end
end
Line 913 ⟶ 992:
end
 
local function with_separator(parms, text) -- for forward declaration above
-- Input text is a number in en digits and optional '.' decimal mark.
-- Return an equivalent of text, formatted for display:
Line 1,259 ⟶ 1,338:
-- '+' (if the input text used '+'), or is '' (if no sign in input).
text = strip(text or '')
local clean = to_en(text, parms)
if clean == '' then
return false, { another and 'cvt_no_num2' or 'cvt_no_num' }
Line 1,518 ⟶ 1,597:
while subunit.subdivs do -- subdivs is nil or a table of allowed subdivisions
local subcode = strip(parms[iparm+1])
local subdiv = subunit.subdivs[subcode] or subunit.subdivs[(all_units[subcode] or {}).target]
if not subdiv then
break
Line 1,689 ⟶ 1,768:
parms.table_joins = { align .. '|', '\n|' .. align .. '|' }
end
local disp_joins = text_code.disp_joins
if parms.opt_lang_en then
local default_joins = disp_joins['b']
parms.join_between = default_joins[3] or '; '
local disp = parms.disp
if disp == nil then -- special case for the most common setting
parms.joins = default_joins
elseif disp == 'x' then
-- Later, parms.joins is set from the input parameters.
else
-- Old template does this.
local abbr = parms.abbr
if disp == 'slash' then
if parms.abbr_org == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
disp = 'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
parms.joins = disp_joins[disp] or default_joins
parms.join_between = parms.joins[3] or parms.join_between
end
if (en_default and not parms.opt_lang_local and (parms[1] or ''):find('%d')) or parms.opt_lang_en then
from_en_table = nil
end
if en_default and from_en_table then
-- For hiwiki: localized symbol/name is defined with the US symbol/name field,
-- and is used if output uses localized numbers.
parms.opt_sp_us = true
end
return true
Line 1,773 ⟶ 1,886:
-- and that on average it speeds up converts by 8%.
if parms.input_precision or parms.opt_spell_in then return end
local clean = to_en(strip(parms[1] or ''), parms)
if #clean > 10 or not clean:match('^[0-9.]+$') then return end
local value = tonumber(clean)
Line 2,409 ⟶ 2,522:
 
local function variable_name(clean, unit_table)
-- For slwiki (Slovenian Wikipedia), a unit name depends on the value.
-- Parameter clean is the unsigned rounded value in en digits, as a string.
-- Value Source Example for "m"
Line 2,489 ⟶ 2,602:
if abbr_on then
result = '/'
elseif omitsep then
result = per_word
elseif unit1 then
result = ' ' .. per_word .. ' '
Line 2,499 ⟶ 2,614:
else
result = (unit1 and variable_name(clean, unit1) or '') .. result .. variable_name('1', unit2)
end
if omitsep and not want_separator(result) then
unit_table.sep = ''
end
return make_link(unit_table.link, result, unit_table)
Line 2,504 ⟶ 2,622:
if unit1 then
result = linked_id(unit1, key_id, want_link, clean) .. result
if unit1.sep then
unit_table.sep = unit1.sep
end
elseif omitsep then
unit_table.sep = ''
end
return result .. linked_id(unit2, key_id2, want_link, '1')
Line 2,510 ⟶ 2,633:
-- A multiplier (like "100" in "100km") forces the unit to be plural.
multiplier = from_en(multiplier)
if abbr_onnot omitsep then
multiplier = multiplier .. (abbr_on and '&nbsp;' or ' ')
elseend
if not abbr_on then
multiplier = multiplier .. ' '
if key_id == 'name1' then
key_id = 'name2'
Line 2,524 ⟶ 2,647:
end
local id = unit_table.fixed_name or ((varname and not abbr_on) and variable_name(clean, unit_table) or unit_table[key_id])
if omitsep and not want_separator(id) then
unit_table.sep = ''
end
if want_link then
local link = link_exceptions[unit_table.linkey or unit_table.symbol] or unit_table.link
Line 2,752 ⟶ 2,878:
end
return preunit .. id1
end
local disp_joins = text_code.disp_joins
local abbr = parms.abbr
local disp = parms.disp
if disp == nil then -- special case for the most common setting
parms.joins = disp_joins['b']
elseif disp ~= 'x' then
-- Old template does this.
if disp == 'slash' then
if parms.abbr_org == nil then
disp = 'slash-nbsp'
elseif abbr == 'in' or abbr == 'out' then
disp = 'slash-sp'
else
disp = 'slash-nosp'
end
elseif disp == 'sqbr' then
if abbr == 'on' then
disp = 'sqbr-nbsp'
else
disp = 'sqbr-sp'
end
end
parms.joins = disp_joins[disp] or disp_joins['b']
end
if parms.opt_also_symbol and not composite then
Line 2,783 ⟶ 2,885:
end
end
if in_current.builtin == 'mach' and first_unit.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. '&nbsp;'
local range = parms.range
Line 2,803 ⟶ 2,905:
sep1 = '-'
sep2 = '-'
end
if omitsep and sep == '' then
-- Testing the id of the most significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
local parts = { first_unit.valinfo[1].show .. sep1 .. id1 }
Line 2,813 ⟶ 2,920:
end
local result, mos
local abbr = parms.abbr
local range = parms.range
if range then
Line 2,887 ⟶ 2,995:
return preunit .. id1
end
if out_current.builtin == 'mach' and out_current.sep ~= '' then -- '' means omitsep with non-enwiki name
local prefix = id1 .. '&nbsp;'
local range = parms.range
Line 3,055 ⟶ 3,163:
else
id = out_current['symbol']
end
if omitsep and i == 1 and not want_separator(id) then
-- Testing the id of the least significant unit should be sufficient.
sep1 = ''
sep2 = ''
end
if want_link then
Line 3,188 ⟶ 3,301:
table.insert(outputs, item)
end
local sep = parms.table_joins and parms.table_joins[2] or '; 'parms.join_between
parts[part] = parms.opt_input_unit_only and '' or table.concat(outputs, sep)
end
Anonymous user