Module:CountryData: Difference between revisions
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| (11 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- | --[[ | ||
* Name: CountryData | |||
* Author: Mark W. Datysgeld | |||
* Description: Unified module for country data management with JSON loading, normalization, region mapping, and Semantic MediaWiki integration | |||
* Notes: Loads from Data:CountryDataset.json; normalizes country names to canonical forms; maps countries to ICANN regions; provides extensible property access; formats country lists with region-specific emoji styling; processes countries for category assignment | |||
]] | |||
-- Dependencies | -- Dependencies | ||
| Line 208: | Line 203: | ||
if not code then | if not code then | ||
local stripped = DiacriticNormalization.removeDiacritics(name) | local stripped = DiacriticNormalization.removeDiacritics(name) | ||
if stripped ~= name then | if stripped ~= name then | ||
code = nameLookup[NormalizationText.normalizeText(stripped)] | |||
end | end | ||
end | end | ||
| Line 324: | Line 317: | ||
table.insert(result, { | table.insert(result, { | ||
code = code, | code = code, | ||
name = country.name | name = country.name | ||
}) | }) | ||
end | end | ||
| Line 362: | Line 355: | ||
if data and data.countries then | if data and data.countries then | ||
for _, country in pairs(data.countries) do | for _, country in pairs(data.countries) do | ||
table.insert(result, country.name | table.insert(result, country.name) | ||
end | end | ||
end | end | ||
| Line 451: | Line 444: | ||
functionCache[cacheKey] = properties | functionCache[cacheKey] = properties | ||
return properties | return properties | ||
end | end | ||
| Line 471: | Line 452: | ||
end | end | ||
local countryPropertyName = | local ConfigRepository = require('Module:ConfigRepository') | ||
local regionPropertyName = | local countryPropertyName = ConfigRepository.getSemanticPropertyName("Has country") | ||
local regionPropertyName = ConfigRepository.getSemanticPropertyName("Has ICANN region") | |||
if not countryPropertyName or not regionPropertyName then | if not countryPropertyName or not regionPropertyName then | ||
| Line 486: | Line 468: | ||
end | end | ||
for _, | for _, countryName in ipairs(countries) do | ||
local normalizedCountry = CountryData.normalizeCountryName( | local normalizedCountry = CountryData.normalizeCountryName(countryName) | ||
if normalizedCountry ~= "(Unrecognized)" then | if normalizedCountry ~= "(Unrecognized)" then | ||
-- Initialize property tables if they don't exist | |||
properties[countryPropertyName] = properties[countryPropertyName] or {} | properties[countryPropertyName] = properties[countryPropertyName] or {} | ||
table.insert(properties[countryPropertyName], normalizedCountry) | table.insert(properties[countryPropertyName], normalizedCountry) | ||
local region = CountryData.getRegionByCountry( | local region = CountryData.getRegionByCountry(normalizedCountry) | ||
if region and region ~= "(Unrecognized)" then | if region and region ~= "(Unrecognized)" then | ||
properties[regionPropertyName] = properties[regionPropertyName] or {} | properties[regionPropertyName] = properties[regionPropertyName] or {} | ||
| Line 535: | Line 518: | ||
function CountryData.formatCountryList(value) | function CountryData.formatCountryList(value) | ||
if not value or value == "" then return "" end | if not value or value == "" then return "" end | ||
local | local ListGeneration = require('Module:ListGeneration') | ||
for | local itemsToProcess = {} | ||
-- First, check if the entire string is a single, valid country. | |||
-- This correctly handles names like "Trinidad and Tobago". | |||
local singleCountryName = CountryData.normalizeCountryName(value) | |||
if singleCountryName ~= "(Unrecognized)" then | |||
-- If it's a valid country, treat it as a single item. | |||
table.insert(itemsToProcess, value) | |||
else | |||
-- If not a single country, assume it's a list and split ONLY by semicolon. | |||
-- This is safer than letting ListGeneration guess the delimiter. | |||
for item in string.gmatch(value, "[^;]+") do | |||
local trimmed = item:match("^%s*(.-)%s*$") | |||
if trimmed and trimmed ~= "" then | |||
table.insert(itemsToProcess, trimmed) | |||
end | |||
end | end | ||
end | end | ||
local | -- Define the item hook for country-specific formatting | ||
local function countryItemHook(countryName) | |||
local normalized = CountryData.normalizeCountryName( | local normalized = CountryData.normalizeCountryName(countryName) | ||
if normalized ~= "(Unrecognized)" then | if normalized ~= "(Unrecognized)" then | ||
local countryRegion = CountryData.getRegionByCountry(normalized) | |||
-- Return a table with content and class for the li element | |||
return { | |||
content = normalized, | |||
class = getRegionClass(countryRegion) | |||
} | |||
end | end | ||
return nil -- Exclude unrecognized countries from the list | |||
end | end | ||
-- Set the options for the list generation | |||
local options = { | |||
mode = 'bullet', | |||
listClass = 'template-list-country', | |||
itemHook = countryItemHook | |||
} | |||
-- Pass the pre-processed table of items to the list generator. | |||
return ListGeneration.createList(itemsToProcess, options) | |||
return | |||
end | end | ||
| Line 573: | Line 572: | ||
local countries = {} | local countries = {} | ||
for | for countryName in string.gmatch(value, "[^;]+") do | ||
local trimmed = | local trimmed = countryName:match("^%s*(.-)%s*$") | ||
if trimmed and trimmed ~= "" then | if trimmed and trimmed ~= "" then | ||
table.insert(countries, | local normalized = CountryData.normalizeCountryName(trimmed) | ||
if normalized ~= "(Unrecognized)" then | |||
table.insert(countries, normalized) | |||
end | |||
end | end | ||
end | end | ||
return countries | |||
end | end | ||
| Line 595: | Line 589: | ||
local inputName = countryNameOrCode:gsub('_', ' ') | local inputName = countryNameOrCode:gsub('_', ' ') | ||
local isoCode = CountryData.getCountryCodeByName(inputName) | local isoCode | ||
-- First, try to get the ISO code by treating inputName as a country name. | |||
isoCode = CountryData.getCountryCodeByName(inputName) | |||
-- If no code was found by name, and the inputName itself is 2 characters long, | |||
-- it might be an ISO code already. Let's validate it. | |||
if not isoCode and #inputName == 2 then | if not isoCode and #inputName == 2 then | ||
if CountryData.getCountryByCode(inputName) then | if CountryData.getCountryByCode(inputName) then | ||