Модуль:Sources/utils

ХӀокху модулах лаьцна хааман Модуль:Sources/utils/doc агӀо кхолла мега

local p = {};local i18nDefaultLanguage = 'ce';p.i18nDefaultLanguage = i18nDefaultLanguage;local NORMATIVE_DOCUMENTS = {Q20754888 = 'Закон Российской Федерации',Q20754884 = 'Закон РСФСР',Q20873831 = 'Распоряжение Президента Российской Федерации',Q20873834 = 'Указ исполняющего обязанности Президента Российской Федерации',Q2061228 = 'Указ Президента Российской Федерации',}local monthg = {'январехь', 'февралехь', 'мартехь', 'апрелехь', 'майхь', 'июнехь', 'июлехь', 'августехь', "сентябрехь", "октябрехь", "ноябрехь", "декабрехь"};local options_commas_nolinks = { separator = ', ', conjunction = ', ', format = function( src ) return src end, nolinks = true, preferids = false };local function isEmpty( str )return ( not str ) or ( str == nil ) or ( #str == 0 );endp.isEmpty = isEmptylocal function getSingleStringQualifierValue( allQualifiers, qualifierPropertyId )if ( not allQualifiers ) then return endif ( not allQualifiers[qualifierPropertyId] ) then return endfor k, qualifier in pairs( allQualifiers[qualifierPropertyId] ) doif ( qualifier and qualifier.datatype == 'string'and qualifier.datavalue and qualifier.datavalue.type == 'string' and not isEmpty( qualifier.datavalue.value ) ) thenreturn qualifier.datavalue.value;endendreturn;endlocal function appendImpl_toTable(result, resultProperty)if ( not result[resultProperty] ) thenresult[resultProperty] = {};elseif ( type( result[resultProperty] ) == 'string' or ( type( result[resultProperty] ) == 'table' and type( result[resultProperty].id ) == 'string' ) ) thenresult[resultProperty] = { result[resultProperty] };endendlocal function appendImpl( datavalue, qualifiers, result, property, options )if ( datavalue.type == 'string' ) thenlocal statedAs = getSingleStringQualifierValue(qualifiers, 'P1932');local value;if ( statedAs ) thenvalue = statedAs;elsevalue = datavalue.value;if ( options.format ) thenvalue = options.format( value );endendappendImpl_toTable( result, property );local pos = getSingleStringQualifierValue(qualifiers, 'P1545')if pos thentable.insert( result[property], pos, value );elsetable.insert( result[property], value);endelseif ( datavalue.type == 'url' ) thenlocal statedAs = getSingleStringQualifierValue(qualifiers, 'P1932');local value = datavalue.value;if ( options.format ) thenvalue = options.format( value );endappendImpl_toTable( result, property );table.insert( result[property], value);elseif ( datavalue.type == 'monolingualtext' ) thenlocal value = datavalue.value.text;if ( options.format ) thenvalue = options.format( value );endappendImpl_toTable( result, property );table.insert( result[property], value);elseif ( datavalue.type == 'quantity' ) thenlocal value = datavalue.value.amount;if ( mw.ustring.sub( value , 1, 1 ) == '+' ) thenvalue = mw.ustring.sub( value , 2 );endif ( options.format ) thenvalue = options.format( value );endappendImpl_toTable( result, property );table.insert( result[property], value);elseif ( datavalue.type == 'wikibase-entityid' ) thenlocal pos = getSingleStringQualifierValue(qualifiers, 'P1545')local value = datavalue.value;appendImpl_toTable( result, property );local toInsert = {id = value.id,label = getSingleStringQualifierValue(qualifiers, 'P1932') -- stated as};if pos thentable.insert( result[property], pos, toInsert );elsetable.insert( result[property], toInsert );endelseif datavalue.type == 'time' thenlocal value = datavalue.value;if ( options.format ) thenvalue = options.format( value );endappendImpl_toTable( result, property );table.insert( result[property], tostring( value.time ));    end endlocal function appendSnaks( allSnaks, snakPropertyId, result, property, options )-- do not populate twiceif ( result[property] and (property ~= 'author' or result[snakPropertyId])) then return result end;if ( not allSnaks ) then return result; end;local selectedSnaks = allSnaks[ snakPropertyId ];if ( not selectedSnaks ) then return result; end;if (property == 'author') then result[snakPropertyId] = true end;local hasPreferred = false;for k, snak in pairs( selectedSnaks ) doif ( snak and snak.mainsnak and snak.mainsnak.datavalue and snak.rank == 'preferred' ) then--it's a preferred claimappendImpl( snak.mainsnak.datavalue, snak.qualifiers, result, property, options );hasPreferred = true;endendif ( hasPreferred ) then return result; end;if ( snakPropertyId == 'P1680' ) then -- if there is a russian for k, snak in pairs( selectedSnaks ) doif ( snak and snak.mainsnak and snak.mainsnak.datavalue and snak.mainsnak.datavalue.value and  snak.rank ~= 'deprecated' and snak.mainsnak.datavalue.value.language  == i18nDefaultLanguage ) then--found russian stringappendImpl( snak.mainsnak.datavalue, snak.qualifiers, result, property, options );return result;endendend;for k, snak in pairs( selectedSnaks ) doif ( snak and snak.mainsnak and snak.mainsnak.datavalue and snak.rank ~= 'deprecated' ) then--it's a claimappendImpl( snak.mainsnak.datavalue, snak.qualifiers, result, property, options );elseif ( snak and snak.datavalue ) then-- it's a snakappendImpl( snak.datavalue, nil, result, property, options );endendendlocal function appendQualifiers( claims, qualifierPropertyId, result, resultProperty, options )-- do not populate twiceif ( not claims ) then return result end;if ( result[resultProperty] ) then return result end;for i, claim in pairs( claims ) doif ( claim.qualifiers and claim.qualifiers[ qualifierPropertyId ] ) thenfor k, qualifier in pairs( claim.qualifiers[ qualifierPropertyId ] ) doif ( qualifier and qualifier.datavalue ) thenappendImpl( qualifier.datavalue, nil, result, resultProperty, options );endendendendendlocal function assertNotNull( argName, arg )if ( (not arg) or (arg == nil) ) thenerror( argName .. ' is not specified' )endendfunction p.coalesce( arg1, arg2, arg3, arg4 )if ( not isEmpty( arg1 ) ) then return arg1 endif ( not isEmpty( arg2 ) ) then return arg2 endif ( not isEmpty( arg3 ) ) then return arg3 endif ( not isEmpty( arg4 ) ) then return arg4 endreturn nil;endlocal function toStringSnak( propertyId, strValue )assertNotNull('propertyId', strValue)assertNotNull('strValue', strValue)local snak = { snaktype = "value", property = propertyId, datatype = 'string'};snak["datavalue"] = { value = strValue, type = 'string' };return snak;endlocal function toUrlSnak( propertyId, strValue )assertNotNull('propertyId', strValue)assertNotNull('strValue', strValue)local snak = { snaktype = "value", property = propertyId, datatype = 'string'};snak["datavalue"] = { value = strValue, type = 'url' };return snak;endfunction p.copyArgsToSnaks( args, snaks )if ( not isEmpty( args.part ) ) then snaks.P958 = { toStringSnak( 'P958', tostring( args.part ) ) } endif ( not isEmpty( args.pages ) ) then snaks.P304 = { toStringSnak( 'P304', tostring( args.pages ) ) } endif ( not isEmpty( args.issue ) ) then snaks.P433 = { toStringSnak( 'P433', tostring( args.issue ) ) } endif ( not isEmpty( args.volume ) ) then snaks.P478 = { toStringSnak( 'P478', tostring( args.volume ) ) } endif ( not isEmpty( args.url ) ) then snaks.P953 = { toUrlSnak( 'P953', tostring( args.url ) ) } endif ( not isEmpty( args.parturl ) ) then snaks.P953 = { toUrlSnak( 'P953', tostring( args.parturl ) ) } endendlocal LANG_CACHE = {Q150= 'fr',Q188= 'de',Q1321= 'es',Q1860= 'en',Q652= 'it',Q7737= 'ru',}function p.getLangCode( langEntityId )if ( not langEntityId ) thenreturn;end-- small optimizationlocal cached = LANG_CACHE[ langEntityId ];if ( cached ) then return cached; endlocal claims = mw.wikibase.getBestStatements( langEntityId, 'P424' );if ( claims ) thenfor _, claim in pairs( claims ) doif ( claimand claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.value ) thenreturn '' .. claim.mainsnak.datavalue.value;endendendreturn;endlocal function findClaimsByValue( entity, propertyId, value )local result = {};if ( entity and entity.claims and entity.claims[propertyId] ) thenfor i, claim in pairs( entity.claims[propertyId] ) doif ( claim.mainsnak and claim.mainsnak.datavalue ) thenlocal datavalue = claim.mainsnak.datavalue;if ( datavalue.type == "string" and datavalue.value == value or datavalue.type == "wikibase-entityid" and datavalue.value["entity-type"] == "item" and tostring( datavalue.value.id ) == value ) thentable.insert( result, claim );endendendendreturn result;endlocal function getBestStatements( entity, propertyId )local resultClaims = {};if ( entity and entity.claims and entity.claims[ propertyId ] ) thenlocal rank = 'normal';for i, statement in pairs( entity.claims[ propertyId ] ) doif ( statement.rank == 'preferred' ) thenrank = 'preferred';break;endendfor i, statement in pairs( entity.claims[ propertyId ] ) doif ( statement.rank == rank ) thentable.insert( resultClaims, statement );endendendreturn resultClaims;endlocal function getEntity( context, entityId )assertNotNull( 'context', context );assertNotNull( 'entityId', entityId );local cached = context.cache[ entityId ];if ( cached ) thenreturn cached;end;local wbStatus, result = pcall( mw.wikibase.getEntity, entityId );if ( wbStatus ~= true ) thenreturn nil;endif ( result ) thencontext.cache[ entityId ] = result;endreturn result;endp.getEntity = getEntityfunction p.expandBookSeries( context, data )local bookSeries = data.bookSeries;if ( not bookSeries ) then return end;-- use only first oneif ( type( bookSeries ) == 'table' and bookSeries[1] and bookSeries[1].id ) thendata.bookSeries = bookSeries[1];bookSeries = data.bookSeries;endif ( not bookSeries ) then return end;if ( not bookSeries.id ) then return end;local bookSeriesEntity = getEntity( context, bookSeries.id );appendSnaks( bookSeriesEntity.claims, 'P123', data, 'publisher', {} );appendSnaks( bookSeriesEntity.claims, 'P291', data, 'place', {} );appendSnaks( bookSeriesEntity.claims, 'P236', data, 'issn', {} );endlocal function isInstanceOf( entity, typeEntityId )if ( not entity or not entity.claims or not entity.claims.P31 ) thenreturn false;endfor _, claim in pairs( entity.claims.P31 ) doif ( claim and claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.valueand claim.mainsnak.datavalue.value.id ) thenlocal actualTypeId = claim.mainsnak.datavalue.value.id;if ( actualTypeId == typeEntityId ) thenreturn true;endendendreturn false;endp.isInstanceOf = isInstanceOflocal function populateDataFromClaims( context, entityId, claims, data )appendSnaks( claims, 'P50', data, 'author', {} );appendSnaks( claims, 'P2093', data, 'author', {} );appendSnaks( claims, 'P407', data, 'lang', {} );appendSnaks( claims, 'P364', data, 'lang', {} );appendSnaks( claims, 'P958', data, 'part', {} );appendSnaks( claims, 'P1810', data, 'part', {} );if ( not data.title ) thenif ( not isEmpty( entityId ) ) thenlocal optionsAsLinks = { format = function( text ) return { id = entityId, label = text } end };appendSnaks( claims, 'P1476', data, 'title', optionsAsLinks );elseappendSnaks( claims, 'P1476', data, 'title', {} );endappendSnaks( claims, 'P1680', data, 'subtitle', {} );endappendSnaks( claims, 'P953', data, 'url', {} );appendSnaks( claims, 'P1065', data, 'url', {} );appendSnaks( claims, 'P854', data, 'url', {} );appendSnaks( claims, 'P973', data, 'url', {} );    appendSnaks( claims, 'P2699', data, 'url', {} );-- temp disable, use only for current entity, see Q22338048 for example of incorrect work-- appendSnaks( claims, 'P856', data, 'url', {} );appendSnaks( claims, 'P98', data, 'editor', {} );appendSnaks( claims, 'P655', data, 'translator', {} );appendSnaks( claims, 'P1433', data, 'publication', {} );appendSnaks( claims, 'P393', data, 'edition', {} );appendSnaks( claims, 'P123', data, 'publisher', {} );appendSnaks( claims, 'P291', data, 'place', {} );if ( claims and claims.P361 ) thenfor c, claim in pairs( claims.P361 ) doif ( claim and claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.valueand claim.mainsnak.datavalue.value.id ) thenlocal possibleBookSeriesEntityId = claim.mainsnak.datavalue.value.id;local possibleBookSeriesEntity = getEntity( context, possibleBookSeriesEntityId );if ( isInstanceOf( possibleBookSeriesEntity, 'Q277759' ) ) thenappendImpl_toTable( data, 'bookSeries' );table.insert( data.bookSeries, { id = possibleBookSeriesEntityId } );appendQualifiers( { claim }, 'P478', data, 'bookSeriesVolume', {} );appendQualifiers( { claim }, 'P433', data, 'bookSeriesIssue', {} );endendendendappendSnaks( claims, 'P478', data, 'volume', {} );appendSnaks( claims, 'P433', data, 'issue', {} );appendSnaks( claims, 'P571', data, 'dateOfCreation', {} );appendSnaks( claims, 'P577', data, 'dateOfPublication', {} );appendSnaks( claims, 'P304', data, 'pages', {} );appendSnaks( claims, 'P1104', data, 'numberOfPages', {} );appendSnaks( claims, 'P1092', data, 'tirage', {} );appendSnaks( claims, 'P212', data, 'isbn', {} ); -- ISBN-13appendSnaks( claims, 'P957', data, 'isbn', {} ); -- ISBN-10appendSnaks( claims, 'P236', data, 'issn', {} );    -- web-- appendSnaks( claims, 'P813', data, 'accessdate', {} );    -- docsappendSnaks( claims, 'P1545', data, 'docNumber', {} );-- otherappendSnaks( claims, 'P31', data, 'type', {} );appendSnaks( claims, 'P818', data, 'arxiv', {} );appendSnaks( claims, 'P356', data, 'doi', {} );appendSnaks( claims, 'P698', data, 'pmid', {} );-- JSTORappendSnaks( claims, 'P888', data, 'url', { format = function( id ) return 'http://www.jstor.org/stable/' .. id end } );return src;endp.populateDataFromClaims = populateDataFromClaimslocal function getNormativeTitle( entity )if ( not entity or not entity.claims or not entity.claims.P31 ) thenreturn;endfor _, claim in pairs( entity.claims.P31 ) doif ( claim and claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.valueand claim.mainsnak.datavalue.value.id ) thenlocal classId = claim.mainsnak.datavalue.value.id;local title = NORMATIVE_DOCUMENTS[ classId ];if ( title ) thenreturn title;endendendreturn;endlocal function getSingle( value )if ( not value ) thenreturn;endif ( type( value ) == 'string' ) thenreturn value;elseif ( type( value ) == 'table' ) thenif ( value.id ) thenreturn value.id;endfor i, tableValue in pairs( value ) doreturn getSingle( tableValue );endendreturn '(unknown)';endp.getSingle = getSinglelocal function wrapInUrl( urls, text )local url = getSingle( urls );if ( string.sub( url, 1, 1 ) == ':' ) thenreturn '[[' .. url .. '|' .. text .. ']]';elsereturn '[' .. url .. ' ' .. text .. ']';endendp.wrapInUrl = wrapInUrllocal function getElementLink( context, entityId, entity )-- fast sitelink lookup, not an expensive operationlocal link = mw.wikibase.sitelink( entityId )if ( link ) then return ':' .. link endif ( not entity and entityId ) thenentity = getEntity( context, entityId )endif ( entity and context.lang ~= 'mul') then-- link to entity in source context languagelocal projectToCheck = context.lang .. 'wiki';if ( entity.sitelinks and entity.sitelinks[ projectToCheck ] ) thenreturn ':' .. context.lang .. ':' .. entity.sitelinks[ projectToCheck ].title;endendif ( entityId ) then return ':d:' .. entityId end;-- if ( entityId ) then return 'https://tools.wmflabs.org/reasonator/?q=' .. entityId .. '&lang=ru' end;return nil;endp.getElementLink = getElementLinklocal function renderLink( context, entityId, customTitle, options )if ( not entityId ) then error("entityId is not specified") endif ( type( entityId ) ~= 'string' ) then error('entityId is not string, but ' .. type( entityId ) ) endif ( type( customTitle or '' ) ~= 'string' ) then error('customTitle is not string, but ' .. type( customTitle ) ) endlocal title = customTitle;if ( isEmpty( title ) ) thenlocal entity = getEntity( context, entityId );-- ISO 4if ( isEmpty( title ) ) thenif ( entity and entity.claims and entity.claims.P1160 ) thenfor _, claim in pairs( entity.claims.P1160 ) doif ( claimand claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.valueand claim.mainsnak.datavalue.value.language == context.lang ) thentitle = claim.mainsnak.datavalue.value.text;mw.log('Got title of ' .. entityId .. ' from ISO 4 claim: «' .. title .. '»' )break;endendendend-- official name P1448-- short name P1813if ( isEmpty( title ) and options.short ) thenif ( entity and entity.claims and entity.claims.P1813 ) thenfor _, claim in pairs( entity.claims.P1813 ) doif ( claimand claim.mainsnakand claim.mainsnak.datavalueand claim.mainsnak.datavalue.valueand claim.mainsnak.datavalue.value.language == context.lang ) thentitle = claim.mainsnak.datavalue.value.text;mw.log('Got title of ' .. entityId .. ' from short name claim: «' .. title .. '»' )break;endendendend-- person name P1559-- labelsif ( isEmpty( title ) and entity.labels[ context.lang ] ) thentitle = entity.labels[ context.lang ].value;mw.log('Got title of ' .. entityId .. ' from label: «' .. title .. '»' )endendlocal actualText = title or '\'\'(untranslated)\'\'';local link = getElementLink( context, entityId, entity);return wrapInUrl( link, actualText );endlocal function toString( context, value, options )if ( type( value ) == 'string' ) thenreturn options.format( value );elseif ( type( value ) == 'table' ) thenif ( value.id ) then-- this is linkif ( type( value.label or '' ) ~= 'string' ) then mw.logObject( value ); error('label of table value is not string but ' .. type( value.label ) ) endif ( options.preferids ) thenreturn options.format( value.id );elseif ( options.nolinks ) thenreturn options.format( value.label or mw.wikibase.label( value.id ) or '\'\'(untranslated title)\'\'' );elsereturn options.format( renderLink( context, value.id, value.label, options ) );endendendlocal resultList = {};for i, tableValue in pairs( value ) dotable.insert( resultList, toString( context, tableValue, options ) );endreturn mw.text.listToText( resultList, options.separator, options.conjunction);elsereturn options.format( '(unknown type)' );endreturn '';endp.toString = toStringlocal function populateSourceDataImpl( context, entity, plainData )    local wsLink = mw.wikibase.getSitelink( entity.id, 'ruwikisource' );    if ( wsLink ) then       plainData.url = ":ru:s:" .. wsLink;    endpopulateDataFromClaims( context, entity.id, entity.claims, plainData );local normativeTitle = getNormativeTitle( entity )if ( normativeTitle ) thenlocal y, m, d = mw.ustring.match( getSingle( plainData.dateOfCreation ) , "(%-?%d+)%-(%d+)%-(%d+)T" );y,m,d = tonumber(y),tonumber(m),tonumber(d);local title = toString( { lang='ru' }, plainData.title, options_commas_nolinks );plainData.title = { normativeTitle .. " от&nbsp;" .. tostring(d) .. "&nbsp;" .. monthg[m]  .. " " .. tostring(y) .. "&nbsp;г. №&nbsp;" .. getSingle( plainData.docNumber ) .. ' «' .. title.. '»' }endif ( not plainData.title ) thenif ( entity and entity.labels and entity.labels.ru and entity.labels.ru.value ) thenplainData.title = { entity.labels.ru.value };endendreturn plainData;endp.populateSourceDataImpl = populateSourceDataImplfunction p.expandPublication( context, sourceEntity, data )local publication = data.publication;-- use only first oneif ( type( publication ) == 'table' and publication[1] and publication[1].id ) thendata.publication = publication[1];publication = data.publication;endif ( not publication ) then return end;if ( not publication.id ) then return end;if ( sourceEntity ) then-- do we have appropriate record in P1433 ?local claims = findClaimsByValue( sourceEntity, 'P1433', publication.id );if ( claims and #claims ~= 0 ) thenfor _, claim in pairs( claims ) dopopulateDataFromClaims( context, sourceEntity, claim.qualifiers, data );break;endendendlocal titleWerePresent = not (not data.title);local pubEntity = getEntity( context, publication.id );populateSourceDataImpl( context, pubEntity, data );if ( titleWerePresent and isEmpty( data.publication.label ) ) thenappendSnaks( pubEntity.claims, 'P1160', data, 'publication-title', {} ); -- obsoletedata.publication.label = getSingle( data['publication-title'] );endif ( titleWerePresent and isEmpty( data.publication.label ) ) thenappendSnaks( pubEntity.claims, 'P1476', data, 'publication-title', {} );appendSnaks( pubEntity.claims, 'P1680', data, 'publication-subtitle', {} );data.publication.label = getSingle( data['publication-title'] );data.publication.subtitle = getSingle( data['publication-subtitle'] );endendlocal function expandSpecialsQualifiers( context, entity, propertyId, data )if ( entity and entity.claims and entity.claims[propertyId] ) thenfor _, claim in pairs( entity.claims[propertyId] ) dopopulateDataFromClaims( context, nil, claim.qualifiers, data );endendend-- Expand special types of references when additional data could be found in OTHER entity propertiesfunction p.expandSpecials( context, currentEntity, reference, data )local sourceId;if ( reference.snaks.P805and reference.snaks.P805[1]and reference.snaks.P805[1].datavalueand reference.snaks.P805[1].datavalue.value.id ) thensourceId = reference.snaks.P805[1].datavalue.value.id;elseif ( reference.snaks.P248and reference.snaks.P248[1]and reference.snaks.P248[1].datavalueand reference.snaks.P248[1].datavalue.value.id ) thensourceId = reference.snaks.P248[1].datavalue.value.id;endif sourceId thendata.sourceId = sourceId;-- Gemeinsame Normdatei -- specified by P227if ( sourceId == 'Q36578' ) thenappendSnaks( currentEntity.claims, 'P227', data, 'part', { format = function( gnd ) return 'Record #' .. gnd; end } );appendSnaks( currentEntity.claims, 'P227', data, 'url', { format = function( gnd ) return 'http://d-nb.info/gnd/' .. gnd .. '/'; end } );data.year = '2012—2016'expandSpecialsQualifiers( context, currentEntity, 'P227', data );-- BNF -- specified by P268elseif ( sourceId == 'Q15222191' ) thenappendSnaks( currentEntity.claims, 'P268', data, 'part', { format = function( id ) return 'Record #' .. id; end } );appendSnaks( currentEntity.claims, 'P268', data, 'url', { format = function( id ) return 'http://catalogue.bnf.fr/ark:/12148/cb' .. id; end } );expandSpecialsQualifiers( context, currentEntity, 'P268', data );-- VIAF -- specified by P214elseif ( sourceId == 'Q54919' ) thenappendSnaks( currentEntity.claims, 'P214', data, 'part', { format = function( id ) return 'Record #' .. id; end } );appendSnaks( currentEntity.claims, 'P214', data, 'url', { format = function( id ) return 'https://viaf.org/viaf/' .. id; end } );expandSpecialsQualifiers( context, currentEntity, 'P214', data );-- generic property searchelselocal sourceEntity = getEntity( context, sourceId );if ( sourceEntity ) thenfor _, sourceClaim in ipairs( getBestStatements( sourceEntity, 'P1687' ) ) doif ( sourceClaim.mainsnak.snaktype == 'value' ) thenlocal sourcePropertyId = sourceClaim.mainsnak.datavalue.value.id;local sourcePropertyEntity = getEntity( context, sourcePropertyId );if ( sourcePropertyEntity ) thenfor _, sourcePropertyClaim in ipairs( getBestStatements( sourcePropertyEntity, 'P1630' ) ) doif ( sourcePropertyClaim.mainsnak.snaktype == 'value' ) thenappendSnaks( currentEntity.claims, sourcePropertyId, data, 'url', {format = function( id )return mw.ustring.gsub( mw.ustring.gsub( sourcePropertyClaim.mainsnak.datavalue.value, '$1', id ), ' ', '%%20' )end;} );expandSpecialsQualifiers( context, currentEntity, sourcePropertyId, data );break;endendendendendendend-- do we have appropriate record in P1433 ?local claims = findClaimsByValue( currentEntity, 'P1343', sourceId );if ( claims and #claims ~= 0 ) thenfor _, claim in pairs( claims ) dopopulateDataFromClaims( context, sourceId, claim.qualifiers, data );endendendendlocal function toTextWithTip( text, tip )return '<span title="' .. tip .. '" style="border-bottom: 1px dotted; cursor: help; white-space: nowrap">' .. text .. '</span>';endlocal function getPlaceName( lang, placeId )-- ГОСТ Р 7.0.12—2011if ( lang == 'ru' ) thenif ( placeId == 'Q649' ) then return toTextWithTip('М.', 'Москва'); endif ( placeId == 'Q656' ) then return toTextWithTip('СПб.', 'Санкт-Петербург'); endif ( placeId == 'Q891' ) then return toTextWithTip('Н. Новгород', 'Нижний Новгород'); endif ( placeId == 'Q908' ) then return toTextWithTip('Ростов н/Д.', 'Ростов-на-Дону'); endendreturn nil;endfunction p.preprocessPlaces( data, lang )if ( not data.place ) thenreturn;end;local newPlaces = {};for index, place in pairs( data.place ) doif ( place.id ) thenlocal newPlaceStr = getPlaceName(lang, place.id)if ( newPlaceStr ) thennewPlaces[index] = newPlaceStr;elsenewPlaces[index] = place;endelsenewPlaces[index] = place;endenddata.place = newPlaces;endfunction p.toWikibaseEntityIdSnak( propertyId, entityId )assertNotNull('propertyId', propertyId)assertNotNull('entityId', entityId)if ( mw.ustring.sub( entityId, 1, 1 ) ~= 'Q' ) then error( 'Incorrect entity ID: «' .. entityId .. '»' ); end;local value = {["entity-type"] = 'item',["id"] = entityId,};local snak = { snaktype = "value", property = propertyId, datatype = 'wikibase-item'};snak["datavalue"] = { value = value, type = 'wikibase-entityid' };return snak;endreturn p;