Module:Cite IUCN
- Afrikaans
- العربية
- অসমীয়া
- Azərbaycanca
- تۆرکجه
- Basa Bali
- বাংলা
- Banjar
- Беларуская
- भोजपुरी
- Bosanski
- Dansk
- الدارجة
- Esperanto
- Galego
- 한국어
- हिन्दी
- Hrvatski
- Igbo
- Ilokano
- Bahasa Indonesia
- Íslenska
- ქართული
- Kurdî
- Lietuvių
- मैथिली
- Македонски
- മലയാളം
- मराठी
- Bahasa Melayu
- Монгол
- မြန်မာဘာသာ
- नेपाली
- 日本語
- Norsk nynorsk
- ଓଡ଼ିଆ
- Oʻzbekcha / ўзбекча
- ပအိုဝ်ႏဘာႏသာႏ
- Português
- Română
- Scots
- සිංහල
- Simple English
- سنڌي
- Slovenščina
- کوردی
- Српски / srpski
- Sunda
- Tagalog
- တႆး
- ไทย
- Türkçe
- Українська
- اردو
- Vahcuengh
- Tiếng Việt
- 中文
- Betawi
- Kadazandusun
- Jaku Iban
Usage
{{#invoke:Cite IUCN|cite}} – for {{cite IUCN}}
{{#invoke:Cite IUCN|make_cite_iucn}} – for {{make cite IUCN}}
Background information
Old-style and new-style IUCN urls
Until late 2018, the IUCN assessments used urls of form
http://www.iucnredlist.org/details/15955/0- where 15955 is the taxon ID and the "0" suffix indicates a global assessment (other single digit numbers code for various regional assessments).
From around September 2018, the IUCN switched to a new format for the url, of the form
https://www.iucnredlist.org/species/15955/50659951- where the 15955 is the taxon ID and a unique suffix identies a version of an assessment. This left all Wikipedia links to IUCN assessments as dead links.
Shortly afterwards the IUCN produced a backup of the old system with links of the form
http://oldredlist.iucnredlist.org/details/15955/0- which uses an old-style url form on the oldredlist subdomain. Many citations were switched over to this url. However, this subdomain was shut down near the end of 2019, leaving many dead links generating 502 Bad Gateway errors.
Current IUCN citations
A typical IUCN citation, as given on their assessment pages, is now of the form:
- Goodrich, J., Lynam, A., Miquelle, D., Wibisono, H., Kawanishi, K., Pattanavibool, A., Htun, S., Tempa, T., Karki, J., Jhala, Y. & Karanth, U. 2015. Panthera tigris. The IUCN Red List of Threatened Species 2015: e.T15955A50659951. https://dx.doi.org/10.2305/IUCN.UK.2015-2.RLTS.T15955A50659951.en. Downloaded on 19 December 2019.
- where the electronic article number
e.T15955A50659951contains the taxon ID (between the T and A) and the assessment ID (after the A). These two identifying numbers are also contained in the doi.
When there is an amendment to an assessment, a new assessment number is assigned, which causes a change in the electronic article number and the url of the page.
The behaviour of the doi is unusual. A new assessment does not cause a new doi, it retains the original assessment number. If this is used by a template to construct a url, it will be to the original version of the assessment. However, if the url of the doi is followed, the IUCN doi resolver redirects to the latest assessment. The target of the doi has changed to the revised version of the IUCN assessment. Thus if the template uses the doi url the linked page will change from the one seen by the editor who added the citation.
Therefore this module will create a url with the following order of precedence:
- Use the electronic article number set by the
|article-number=parameter to generate the url. - Use the
|id=to generate the url if it is of the two new-style two part form, i.e.TAXON_ID/ASSESSMENT_ID(e.g.15955/50659951) - Use the
|doi=parameter to generate the url. This is last choice because it uses the number of the original assessment even when the assessment has been amended.
When none of the above options are available, and when |url= has the old form, this module will change the scheme from http:// to https:// in an attempt to make a working link (see next section).
Legacy issue with old-style urls
There is still a legacy issue with old-style IUCN urls, which are still used in many Wikipedia citations.
Some months after the change to the new-style urls, the IUCN introduced redirects for the old-style urls that link to the appropriate pages addressed by the new style url. In most cases these redirects will work. So the oldstyle url for the tiger https://www.iucnredlist.org/details/15955/0 correctly links to the assessment at https://www.iucnredlist.org/species/15955/50659951 (see tiger).
However, not all assessments redirect. For instance, the oldstyle url for the Bengal mud eel http://www.iucnredlist.org/details/166410/0 links to the home page (see Bengal mud eel).
This failure of some old style url to be redirected is unexpected, as the redirect function of the IUCN API does link to the correct page. A url of the form
https://apiv3.iucnredlist.org/api/v3/taxonredirect/166410- will link to the correct page, even in cases where the automatic redirect faile, e.g. the Bengal mud eel.
However, redirects are not available when the taxon id has been replaced and an error in JSON format is returned (e.g. for house sparrow).
New taxon IDs
There is another case where the old style urls gives dead links, when the taxon ID has changed. For instance, the Italian sparrow was split off from the house sparrow as a new species and both assigned new taxon IDs. This left any old style urls to the original assessment as dead links.
- Old-style url
http://www.iucnredlist.org/details/149100/0for house sparrow (dead link on old taxon id149100) - New-style url
https://www.iucnredlist.org/species/103818789/155522130for house sparrow (Passer domesticus), using new taxon id and assessment number103818789/155522130. - New-style url
https://www.iucnredlist.org/species/103819014/132196181for Italian sparrow (Passer italiae), using new taxon id and assessment number103819014/132196181.
In this case there is no action the template/module can take to resolve the issue. Active intervention of an editor is required.
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.
require('strict'); localgetArgs=require('Module:Arguments').getArgs; localamendment_pattern='%s*%(amended version of (%d%d%d%d) assessment%)'; localerrata_pattern='%s*%(errata version published in (%d%d%d%d)%)'; localgreen_status_pattern='%s*%((Green Status assessment)%)'; --[[--------------------------< I U C N _ I D E N T I F I E R S _ G E T >-------------------------------------- cs1|2 templates cite single sources; when the identifiers in |doi=, |id=, and |article-number= are different from each other then the template is attempting to cite multiple sources. This function evaluates the identifier portions of these parameters. returns seven values: identifyier parts (or nil when parameter not used) and a message (nil on success, error message else) the identifier portions of the several parameters must be properly formed ]] localfunctioniucn_identifiers_get(args,error_msgs_t,maint_msgs_t) localdoi_taxon_ID,doi_assesment_ID localart_num_taxon_ID,art_num_assesment_ID localurl_taxon_ID,url_assesment_ID ifargs.doithen locallang_tag doi_taxon_ID,doi_assesment_ID,lang_tag=args.doi:match('[Tt](%d+)[Aa](%d+)%.(%l%l)$') ifnotdoi_taxon_IDornot({['en']=true,['es']=true,['fr']=true,['pt']=true})[lang_tag]then table.insert(error_msgs_t,'malformed |doi= identifier'); end end localartnum=args['article-number']orargs.page;-- |page= is deprecated; one accepted; |article-number= preferred ifartnumthen art_num_taxon_ID,art_num_assesment_ID=artnum:match('^[eE]%.[Tt](%d+)[Aa](%d+)$') ifnotart_num_taxon_IDthen table.insert(error_msgs_t,'malformed |article-number= identifier'); end ifargs.pagethen-- maint message when |page= is used table.insert(maint_msgs_t,'uses deprecated |page= identifier'); args.page=nil;-- unset as not used args['article-number']=artnum;-- make sure that {{cite journal}} gets |article-number= end end ifargs.urlthen ifargs.url:match('https://www.iucnredlist.org/species/')then-- must be a 'new-form' url url_taxon_ID,url_assesment_ID=args.url:match('/species/(%d+)/(%d+)') ifnoturl_taxon_IDthen table.insert(error_msgs_t,'malformed |url= identifier'); end end end ifnoterror_msgs_t[1]then ifdoi_taxon_IDandart_num_taxon_IDthen if(doi_taxon_ID~=art_num_taxon_IDor((doi_assesment_ID~=art_num_assesment_ID)andnotargs.errata))then table.insert(error_msgs_t,'|doi= / |article-number= mismatch'); end end ifdoi_taxon_IDandurl_taxon_IDthen if(doi_taxon_ID~=url_taxon_IDor((doi_assesment_ID~=url_assesment_ID)andnotargs.errata))then table.insert(error_msgs_t,'|doi= / |url= mismatch'); end end ifart_num_taxon_IDandurl_taxon_IDthen if(art_num_taxon_ID~=url_taxon_IDor((art_num_assesment_ID~=url_assesment_ID)andnotargs.errata))then table.insert(error_msgs_t,'|article-number= / |url= mismatch'); end end end returndoi_taxon_ID,doi_assesment_ID,art_num_taxon_ID,art_num_assesment_ID; end --[[--------------------------< I U C N _ V O L U M E _ C H E C K >-------------------------------------------- compares volume in |volume= (if present) against year in |date= or |year= (if present) against volume in |doi= (if present) returns nil if all that are present are correct; message else ]] localfunctioniucn_volume_check(args,maint_msgs_t) localvol=args.volume; localdate=args.dateorargs.year; localdoi=args.doiandargs.doi:match('[Ii][Uu][Cc][Nn]%.[Uu][Kk]%.(%d%d%d%d)') ifvolanddateand(vol~=date)then table.insert(maint_msgs_t,'|volume= / |date= mismatch'); end ifvolanddoiand((vol~=doi)andnotargs.amends)then table.insert(maint_msgs_t,'|volume= / |doi= mismatch'); end ifdateanddoiand((doi~=date)andnotargs.amends)then table.insert(maint_msgs_t,'|date= / |doi= mismatch'); end end --[[--------------------------< _ C I T E >-------------------------------------------------------------------- entry point for calls from another module Wraps {{cite journal}}: takes cite journal parameters but updates old style url using electronic article number number |article-number= should be in format e.T13922A45199653 the url uses 13922/45199653 so we need to extract the number between T and A (taxon ID) and the number after A (assessment ID) the target url is https://www.iucnredlist.org/species/13922/45199653 usage: {{#invoke:iucn|cite}} template: {{Template:Cite iucn}} ]] localfunction_cite(args,frame) localerror_msgs_t={};-- holds error messages for rendering localmaint_msgs_t={};-- holds hidden maint messages for rendering localnamespace=mw.title.getCurrentTitle().namespace;-- used for categorization frame=frameormw.getCurrentFrame()-- fetches frame if called from another module ifargs.titleand(args.title:match(errata_pattern)orargs.title:match(amendment_pattern))then table.insert(error_msgs_t,'title has extraneous text');-- announce that this template has has errata or amendment text end localdoi_taxon_ID,doi_assesment_ID;-- all of these contain the same identifying info in slightly localart_num_taxon_ID,art_num_assesment_ID;-- different forms. when any combination of these is present, doi_taxon_ID,doi_assesment_ID,art_num_taxon_ID,art_num_assesment_ID=iucn_identifiers_get(args,error_msgs_t,maint_msgs_t); args.id=nil-- unset; not supported localurl_taxon_ID=art_num_taxon_IDordoi_taxon_ID;-- select for use in url that we will create localurl_assesment_ID=art_num_assesment_IDordoi_assesment_ID; localurl=args.url; ifurlthen ifurl:find('iucnredlist.org/details/',1,true)then-- old-form url ifurl_taxon_IDthen-- when there is an identifier url=nil-- unset; we'll create new url below else-- here when old-form but no identifier that we can use to create new url args.url=args.url:gsub("http:","https:")-- sometimes works with redirect on iucn site end table.insert(maint_msgs_t,'old-form url')-- announce that this template has has an old-form url elseifurl:find('iucnredlist.org/species/',1,true)then-- new-form url -- table.insert (maint_msgs_t, 'new-form url') --TODO: restore this line when most new-form urls have been removed from article space -- announce that this template has has an new-form url else table.insert(error_msgs_t,'unknown url')-- emit error message end end ifnoturlthen-- when no url or unset old-form url ifurl_taxon_IDthen args.url="https://www.iucnredlist.org/species/"..url_taxon_ID..'/'..url_assesment_ID else table.insert(error_msgs_t,'no identifier')-- emit error message end end -- add journal if not provided (TODO decide if this should override provided value) ifnotargs['journal']andnotargs['work']then args['journal']="[[IUCN Red List|IUCN Red List of Threatened Species]]" end iucn_volume_check(args,maint_msgs_t);-- |volume=, |year= (|date=), |doi= must all refer to the same volume ifnotargs.volumeand(args.yearorargs.date)then args.volume=args.yearorargs.date end ifargs.erratathen args['orig-date']='errata version of '..(args.yearorargs.dateorargs.volume)..' assessment'; args.date=args.errata;-- update publication data to errata year args.year=nil;-- unset these as no longer needed args.errata=nil; elseifargs.amendsthen args['orig-date']='amended version of '..args.amends..' assessment'; args.amends=nil;-- unset as no longer needed end -- add free-to-read icon to mark a correctly formed doi args['doi-access']=args.doiandargs.doi:match('10%.2305/[Ii][Uu][Cc][Nn].+[Tt]%d+[Aa]%d+%.%a%a')and'free'ornil localout_t={}; iferror_msgs_t[1]then table.insert(out_t,' <span class="error" style="font-size:100%">{{[[Template:cite iucn|cite iucn]]}}: error: '); table.insert(out_t,table.concat(error_msgs_t,', ')); table.insert(out_t,' ([[Template:Cite iucn#Error messages|help]])'); if(0==namespace)then table.insert(out_t,'[[Category:cite IUCN errors]]'); end table.insert(out_t,'</span>'); end ifmaint_msgs_t[1]then table.insert(out_t,'<span class="citation-comment" style="display: none; color: #085; margin-left: 0.3em;">'); ifnoterror_msgs_t[1]then table.insert(out_t,'{{[[Template:cite iucn|cite iucn]]}}: ') table.insert(out_t,table.concat(maint_msgs_t,', ')); table.insert(out_t,' ([[Template:Cite iucn#Maintenance messages|help]])'); if(0==namespace)then table.insert(out_t,'[[Category:cite IUCN maint]]'); end end table.insert(out_t,'</span>'); end if(notargs['doi-access'])and(0==namespace)then table.insert(out_t,'[[Category:cite IUCN without doi]]'); end returnrequire('Module:Citation/CS1')._citation(frame,args,{CitationClass='journal'})..-- invoke the module to bypass the call to {{cite journal}} table.concat(out_t);-- error and maint messages and categories end --[[--------------------------< C I T E >---------------------------------------------------------------------- entry point for template calls ]] localfunctioncite(frame) localargs=getArgs(frame);-- local copy of template arguments return_cite(args,frame); end --[=[-------------------------< E T _ A L _ P A T T E R N S >-------------------------------------------------- This adapted from Module:Citation/CS1/Configuration This table provides Lua patterns for the phrase "et al" and variants in a name. ]=] localet_al_patterns={ "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\"']*$",-- variations on the 'et al' theme "[;,]? *[\"']*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\"']*$",-- variations on the 'et alia', 'et alii' and 'et aliae' themes (false positive 'et aliie' unlikely to match) "[;,]? *%f[%a]and [Oo]thers",-- an alternative to et al. } --[[---------------------< N A M E _ H A S _ E T A L >-------------------------- This adapted from Module:Citation/CS1 Evaluates the content of a name for variations on the theme of et al. If found, returns true; nil else ]] localfunctionname_has_etal(name) localetal; ifnamethen-- name can be nil in which case just return name=name:gsub('%b<>','');-- remove any html markup (typically <i>...</i>) for_,patterninipairs(et_al_patterns)do-- loop through all of the patterns ifname:match(pattern)then-- if this 'et al' pattern is found in name returntrue;-- has etal, so return true end end end end --[[--------------------------< A U T H O R _ L I S T _ M A K E >---------------------------------------------- creates a list of individual |authorn= parameters from the list of names provided in the raw iucn citation. names must have the form: Surname, I. (more than one 'I.' pair allowed but no spaces between I. pairs) assumes that parenthetical text at the end of the author-name-list is a collaboration Name, I.I., & Name, I.I. (Colaboration name) assumes that <i>et al.</i> is the last name in a list of names ]] --local function author_names_get (raw_iucn_cite) localfunctionauthor_names_get(raw_iucn_cite,params_t)-- EXPERIMENT locallist={};-- table that holds name list parts localauthor_names=raw_iucn_cite:match('^([^%d]-)%s+%d%d%d%d');-- extract author name-list from raw iucn citation localcollaboration=author_names:match('%s*(%b())$');-- get collaboration name if it exists ifcollaborationthen-- when there is a colaboration collaboration=collaboration:gsub('[%(%)]','');-- remove bounding parentheses author_names=author_names:gsub('%s*(%b())$','');-- and remove collaboration from author-name-list end localnames=author_names:gsub('%.?,?%s+&%s+','.|');-- replace 'separators' (<optional dot><optional comma><space><ampersand><space>) with <dot><pipe> names=names:gsub('%.,%s*','.|');-- replace 'separators' (<dot><comma><optional space>) with <dot><pipe> names=names:gsub('(%.%u),','%1.|');-- special case for when last initial is missing its trailing dot list=mw.text.split(names,'|');-- split the string on the pipes into entries in list{} if0==#listthen params_t['author']=author_names;-- EXPERIMENT returntable.concat({'|author=',author_names}),params_t;-- EXPERIMENT -- no 'names' of the proper form; return the original as a single |author= parameter -- return table.concat ({'|author=', author_names}) -- no 'names' of the proper form; return the original as a single |author= parameter else fori,nameinipairs(list)do-- spin through the list and ifname_has_etal(name)then-- if this name has some form of 'et al' params_t['display-authors']='etal';-- EXPERIMENT list[i]='|display-authors=etal';-- add |dispaly-authors=etal parameter and break;-- assume that the etal was the last 'name' so stop processing names else params_t['author'..i]=name;-- EXPERIMENT list[i]=table.concat({'|author',(i==1)and''ori,'=',name});-- add |authorn= parameter names; create |author= instead of |author1= end end ifcollaborationthen params_t['collaboration']=collaboration;-- EXPERIMENT table.insert(list,table.concat({'|collaboration','=',collaboration}));-- add |collaboration= parameter end returntable.concat(list,' ');-- make a big string and return that end end --[[--------------------------< T I T L E _ G E T >------------------------------------------------------------ extract and format citation title; attempts to get the italic right ''binomen'' (amended or errata title) ''binomen'' ''binomen'' ssp. ''subspecies'' ''binomen'' subsp. ''subspecies'' ''binomen'' var. ''variety'' ''binomen'' subvar. ''subvariety'' all of the above may have trailing amended or errata text in parentheses TODO: are there others? ]] localfunctiontitle_get(raw_iucn_cite) localtitle=raw_iucn_cite:match('%d%d%d%d%.%s+(.-)%s*%. The IUCN Red List of Threatened Species'); localpatterns={-- tables of string.match patterns [1] and string.gsub patterns [2] {'(.-)%sssp%.%s+(.-)%s(%b())$',"''%1'' ssp. ''%2'' %3"},-- binomen ssp. subspecies (zoology) with errata or amended text {'(.-)%sssp%.%s+(.+)',"''%1'' ssp. ''%2''"},-- binomen ssp. subspecies (zoology) {'(.-)%ssubsp%.%s+(.-)%s(%b())$',"''%1'' subsp. ''%2'' %3"},-- binomen subsp. subspecies (botany) with errata or amended text {'(.-)%ssubsp%.%s+(.+)',"''%1'' subsp. ''%2''"},-- binomen subsp. subspecies (botany) {'(.-)%svar%.%s+(.-)%s+(%b())$',"''%1'' var. ''%2'' %3"},-- binomen var. variety (botany) with errata or amended text {'(.-)%svar%.%s+(.+)',"''%1'' var. ''%2''"},-- binomen var. variety (botany) {'(.-)%ssubvar%.%s+(.-)%s(%b())$',"''%1'' subvar. ''%2'' %3"},-- binomen subvar. subvariety (botany) with errata or amended text {'(.-)%ssubvar%.%s+(.+)',"''%1'' subvar. ''%2''"},-- binomen subvar. subvariety (botany) {'(.-)%s*(%b())$',"''%1'' %2"},-- binomen with errata or amended text {'(.+)',"''%1''"},-- binomen } fori,vinipairs(patterns)do-- spin through the patterns iftitle:match(v[1])then-- when a match title=title:gsub(v[1],v[2]);-- add italics break;-- and done end end -- return table.concat ({' |title=', title}); -- return the |title= parameter returntitle;-- return the formatted title end --[[--------------------------< M A K E _ C I T E _ I U C N >-------------------------------------------------- parses apart an iucn-format citation copied from their webpage and reformats that into a {{cite iucn}} template for substing automatic substing by User:AnomieBOT/docs/TemplateSubster ]] localfunctionmake_cite_iucn(frame) localargs_t=getArgs(frame); localraw_iucn_cite=args_t[1]; localtemplate_t={'{{cite iucn '};-- sequence that holds the {{cite iucn}} template as it is being assembled; for nowiki'd output localparams_t={};-- table of parameter/value pairs for substing localyear,volume,artnum,doi,accessdate; year=raw_iucn_cite:match('^%D+(%d%d%d%d)'); volume,artnum=raw_iucn_cite:match('(%d%d%d%d):%s+(e%.T%d+A+%d+)%.%s?'); doi=raw_iucn_cite:match('10%.2305/IUCN%.UK%.[%d%-]+%.RLTS%.T%d+A%d+%.%a%a'); accessdate=raw_iucn_cite:match('Accessed on (.-)%.?$')orraw_iucn_cite:match('Downloaded on (.-)%.?$');-- 'Downloaded' → 'Accessed' change occured December 2021; accessdate=accessdate:gsub('^0','');-- strips leading 0 in day 01 January 2020 -> 1 January 2020 table.insert(template_t,author_names_get(raw_iucn_cite,params_t));-- add author name parameters; as a single string to <template_t>; as individual entries to <params_t> table.insert(template_t,table.concat({' |year=',year}));-- add formatted year params_t.year=year; localtitle=title_get(raw_iucn_cite); localtype_p=title:match(green_status_pattern); iftype_pthen title=title:match('^([^%(]+)%s*%('); table.insert(template_t,table.concat({' |type=',type_p}));-- add formatted errata params_t.type=type_p; end localerrata=title:match(errata_pattern);-- nil unless IUCN citation has errata annotation; else year that this errata published (|date=) iferratathen table.insert(template_t,table.concat({' |errata=',errata}));-- add formatted errata params_t.errata=errata; title=title:gsub(errata_pattern,'');-- remove errata annotation end localamends=title:match(amendment_pattern);-- nil unless IUCN citation has amendment annotation; else year that this assessment amends (|orig-date=) ifamendsthen table.insert(template_t,table.concat({' |amends=',amends}));-- add year of assessment that this assessment amends params_t.amends=amends; title=title:gsub(amendment_pattern,'');-- remove amendment annotation end table.insert(template_t,table.concat({' |title=',title}));-- add formatted title params_t.title=title; table.insert(template_t,table.concat({' |volume=',volume}));-- add formatted volume params_t.volume=volume; table.insert(template_t,table.concat({' |article-number=',artnum}));-- add formatted article number params_t['article-number']=artnum; table.insert(template_t,table.concat({' |doi=',doi}));-- add formatted doi params_t.doi=doi; table.insert(template_t,table.concat({' |access-date=',accessdate}));-- add formatted access-date params_t['access-date']=accessdate; table.insert(template_t,'}}');-- close the template ifargs_t[2]then-- if anything in args_t[2], write a nowiki'd version that editors can copy into <ref> tags returnframe:preprocess(table.concat({'<syntaxhighlight lang="wikitext" inline="1">',table.concat(template_t),'</syntaxhighlight>'}));-- caveat lector: if left long enough anomiebot will subst this end ifargs_t['ref']then-- enable subst of ref tags with name returnframe:preprocess('<ref name='..args_t['ref']..'>'..table.concat(template_t)..'</ref>') end returnframe:preprocess(table.concat(template_t));-- render {{cite iucn}} template; substable end --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ ]] return{ cite=cite,-- wraps {{cite journal}} _cite=_cite,-- for calling from other modules make_cite_iucn=make_cite_iucn,-- wraps {{cite IUCN}} }