モジュール:NationAndOccupation

提供:脳科学辞典
2020年1月29日 (水) 13:27時点におけるNijcadmin (トーク | 投稿記録)による版 (1版 をインポートしました)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

このモジュールについての説明文ページを モジュール:NationAndOccupation/doc に作成できます

--[[  
  __  __           _       _        _   _       _   _                _              _  ___                             _   _             
 |  \/  | ___   __| |_   _| | ___ _| \ | | __ _| |_(_) ___  _ __    / \   _ __   __| |/ _ \  ___ ___ _   _ _ __   __ _| |_(_) ___  _ __  
 | |\/| |/ _ \ / _` | | | | |/ _ (_)  \| |/ _` | __| |/ _ \| '_ \  / _ \ | '_ \ / _` | | | |/ __/ __| | | | '_ \ / _` | __| |/ _ \| '_ \ 
 | |  | | (_) | (_| | |_| | |  __/_| |\  | (_| | |_| | (_) | | | |/ ___ \| | | | (_| | |_| | (_| (__| |_| | |_) | (_| | |_| | (_) | | | |
 |_|  |_|\___/ \__,_|\__,_|_|\___(_)_| \_|\__,_|\__|_|\___/|_| |_/_/   \_\_| |_|\__,_|\___/ \___\___|\__,_| .__/ \__,_|\__|_|\___/|_| |_|

 
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.

]]

local p = {}

-- =======================================
-- === Dependencies ======================
-- =======================================
local conj     = require('Module:Linguistic').conj
local Wikidata = require("Module:Wikidata label")    -- used for creation of name based on wikidata
local q2iso    = require("Module:NationAndOccupation/nationalityLUT")
local n2iso    = require("Module:NationAndOccupation/CountryAdjective2iso")

local function langSwitch(list,lang)
	local langList = mw.language.getFallbacksFor(lang)
	table.insert(langList,1,lang)
	for i,language in ipairs(langList) do
		if list[language] then
			return list[language]
		end
	end
	return nil
end


local function getFemaleLabel(q, lang)
	local label = {}
	local entity = mw.wikibase.getEntity(q)
	if entity.claims and entity.claims.P2521  then -- if we have wikidata item and item has the property
		for _, statement in pairs( entity:getBestStatements( 'P2521' )) do
			local v = statement.mainsnak.datavalue
			if v then 
				v = v.value
				label[v.language] = v.text
			end
		end
	end
	if label then
		return langSwitch(label,lang)
	else
		return nil
	end
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)

  -- Use LangSwitch to choose the style based on the language. That way [[template:Fallback]] is used
	local style = langSwitch({ 
		-- 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}, 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 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
	local 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
			local n = 0;
			if entity.claims and entity.claims[prop] then -- if we have wikidata item and item has the property
				-- capture multiple "best" Wikidata value
				for _, statement in pairs( entity:getBestStatements( prop )) do
					if (statement.mainsnak.snaktype == "value") then 
						local v = statement.mainsnak.datavalue.value.id
						n = n+1
						if n==1 then data[field]={} end
						data[field][n] = v
					end
				end
			end
		end
	end
	
	-- Look up gender
	if data.gender then	
		if (data.gender[1]=='Q6581097' or data.gender[1]=='Q2449503') then
			gender = 'male'
		end
		if (data.gender[1]=='Q6581072' or data.gender[1]=='Q1052281') then
			gender = 'female'
		end
	end
	
	-- Look up occupation
	if data.occupation then -- from wikidata
		local occItem = {}
		occupationEN = {}
		for i = 1,6 do 
			if data.occupation[i] and data.occupation[i]~='' then 
				table.insert(occItem, data.occupation[i])
				table.insert(occupationEN, Wikidata._getLabel(data.occupation[i], 'en', "-"))
			end
		end
		
		occupation = {}
		if gender == 'female' then -- get localized (translated) occupation labels in female form
			for i,occ in ipairs(occItem) do 
				table.insert(occupation, getFemaleLabel(occ, lang) or Wikidata._getLabel(occ, lang, "-"))
			end
		elseif lang=='en' then     -- get English occupation labels in male form
			occupation = occupationEN
		else                       -- get localized (translated) occupation labels in male form
			for i,occ in ipairs(occItem) do 
				table.insert(occupation, Wikidata._getLabel(occ, lang, "-"))
			end
		end
	end
	
	-- Look up nationality
	if data.country or data.ethnicity then -- from wikidata
		-- process P27/country and P172/ethnicity
		local nTable = {}
		for i, v in ipairs( data.country or {} ) do
			table.insert(nTable, q2iso[v])
		end
		for i, v in ipairs( data.ethnicity or {} ) do
			table.insert(nTable, q2iso[v])
		end
		-- find unique values
		table.sort(nTable)
		nationality = {}
		if nTable[1] then
			table.insert(nationality, nTable[1])
		end
		for i = 2, #nTable do
			if (nTable[i-1]~=nTable[i]) and nTable[i] then
				table.insert(nationality, nTable[i])
			end
		end
	end
	return {nationality=nationality, occupation=occupation, gender=gender, occupationEN=occupationEN}
end

--[[
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()
		occupationEN = mw.text.split(args0.occupation  or '', '/')
		occupation = {}
		for i = 1,6 do 
			if occupationEN[i] and occupationEN[i]~='' then 
				local args={occupationEN[i], gender, lang=args0.lang}
				table.insert(occupation, frame:expandTemplate{ title='Occupation', args=args })
			end
		end
	end
	
	-- Look up nationality
	if args0.nationality then -- from input arguments
		nationality = mw.text.split(args0.nationality or '', '/')
		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
	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}

	return outStr, args, data
end

--[[
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 = {}
	for name, value in pairs( frame.args ) do 
		value = string.gsub(value,"\/+$", "") -- remove /// on the end
		value = string.gsub(value,"%s*$", "") -- remove whitespaces on the end
		value = string.gsub(value,"^%s*", "") -- remove whitespaces at the beggining
		if value ~= '' then -- nuke empty strings
			local name1 = string.gsub( string.lower(name), ' ', '_')
			args0[name1] = value
		end
	end
	if not (args0.lang and mw.language.isSupportedLanguage(args0.lang)) then 
		args0.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language 
	end
	local outStr, args, data = p._NationAndOccupation(args0)
	return outStr
end

return p