Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be bug-free and ready for use wherever appropriate. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
--[[
__ __ _ _ _ _ _ _ _ _ ___ _ _
| \/ | ___ __| |_ _| | ___ _| \ | | __ _| |_(_) ___ _ __ / \ _ __ __| |/ _ \ ___ ___ _ _ _ __ __ _| |_(_) ___ _ __
| |\/| |/ _ \ / _` | | | | |/ _ (_) \| |/ _` | __| |/ _ \| '_ \ / _ \ | '_ \ / _` | | | |/ __/ __| | | | '_ \ / _` | __| |/ _ \| '_ \
| | | | (_) | (_| | |_| | | __/_| |\ | (_| | |_| | (_) | | | |/ ___ \| | | | (_| | |_| | (_| (__| |_| | |_) | (_| | |_| | (_) | | | |
|_| |_|\___/ \__,_|\__,_|_|\___(_)_| \_|\__,_|\__|_|\___/|_| |_/_/ \_\_| |_|\__,_|\___/ \___\___|\__,_| .__/ \__,_|\__|_|\___/|_| |_|
This module translates a person’s nationality and profession into user’s preferred language.
The template takes care for the right word order: {{NationAndOccupation|m|FR|painter|poet}}
gives “French painter and poet”, if the user’s preferred language is set to English, but
“pintor y poeta francés”, if the language is set to Spanish. This is especially useful with
the “Description” field of {{Creator}} templates.
]]
-- =======================================
-- === Dependencies ======================
-- =======================================
local core = require("Module:core")
local conj = require('Module:Linguistic').conj
local q2iso = require("Module:NationAndOccupation/nationalityLUT")
local n2iso = require("Module:NationAndOccupation/CountryAdjective2iso")
-- ==================================================
-- === Internal functions ===========================
-- ==================================================
-------------------------------------------------------------------------------
local function getBareLabel(id, userLang)
-- code equivalent to require("Module:Wikidata label")._getLabel with Wikidata=- option
local label, link
-- build language fallback list
local langList = mw.language.getFallbacksFor(userLang)
table.insert(langList, 1, userLang)
for _, lang in ipairs(langList) do -- loop over language fallback list looking for label in the specific language
label = mw.wikibase.getLabelByLang(id, lang)
if label then break end -- label found and we are done
end
return label or id
end
------------------------------------------------------------------------------
-- straight union of two arrays (tables)
local function union ( a, b )
local result = {}
for _,v in pairs ( a or {} ) do
table.insert( result, v )
end
for _,v in pairs ( b or {} ) do
table.insert( result, v )
end
return result
end
------------------------------------------------------------------------------
-- get female forms of occupation using " female form of label (P2521) " property
local function getFemaleLabel(item, lang)
local label = {}
for _, statement in pairs( mw.wikibase.getBestStatements( item, 'P2521' )) do
local v = statement.mainsnak.datavalue.value
if v then
label[v.language] = v.text
end
end
if label then
label = core.langSwitch(label,lang)
end
if not label then
label = getBareLabel(item, lang)
end
return label
end
--[[
Implementation of Template:NationAndOccupation/default
INPUTS:
* nationality - array of string in the form compatible with Template:Nationality
* occupation - array of already translated strings
* gender - single gender string "male" or "female"
* lang - users language
]]
local function assembleNaO(nationality, occupation, gender, lang)
local styleLUT = { -- language dependent order
-- Occupation then nationality order
ca=10 , es=10, eu=10, fa=10, he=10, it=10, pt=10, ro=10, vi=10,
-- Occupation then nationality order with first nationality in a special form
fr=11,
-- Nationality then Occupation order
cs=20 , da=20, el=20, en=20, eo=20, et=20, hu=20, mk=20, ml=20, nl=20,
-- Nationality then Occupation order, no space
zh=21,
-- Nationality then Occupation order with 1st nationality in a special form and 2nd nationality upper case
nds=22, de=22 ,
-- Nationality then Occupation order with 1st nationality in a special form and 2nd nationality lower case
pl=23, ru=23, sl=23, bg=23}
-- Use LangSwitch to choose the style based on the language. That way language fallback chain is used
local style = core.langSwitch(styleLUT, lang)
-- create nationality string
gender = gender or 'male'
local frame = mw.getCurrentFrame()
local nStr=''
if nationality and #nationality==1 then --Single nationality case
nStr = frame:expandTemplate{ title='Nationality', args={nationality[1], gender, lang=lang} }
elseif nationality and #nationality>1 then --Double nationality case
local N2 = frame:expandTemplate{ title='Nationality', args={nationality[2], gender, lang=lang} }
if style==11 or style==22 or style==23 then -- nationality in a special form
gender = 's'
end
local N1 = frame:expandTemplate{ title='Nationality', args={nationality[1], gender, lang=lang} }
if style==23 then
N2 = mw.ustring.lower(N2)
end
nStr = N1 .. '-' .. N2
end
-- Create final string
if occupation then
local oStr = conj(occupation, lang, 'and')
if style<20 then -- Type 1: Occupation then nationality order
return oStr .. ' ' .. nStr
elseif style==21 then -- Type 1: Nationality then Occupation order, no space
return nStr .. oStr
else -- Type 2: Nationality then Occupation order
return nStr .. ' ' .. oStr
end
else
return nStr
end
end
--[[
Implementation of Template:NationAndOccupation
INPUTS:
* entity - wikidata entity
* lang - users language
OUTPUTS:
* data - data structure with data extracted from Wikidata, including fields:
* nationality - array of string in the form compatible with Template:Nationality
* occupation - array of already translated occupation strings
* occupationEN - array of occupation strings in english
* gender - single gender string "male" or "female"
]]
local function harvest_wikidata(entity, lang)
local occupation, occupationEN, nationality, gender, data = {}, {}, {}, {}, {}
-- if wikidata q-code is provided than look up few properties
if entity then
-- harvest properties from wikidata
local property = {P21='gender', P27='country', P106='occupation', P172='ethnicity'}
for prop, field in pairs( property ) do
if entity.claims and entity.claims[prop] then -- if we have wikidata item and item has the property
-- capture multiple "best" Wikidata value
data[field] = core.parseStatements(entity:getBestStatements( prop ), nil)
end
end
end
-- Look up gender
if data.gender then
local LUT = { Q6581097='male', Q2449503='male', Q6581072='female', Q1052281='female' }
gender = LUT[data.gender[1]]
end
if gender~='male' and gender~='female' then
gender = 'male'
end
-- Look up occupation
local occ
for i, oItem in ipairs(data.occupation or {}) do
if i>6 then
break -- only 6 occupations are allowed
end
local occEN = mw.wikibase.getLabelByLang(oItem, 'en')
if gender == 'female' then -- get localized (translated) occupation labels in female form
occ = getFemaleLabel(oItem, lang)
elseif lang=='en' then -- get English occupation labels in male form
occ = occEN
else -- get localized (translated) occupation labels in male form
occ = getBareLabel(oItem, lang)
end
table.insert(occupation , occ)
table.insert(occupationEN, occEN)
end
-- Look up nationality
if data.country or data.ethnicity then -- from wikidata
-- process P27/country and P172/ethnicity
local nTable = {} -- table of unique nationality iso codes stored as keys
for _, v in ipairs( union(data.country, data.ethnicity) ) do
for iso in mw.text.gsplit( q2iso[v] or '', '/', true ) do
nTable[ iso ] = 1
end
end
for nat, _ in pairs(nTable) do
table.insert(nationality, nat)
end
end
data = {nationality=nationality, occupation=occupation, gender=gender, occupationEN=occupationEN}
return data
end
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================
--[[
Implementation of Template:NationAndOccupation
INPUTS:
* args.nationality - '/' separated string with substrings in the form compatible
with Template:Nationality
* args.occupation - '/' separated string with substrings with english names of
occupations compatible with Template:Occupations
* args.gender - single gender string "male" or "female"
* args.wikidata - wikidata q-code
* args.lang - users language
OUTPUTS:
* OutStr - string with transpaced phrase like "english writer"
* args - data structure with processed inputs
* data - data structure with data extracted from Wikidata
]]
function p._NationAndOccupation(args0)
local occupation, nationality, entity, occupationEN
-- if wikidata q-code is provided than look up few properties
local q = args0.wikidata
if q and type(q)=='string' and string.sub(q,1,1)=="Q" then --
entity = mw.wikibase.getEntity(q)
elseif q then
entity = q
end
local data = harvest_wikidata(entity, args0.lang)
local gender = args0.gender or data.gender
-- Look up occupation
if args0.occupation then -- from input arguments
local frame = mw.getCurrentFrame()
local occArray = mw.text.split(args0.occupation, '/')
occupation = {}
for i = 1,6 do
if occArray[i] and occArray[i]~='' then
local args={occArray[i], gender, lang=args0.lang}
table.insert(occupation, frame:expandTemplate{ title='Occupation', args=args })
end
end
if #occupation==0 then
occupation = nil
end
end
-- Look up nationality
if args0.nationality then -- from input arguments
nationality = mw.text.split(args0.nationality, '/')
for i = 1,2 do -- if nationality is a word than see if we can find iso code
local N = string.lower(nationality[i] or '')
if #N>2 and n2iso[N] then
nationality[i] = n2iso[N]
end
end
if #nationality==0 then
nationality = nil
end
end
local outStr = assembleNaO(nationality or data.nationality, occupation or data.occupation, gender, args0.lang)
local args = {nationality=nationality, occupation=occupation, gender=args0.gender, occupationEN=occupationEN}
--outStr = outStr .. '\n' .. mw.text.jsonEncode(data) .. '\n' .. mw.text.jsonEncode(args)
return outStr, args, data
end
-- ===========================================================================
-- === Version of the functions to be called from template namespace
-- ===========================================================================
--[[
NationAndOccupation
This function is the core part of the NationAndOccupation template.
Usage:
{{#invoke:}}
Parameters:
*nationality - '/' separated string with substrings in the form compatible
with Template:Nationality
* occupation - '/' separated string with substrings with english names of
occupations compatible with Template:Occupations
* gender - single gender string "male" or "female"
* wikidata - wikidata q-code
* lang - users language
Error Handling:
]]
function p.NationAndOccupation(frame)
local args0 = core.getArgs(frame)
local outStr, args, data = p._NationAndOccupation(args0)
return outStr
end
return p