Module:Wn/bn/উৎস
Appearance
(Redirected from Module:Wn/bn/source)
| এই মডিউলটি একাধিক পৃষ্ঠাতে এবং বহুসংখ্যক টেমপ্লেটে প্রত্যক্ষ বা পরোক্ষভাবে ব্যবহৃত হয়েছে। এই মডিউলের মধ্যে কোনও প্রকার পরিবর্তনের ফলে সার্ভার লোড বিলম্বিত হতে পারে এবং কোনও ত্রুটি অনেক পৃষ্ঠায় দৃশ্যমান হবে। অনুগ্রহ করে কোনো সম্পাদনা করার আগে সাবধানে পরীক্ষা করুন এবং অপ্রয়োজনীয় সম্পাদনা করা এড়িয়ে চলুন। |
local arguments = require('Module:Wn/bn/Arguments')
local Config = {
Patterns = {
BENGALI = "[\u{0980}-\u{09FF}]",
URL = "^https?://[%w%-%._~:/%?#%[%]@!%$&'%(%)%*%+,;=%%\u{0980}-\u{09FF}]+$",
ENGLISH = "^[A-Za-z0-9%s%p]+$",
LATIN = "[A-Za-z]"
},
Messages = {
NO_PUBLISHER = "ত্রুটি: প্রকাশক প্রদান করা হয়নি",
NO_URL = "ত্রুটি: ইউআরএল প্রদান করা হয়নি",
NO_TITLE = "ত্রুটি: শিরোনাম প্রদান করা হয়নি",
INVALID_URL = "অবৈধ ইউআরএল",
INVALID_ARCHIVE_URL = "অবৈধ সংরক্ষিত ইউআরএল",
INVALID_ACCESS_DATE = "ত্রুটি: প্রাপ্তির তারিখ, প্রকাশনার তারিখের পূর্বে।",
FORMAT_ERROR = "উৎস বিন্যাস ত্রুটি: "
},
Categories = {
NON_BENGALI = "[[Category:Wn/bn/বাংলা ব্যতীত প্যারামিটারযুক্ত উৎস]]",
HAS_ERROR = "[[Category:Wn/bn/ত্রুটিযুক্ত উৎস সহ পৃষ্ঠাসমূহ]]"
},
Mappings = {
Digits = {
['০']='0', ['১']='1', ['২']='2', ['৩']='3', ['৪']='4',
['৫']='5', ['৬']='6', ['৭']='7', ['৮']='8', ['৯']='9'
},
Months = {
['জানুয়ারি']='January', ['জানুয়ারী']='January',
['ফেব্রুয়ারি']='February', ['ফেব্রুয়ারী']='February',
['মার্চ']='March', ['এপ্রিল']='April', ['মে']='May',
['জুন']='June', ['জুলাই']='July', ['আগস্ট']='August',
['সেপ্টেম্বর']='September', ['অক্টোবর']='October',
['নভেম্বর']='November', ['ডিসেম্বর']='December'
},
MonthToNum = {
January=1, February=2, March=3, April=4, May=5, June=6,
July=7, August=8, September=9, October=10, November=11, December=12
}
}
}
-- Utility functions
local Util = {}
function Util.wrapError(text)
return string.format('<span class="error">%s</span>', text)
end
function Util.trim(str)
return str and str:match("^%s*(.-)%s*$")
end
function Util.decodePercent(str)
return str:gsub("%%(%x%x)", function(h)
return string.char(tonumber(h, 16))
end)
end
-- Validation functions
local Validator = {}
function Validator.isValidUrl(url)
if not url then return false end
local cleanUrl = url:gsub("%s+", "")
:gsub("[\u{200B}-\u{200D}]", "")
return cleanUrl:match(Config.Patterns.URL) ~= nil or
Util.decodePercent(cleanUrl):match(Config.Patterns.URL) ~= nil
end
function Validator.containsBengali(text)
return text and (text:match(Config.Patterns.BENGALI) ~= nil or text:match("[।,%d]") ~= nil)
end
function Validator.isEnglish(text)
return text and text:match("[A-Za-z0-9]") ~= nil
end
function Validator.hasNonBengaliContent(text)
return text and text:match(Config.Patterns.LATIN) ~= nil
end
-- Date handling
local DateHandler = {}
function DateHandler.convertToEnglish(str)
local converted = str
for bn, en in pairs(Config.Mappings.Digits) do
converted = converted:gsub(bn, en)
end
for bn, en in pairs(Config.Mappings.Months) do
converted = converted:gsub(bn, en)
end
return converted
end
function DateHandler.parseDate(str)
if not str then return nil end
local engStr = DateHandler.convertToEnglish(Util.trim(str))
local day, month, year = engStr:match("^(%d+)%s+(%a+)[,%s]*(%d+)$")
if not (day and month and year) then return nil end
return {
day = tonumber(day),
month = Config.Mappings.MonthToNum[month] or 0,
year = tonumber(year)
}
end
function DateHandler.compareDates(date1, date2)
if not date1 or not date2 then return true end
local d1 = DateHandler.parseDate(date1)
local d2 = DateHandler.parseDate(date2)
if not d1 or not d2 then return true end
if d1.year ~= d2.year then return d1.year <= d2.year end
if d1.month ~= d2.month then return d1.month <= d2.month end
return d1.day <= d2.day
end
-- Formatter functions
local Formatter = {}
function Formatter.detectLanguage(text, frame)
if not text then return nil end
text = Util.trim(text)
if Validator.isEnglish(text) then
return frame:expandTemplate{title = 'Wn/bn/ইংরেজি'}
end
return nil
end
function Formatter.formatPublisher(frame, publisher)
if not publisher then
return " — " .. Util.wrapError(Config.Messages.NO_PUBLISHER), true
end
local baseText = " — "
if frame:callParserFunction{name = '#ifexist', args = {'Category:Wn/bn/' .. publisher, 'yes', 'no'}} == 'yes' then
return baseText .. string.format('[[:%s|%s]]', 'Category:Wn/bn/' .. publisher, publisher), false
end
return baseText .. string.format('[[w:bn:%s|%s]]', publisher, publisher), false
end
function Formatter.formatUrl(url, archivedUrl, title)
if not url then return Util.wrapError(Config.Messages.NO_URL), true end
if not title then return Util.wrapError(Config.Messages.NO_TITLE), true end
if not Validator.isValidUrl(url) then
return string.format('[%s %s <%s>]', url, title, Config.Messages.INVALID_URL), true
end
if archivedUrl then
if not Validator.isValidUrl(archivedUrl) then
return Util.wrapError(Config.Messages.INVALID_ARCHIVE_URL), true
end
return string.format('[%s %s]', archivedUrl, title), false
end
return string.format('[%s %s]', url, title), false
end
-- Main module
local p = {}
function p.formatSource(frame)
local args = require('Module:Wn/bn/Arguments').getArgs(frame)
local source = {}
local state = {
hasError = false,
hasNonBengaliParams = false
}
-- Check for non-Bengali content
if (args.author and Validator.hasNonBengaliContent(args.author)) or
(args.publisher and Validator.hasNonBengaliContent(args.publisher)) then
state.hasNonBengaliParams = true
end
-- Build source components
if args.author then
table.insert(source, args.author .. "। ")
end
local urlText, urlError = Formatter.formatUrl(args.url, args.archived_url, args.title)
state.hasError = state.hasError or urlError
table.insert(source, '"' .. urlText .. '"')
local publisherText, pubError = Formatter.formatPublisher(frame, args.publisher)
state.hasError = state.hasError or pubError
local separator = (args.archived_url or (args.access_date and not args.date)) and "। " or ", "
table.insert(source, publisherText .. separator)
if args.archived_url and args.url and Validator.isValidUrl(args.url) then
table.insert(source, string.format('মূল [%s সংস্করণ] থেকে সংরক্ষিত। ', args.url))
end
if args.date then
table.insert(source, args.date)
end
if args.access_date then
if args.date and not DateHandler.compareDates(args.date, args.access_date) then
table.insert(source, Util.wrapError(Config.Messages.INVALID_ACCESS_DATE))
state.hasError = true
else
table.insert(source, args.date and "। " or "")
table.insert(source, "সংগ্রহের তারিখ: " .. args.access_date)
end
end
-- Handle language
local languageText
if args.language and args.language:match("%S") then
languageText = frame:expandTemplate{title = 'Wn/bn/Languageicon', args = {args.language}}
else
languageText = args.title and Formatter.detectLanguage(args.title, frame)
end
if languageText then
table.insert(source, "। ")
table.insert(source, languageText)
end
-- Add tracking categories
if state.hasNonBengaliParams then
table.insert(source, "\n" .. Config.Categories.NON_BENGALI)
end
if state.hasError then
table.insert(source, "\n" .. Config.Categories.HAS_ERROR)
end
return table.concat(source, "")
end
function p.formatSourceWithCheck(frame)
local success, result = pcall(p.formatSource, frame)
return success and result or Util.wrapError(Config.Messages.FORMAT_ERROR .. result)
end
return p