glam/frontend/src/utils/countryNames.ts
kempersc 0a38225b36 feat(frontend): Add multi-select filters, URL params, and UI improvements
- Institution Browser: multi-select for types and countries
- URL query param sync for shareable filter URLs
- New utility: countryNames.ts with flag emoji support
- New utility: imageProxy.ts for image URL handling
- New component: SearchableMultiSelect dropdown
- Career timeline CSS and component updates
- Media gallery improvements
- Lazy load error boundary component
- Version check utility
2025-12-15 01:47:11 +01:00

367 lines
14 KiB
TypeScript

/**
* Country Names Mapping
* ISO 3166-1 alpha-2 country codes to full names in Dutch and English
*
* Comprehensive mapping for heritage custodian data across 190+ countries
*/
export interface CountryInfo {
nl: string;
en: string;
flag?: string; // Flag emoji (generated from code)
}
// Convert ISO 3166-1 alpha-2 country code to Unicode flag emoji
export function getFlagEmoji(countryCode: string): string {
if (!countryCode || countryCode.length !== 2) return '';
const code = countryCode.toUpperCase();
const codePoints = code
.split('')
.map(char => 127397 + char.charCodeAt(0));
return String.fromCodePoint(...codePoints);
}
// Complete ISO 3166-1 alpha-2 country code to name mapping
export const COUNTRY_NAMES: Record<string, CountryInfo> = {
// A
'AD': { nl: 'Andorra', en: 'Andorra' },
'AE': { nl: 'Verenigde Arabische Emiraten', en: 'United Arab Emirates' },
'AF': { nl: 'Afghanistan', en: 'Afghanistan' },
'AG': { nl: 'Antigua en Barbuda', en: 'Antigua and Barbuda' },
'AI': { nl: 'Anguilla', en: 'Anguilla' },
'AL': { nl: 'Albanië', en: 'Albania' },
'AM': { nl: 'Armenië', en: 'Armenia' },
'AO': { nl: 'Angola', en: 'Angola' },
'AQ': { nl: 'Antarctica', en: 'Antarctica' },
'AR': { nl: 'Argentinië', en: 'Argentina' },
'AS': { nl: 'Amerikaans-Samoa', en: 'American Samoa' },
'AT': { nl: 'Oostenrijk', en: 'Austria' },
'AU': { nl: 'Australië', en: 'Australia' },
'AW': { nl: 'Aruba', en: 'Aruba' },
'AX': { nl: 'Åland', en: 'Åland Islands' },
'AZ': { nl: 'Azerbeidzjan', en: 'Azerbaijan' },
// B
'BA': { nl: 'Bosnië en Herzegovina', en: 'Bosnia and Herzegovina' },
'BB': { nl: 'Barbados', en: 'Barbados' },
'BD': { nl: 'Bangladesh', en: 'Bangladesh' },
'BE': { nl: 'België', en: 'Belgium' },
'BF': { nl: 'Burkina Faso', en: 'Burkina Faso' },
'BG': { nl: 'Bulgarije', en: 'Bulgaria' },
'BH': { nl: 'Bahrein', en: 'Bahrain' },
'BI': { nl: 'Burundi', en: 'Burundi' },
'BJ': { nl: 'Benin', en: 'Benin' },
'BL': { nl: 'Saint-Barthélemy', en: 'Saint Barthélemy' },
'BM': { nl: 'Bermuda', en: 'Bermuda' },
'BN': { nl: 'Brunei', en: 'Brunei' },
'BO': { nl: 'Bolivia', en: 'Bolivia' },
'BQ': { nl: 'Caribisch Nederland', en: 'Caribbean Netherlands' },
'BR': { nl: 'Brazilië', en: 'Brazil' },
'BS': { nl: 'Bahama\'s', en: 'Bahamas' },
'BT': { nl: 'Bhutan', en: 'Bhutan' },
'BV': { nl: 'Bouveteiland', en: 'Bouvet Island' },
'BW': { nl: 'Botswana', en: 'Botswana' },
'BY': { nl: 'Wit-Rusland', en: 'Belarus' },
'BZ': { nl: 'Belize', en: 'Belize' },
// C
'CA': { nl: 'Canada', en: 'Canada' },
'CC': { nl: 'Cocoseilanden', en: 'Cocos (Keeling) Islands' },
'CD': { nl: 'Congo-Kinshasa', en: 'DR Congo' },
'CF': { nl: 'Centraal-Afrikaanse Republiek', en: 'Central African Republic' },
'CG': { nl: 'Congo-Brazzaville', en: 'Republic of the Congo' },
'CH': { nl: 'Zwitserland', en: 'Switzerland' },
'CI': { nl: 'Ivoorkust', en: 'Ivory Coast' },
'CK': { nl: 'Cookeilanden', en: 'Cook Islands' },
'CL': { nl: 'Chili', en: 'Chile' },
'CM': { nl: 'Kameroen', en: 'Cameroon' },
'CN': { nl: 'China', en: 'China' },
'CO': { nl: 'Colombia', en: 'Colombia' },
'CR': { nl: 'Costa Rica', en: 'Costa Rica' },
'CU': { nl: 'Cuba', en: 'Cuba' },
'CV': { nl: 'Kaapverdië', en: 'Cape Verde' },
'CW': { nl: 'Curaçao', en: 'Curaçao' },
'CX': { nl: 'Christmaseiland', en: 'Christmas Island' },
'CY': { nl: 'Cyprus', en: 'Cyprus' },
'CZ': { nl: 'Tsjechië', en: 'Czechia' },
// D
'DE': { nl: 'Duitsland', en: 'Germany' },
'DJ': { nl: 'Djibouti', en: 'Djibouti' },
'DK': { nl: 'Denemarken', en: 'Denmark' },
'DM': { nl: 'Dominica', en: 'Dominica' },
'DO': { nl: 'Dominicaanse Republiek', en: 'Dominican Republic' },
'DZ': { nl: 'Algerije', en: 'Algeria' },
// E
'EC': { nl: 'Ecuador', en: 'Ecuador' },
'EE': { nl: 'Estland', en: 'Estonia' },
'EG': { nl: 'Egypte', en: 'Egypt' },
'EH': { nl: 'Westelijke Sahara', en: 'Western Sahara' },
'ER': { nl: 'Eritrea', en: 'Eritrea' },
'ES': { nl: 'Spanje', en: 'Spain' },
'ET': { nl: 'Ethiopië', en: 'Ethiopia' },
// F
'FI': { nl: 'Finland', en: 'Finland' },
'FJ': { nl: 'Fiji', en: 'Fiji' },
'FK': { nl: 'Falklandeilanden', en: 'Falkland Islands' },
'FM': { nl: 'Micronesia', en: 'Micronesia' },
'FO': { nl: 'Faeröer', en: 'Faroe Islands' },
'FR': { nl: 'Frankrijk', en: 'France' },
// G
'GA': { nl: 'Gabon', en: 'Gabon' },
'GB': { nl: 'Verenigd Koninkrijk', en: 'United Kingdom' },
'GD': { nl: 'Grenada', en: 'Grenada' },
'GE': { nl: 'Georgië', en: 'Georgia' },
'GF': { nl: 'Frans-Guyana', en: 'French Guiana' },
'GG': { nl: 'Guernsey', en: 'Guernsey' },
'GH': { nl: 'Ghana', en: 'Ghana' },
'GI': { nl: 'Gibraltar', en: 'Gibraltar' },
'GL': { nl: 'Groenland', en: 'Greenland' },
'GM': { nl: 'Gambia', en: 'Gambia' },
'GN': { nl: 'Guinee', en: 'Guinea' },
'GP': { nl: 'Guadeloupe', en: 'Guadeloupe' },
'GQ': { nl: 'Equatoriaal-Guinea', en: 'Equatorial Guinea' },
'GR': { nl: 'Griekenland', en: 'Greece' },
'GS': { nl: 'Zuid-Georgia en de Zuidelijke Sandwicheilanden', en: 'South Georgia' },
'GT': { nl: 'Guatemala', en: 'Guatemala' },
'GU': { nl: 'Guam', en: 'Guam' },
'GW': { nl: 'Guinee-Bissau', en: 'Guinea-Bissau' },
'GY': { nl: 'Guyana', en: 'Guyana' },
// H
'HK': { nl: 'Hongkong', en: 'Hong Kong' },
'HM': { nl: 'Heard en McDonaldeilanden', en: 'Heard Island and McDonald Islands' },
'HN': { nl: 'Honduras', en: 'Honduras' },
'HR': { nl: 'Kroatië', en: 'Croatia' },
'HT': { nl: 'Haïti', en: 'Haiti' },
'HU': { nl: 'Hongarije', en: 'Hungary' },
// I
'ID': { nl: 'Indonesië', en: 'Indonesia' },
'IE': { nl: 'Ierland', en: 'Ireland' },
'IL': { nl: 'Israël', en: 'Israel' },
'IM': { nl: 'Man', en: 'Isle of Man' },
'IN': { nl: 'India', en: 'India' },
'IO': { nl: 'Brits Indische Oceaanterritorium', en: 'British Indian Ocean Territory' },
'IQ': { nl: 'Irak', en: 'Iraq' },
'IR': { nl: 'Iran', en: 'Iran' },
'IS': { nl: 'IJsland', en: 'Iceland' },
'IT': { nl: 'Italië', en: 'Italy' },
// J
'JE': { nl: 'Jersey', en: 'Jersey' },
'JM': { nl: 'Jamaica', en: 'Jamaica' },
'JO': { nl: 'Jordanië', en: 'Jordan' },
'JP': { nl: 'Japan', en: 'Japan' },
// K
'KE': { nl: 'Kenia', en: 'Kenya' },
'KG': { nl: 'Kirgizië', en: 'Kyrgyzstan' },
'KH': { nl: 'Cambodja', en: 'Cambodia' },
'KI': { nl: 'Kiribati', en: 'Kiribati' },
'KM': { nl: 'Comoren', en: 'Comoros' },
'KN': { nl: 'Saint Kitts en Nevis', en: 'Saint Kitts and Nevis' },
'KP': { nl: 'Noord-Korea', en: 'North Korea' },
'KR': { nl: 'Zuid-Korea', en: 'South Korea' },
'KW': { nl: 'Koeweit', en: 'Kuwait' },
'KY': { nl: 'Kaaimaneilanden', en: 'Cayman Islands' },
'KZ': { nl: 'Kazachstan', en: 'Kazakhstan' },
// L
'LA': { nl: 'Laos', en: 'Laos' },
'LB': { nl: 'Libanon', en: 'Lebanon' },
'LC': { nl: 'Saint Lucia', en: 'Saint Lucia' },
'LI': { nl: 'Liechtenstein', en: 'Liechtenstein' },
'LK': { nl: 'Sri Lanka', en: 'Sri Lanka' },
'LR': { nl: 'Liberia', en: 'Liberia' },
'LS': { nl: 'Lesotho', en: 'Lesotho' },
'LT': { nl: 'Litouwen', en: 'Lithuania' },
'LU': { nl: 'Luxemburg', en: 'Luxembourg' },
'LV': { nl: 'Letland', en: 'Latvia' },
'LY': { nl: 'Libië', en: 'Libya' },
// M
'MA': { nl: 'Marokko', en: 'Morocco' },
'MC': { nl: 'Monaco', en: 'Monaco' },
'MD': { nl: 'Moldavië', en: 'Moldova' },
'ME': { nl: 'Montenegro', en: 'Montenegro' },
'MF': { nl: 'Sint-Maarten (Frans)', en: 'Saint Martin' },
'MG': { nl: 'Madagaskar', en: 'Madagascar' },
'MH': { nl: 'Marshalleilanden', en: 'Marshall Islands' },
'MK': { nl: 'Noord-Macedonië', en: 'North Macedonia' },
'ML': { nl: 'Mali', en: 'Mali' },
'MM': { nl: 'Myanmar', en: 'Myanmar' },
'MN': { nl: 'Mongolië', en: 'Mongolia' },
'MO': { nl: 'Macau', en: 'Macau' },
'MP': { nl: 'Noordelijke Marianen', en: 'Northern Mariana Islands' },
'MQ': { nl: 'Martinique', en: 'Martinique' },
'MR': { nl: 'Mauritanië', en: 'Mauritania' },
'MS': { nl: 'Montserrat', en: 'Montserrat' },
'MT': { nl: 'Malta', en: 'Malta' },
'MU': { nl: 'Mauritius', en: 'Mauritius' },
'MV': { nl: 'Maldiven', en: 'Maldives' },
'MW': { nl: 'Malawi', en: 'Malawi' },
'MX': { nl: 'Mexico', en: 'Mexico' },
'MY': { nl: 'Maleisië', en: 'Malaysia' },
'MZ': { nl: 'Mozambique', en: 'Mozambique' },
// N
'NA': { nl: 'Namibië', en: 'Namibia' },
'NC': { nl: 'Nieuw-Caledonië', en: 'New Caledonia' },
'NE': { nl: 'Niger', en: 'Niger' },
'NF': { nl: 'Norfolk', en: 'Norfolk Island' },
'NG': { nl: 'Nigeria', en: 'Nigeria' },
'NI': { nl: 'Nicaragua', en: 'Nicaragua' },
'NL': { nl: 'Nederland', en: 'Netherlands' },
'NO': { nl: 'Noorwegen', en: 'Norway' },
'NP': { nl: 'Nepal', en: 'Nepal' },
'NR': { nl: 'Nauru', en: 'Nauru' },
'NU': { nl: 'Niue', en: 'Niue' },
'NZ': { nl: 'Nieuw-Zeeland', en: 'New Zealand' },
// O
'OM': { nl: 'Oman', en: 'Oman' },
// P
'PA': { nl: 'Panama', en: 'Panama' },
'PE': { nl: 'Peru', en: 'Peru' },
'PF': { nl: 'Frans-Polynesië', en: 'French Polynesia' },
'PG': { nl: 'Papoea-Nieuw-Guinea', en: 'Papua New Guinea' },
'PH': { nl: 'Filipijnen', en: 'Philippines' },
'PK': { nl: 'Pakistan', en: 'Pakistan' },
'PL': { nl: 'Polen', en: 'Poland' },
'PM': { nl: 'Saint-Pierre en Miquelon', en: 'Saint Pierre and Miquelon' },
'PN': { nl: 'Pitcairneilanden', en: 'Pitcairn Islands' },
'PR': { nl: 'Puerto Rico', en: 'Puerto Rico' },
'PS': { nl: 'Palestina', en: 'Palestine' },
'PT': { nl: 'Portugal', en: 'Portugal' },
'PW': { nl: 'Palau', en: 'Palau' },
'PY': { nl: 'Paraguay', en: 'Paraguay' },
// Q
'QA': { nl: 'Qatar', en: 'Qatar' },
// R
'RE': { nl: 'Réunion', en: 'Réunion' },
'RO': { nl: 'Roemenië', en: 'Romania' },
'RS': { nl: 'Servië', en: 'Serbia' },
'RU': { nl: 'Rusland', en: 'Russia' },
'RW': { nl: 'Rwanda', en: 'Rwanda' },
// S
'SA': { nl: 'Saoedi-Arabië', en: 'Saudi Arabia' },
'SB': { nl: 'Salomonseilanden', en: 'Solomon Islands' },
'SC': { nl: 'Seychellen', en: 'Seychelles' },
'SD': { nl: 'Soedan', en: 'Sudan' },
'SE': { nl: 'Zweden', en: 'Sweden' },
'SG': { nl: 'Singapore', en: 'Singapore' },
'SH': { nl: 'Sint-Helena', en: 'Saint Helena' },
'SI': { nl: 'Slovenië', en: 'Slovenia' },
'SJ': { nl: 'Spitsbergen en Jan Mayen', en: 'Svalbard and Jan Mayen' },
'SK': { nl: 'Slowakije', en: 'Slovakia' },
'SL': { nl: 'Sierra Leone', en: 'Sierra Leone' },
'SM': { nl: 'San Marino', en: 'San Marino' },
'SN': { nl: 'Senegal', en: 'Senegal' },
'SO': { nl: 'Somalië', en: 'Somalia' },
'SR': { nl: 'Suriname', en: 'Suriname' },
'SS': { nl: 'Zuid-Soedan', en: 'South Sudan' },
'ST': { nl: 'Sao Tomé en Principe', en: 'São Tomé and Príncipe' },
'SV': { nl: 'El Salvador', en: 'El Salvador' },
'SX': { nl: 'Sint Maarten', en: 'Sint Maarten' },
'SY': { nl: 'Syrië', en: 'Syria' },
'SZ': { nl: 'Eswatini', en: 'Eswatini' },
// T
'TC': { nl: 'Turks- en Caicoseilanden', en: 'Turks and Caicos Islands' },
'TD': { nl: 'Tsjaad', en: 'Chad' },
'TF': { nl: 'Franse Zuidelijke Gebieden', en: 'French Southern Territories' },
'TG': { nl: 'Togo', en: 'Togo' },
'TH': { nl: 'Thailand', en: 'Thailand' },
'TJ': { nl: 'Tadzjikistan', en: 'Tajikistan' },
'TK': { nl: 'Tokelau', en: 'Tokelau' },
'TL': { nl: 'Oost-Timor', en: 'Timor-Leste' },
'TM': { nl: 'Turkmenistan', en: 'Turkmenistan' },
'TN': { nl: 'Tunesië', en: 'Tunisia' },
'TO': { nl: 'Tonga', en: 'Tonga' },
'TR': { nl: 'Turkije', en: 'Turkey' },
'TT': { nl: 'Trinidad en Tobago', en: 'Trinidad and Tobago' },
'TV': { nl: 'Tuvalu', en: 'Tuvalu' },
'TW': { nl: 'Taiwan', en: 'Taiwan' },
'TZ': { nl: 'Tanzania', en: 'Tanzania' },
// U
'UA': { nl: 'Oekraïne', en: 'Ukraine' },
'UG': { nl: 'Oeganda', en: 'Uganda' },
'UM': { nl: 'Kleine afgelegen eilanden van de VS', en: 'U.S. Minor Outlying Islands' },
'US': { nl: 'Verenigde Staten', en: 'United States' },
'UY': { nl: 'Uruguay', en: 'Uruguay' },
'UZ': { nl: 'Oezbekistan', en: 'Uzbekistan' },
// V
'VA': { nl: 'Vaticaanstad', en: 'Vatican City' },
'VC': { nl: 'Saint Vincent en de Grenadines', en: 'Saint Vincent and the Grenadines' },
'VE': { nl: 'Venezuela', en: 'Venezuela' },
'VG': { nl: 'Britse Maagdeneilanden', en: 'British Virgin Islands' },
'VI': { nl: 'Amerikaanse Maagdeneilanden', en: 'U.S. Virgin Islands' },
'VN': { nl: 'Vietnam', en: 'Vietnam' },
'VU': { nl: 'Vanuatu', en: 'Vanuatu' },
// W
'WF': { nl: 'Wallis en Futuna', en: 'Wallis and Futuna' },
'WS': { nl: 'Samoa', en: 'Samoa' },
// X - User-assigned codes (for special entities)
'XK': { nl: 'Kosovo', en: 'Kosovo' },
// Y
'YE': { nl: 'Jemen', en: 'Yemen' },
'YT': { nl: 'Mayotte', en: 'Mayotte' },
// Z
'ZA': { nl: 'Zuid-Afrika', en: 'South Africa' },
'ZM': { nl: 'Zambia', en: 'Zambia' },
'ZW': { nl: 'Zimbabwe', en: 'Zimbabwe' },
};
/**
* Get the country name with flag emoji for display
* @param code ISO 3166-1 alpha-2 country code
* @param language 'nl' or 'en'
* @returns Formatted string like "🇳🇱 Nederland" or the code if not found
*/
export function getCountryLabel(code: string, language: 'nl' | 'en' = 'en'): string {
const upperCode = code.toUpperCase();
const country = COUNTRY_NAMES[upperCode];
const flag = getFlagEmoji(upperCode);
if (country) {
return `${flag} ${country[language]}`.trim();
}
// Fallback: return code with flag if possible
return flag ? `${flag} ${upperCode}` : upperCode;
}
/**
* Get just the country name without flag
* @param code ISO 3166-1 alpha-2 country code
* @param language 'nl' or 'en'
* @returns Country name or the code if not found
*/
export function getCountryName(code: string, language: 'nl' | 'en' = 'en'): string {
const upperCode = code.toUpperCase();
const country = COUNTRY_NAMES[upperCode];
return country ? country[language] : upperCode;
}
/**
* Check if a country code is valid (exists in our mapping)
* @param code ISO 3166-1 alpha-2 country code
* @returns boolean
*/
export function isValidCountryCode(code: string): boolean {
return code.toUpperCase() in COUNTRY_NAMES;
}