mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-29 16:28:13 +00:00
feat: add country selection translations and update country name retrieval
This commit is contained in:
@@ -1,65 +1,24 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Group, Select, Text, type ComboboxItem, type SelectProps } from '@mantine/core';
|
||||
import { getData, getName, overwrite } from 'country-list';
|
||||
import { registerLocale, getNames, getName } from 'i18n-iso-countries';
|
||||
import * as Flags from 'country-flag-icons/react/3x2';
|
||||
import en from 'i18n-iso-countries/langs/en.json';
|
||||
import am from 'i18n-iso-countries/langs/am.json';
|
||||
|
||||
// country-list ships raw ISO 3166 register names, which invert qualifiers into
|
||||
// a trailing "(the)" / "(Qualifier of)" suffix — e.g. "Iran (Islamic Republic of)".
|
||||
// Reorder every such entry into natural reading order ("Islamic Republic of Iran").
|
||||
// Full list + codes still come from country-list; this only rewrites display text.
|
||||
overwrite([
|
||||
{ code: 'AE', name: 'United Arab Emirates' },
|
||||
{ code: 'BO', name: 'Plurinational State of Bolivia' },
|
||||
{ code: 'BS', name: 'Bahamas' },
|
||||
{ code: 'CC', name: 'Cocos (Keeling) Islands' },
|
||||
{ code: 'CD', name: 'Democratic Republic of the Congo' },
|
||||
{ code: 'CF', name: 'Central African Republic' },
|
||||
{ code: 'CG', name: 'Congo' },
|
||||
{ code: 'CK', name: 'Cook Islands' },
|
||||
{ code: 'DO', name: 'Dominican Republic' },
|
||||
{ code: 'FK', name: 'Falkland Islands (Malvinas)' },
|
||||
{ code: 'FM', name: 'Federated States of Micronesia' },
|
||||
{ code: 'FO', name: 'Faroe Islands' },
|
||||
{ code: 'GB', name: 'United Kingdom of Great Britain and Northern Ireland' },
|
||||
{ code: 'GM', name: 'Gambia' },
|
||||
{ code: 'IO', name: 'British Indian Ocean Territory' },
|
||||
{ code: 'IR', name: 'Islamic Republic of Iran' },
|
||||
{ code: 'KM', name: 'Comoros' },
|
||||
{ code: 'KP', name: "Democratic People's Republic of Korea" },
|
||||
{ code: 'KR', name: 'Republic of Korea' },
|
||||
{ code: 'KY', name: 'Cayman Islands' },
|
||||
{ code: 'LA', name: "Lao People's Democratic Republic" },
|
||||
{ code: 'MD', name: 'Republic of Moldova' },
|
||||
{ code: 'MF', name: 'Saint Martin' },
|
||||
{ code: 'MH', name: 'Marshall Islands' },
|
||||
{ code: 'MP', name: 'Northern Mariana Islands' },
|
||||
{ code: 'NE', name: 'Niger' },
|
||||
{ code: 'NL', name: 'Kingdom of the Netherlands' },
|
||||
{ code: 'PH', name: 'Philippines' },
|
||||
{ code: 'PS', name: 'State of Palestine' },
|
||||
{ code: 'RU', name: 'Russian Federation' },
|
||||
{ code: 'SD', name: 'Sudan' },
|
||||
{ code: 'SX', name: 'Sint Maarten' },
|
||||
{ code: 'SY', name: 'Syrian Arab Republic' },
|
||||
{ code: 'TC', name: 'Turks and Caicos Islands' },
|
||||
{ code: 'TF', name: 'French Southern Territories' },
|
||||
{ code: 'TW', name: 'Taiwan' },
|
||||
{ code: 'TZ', name: 'United Republic of Tanzania' },
|
||||
{ code: 'UM', name: 'United States Minor Outlying Islands' },
|
||||
{ code: 'US', name: 'United States of America' },
|
||||
{ code: 'VA', name: 'Holy See' },
|
||||
{ code: 'VE', name: 'Bolivarian Republic of Venezuela' },
|
||||
{ code: 'VG', name: 'British Virgin Islands' },
|
||||
{ code: 'VI', name: 'United States Virgin Islands' },
|
||||
]);
|
||||
// Registered once at module load — locale data is static.
|
||||
registerLocale(en);
|
||||
registerLocale(am);
|
||||
|
||||
// Built once at module load — static data, no hook memoization needed.
|
||||
const COUNTRIES = getData()
|
||||
.map(({ code, name }) => ({ value: code, label: name }))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
type CountryLang = 'en' | 'am';
|
||||
|
||||
/** English country name for an alpha-2 code; '' when unset/unknown. */
|
||||
export function getCountryName(code: string | null | undefined): string {
|
||||
return code ? (getName(code) ?? '') : '';
|
||||
function resolveLang(lng: string): CountryLang {
|
||||
return lng === 'am' ? 'am' : 'en';
|
||||
}
|
||||
|
||||
/** Localized country name for an alpha-2 code; '' when unset/unknown. */
|
||||
export function getCountryName(code: string | null | undefined, lang: CountryLang = 'en'): string {
|
||||
return code ? (getName(code, lang) ?? '') : '';
|
||||
}
|
||||
|
||||
function CountryFlag({ code }: { code: string }) {
|
||||
@@ -98,19 +57,30 @@ export interface CountrySelectProps {
|
||||
export function CountrySelect({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = 'Select a country',
|
||||
placeholder,
|
||||
...rest
|
||||
}: CountrySelectProps) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const lang = resolveLang(i18n.language);
|
||||
|
||||
const countries = useMemo(
|
||||
() =>
|
||||
Object.entries(getNames(lang))
|
||||
.map(([code, label]) => ({ value: code, label }))
|
||||
.sort((a, b) => a.label.localeCompare(b.label, lang)),
|
||||
[lang],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select
|
||||
data={COUNTRIES}
|
||||
data={countries}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
placeholder={placeholder ?? t('country.select')}
|
||||
leftSection={value ? <CountryFlag code={value} /> : undefined}
|
||||
renderOption={renderCountryOption}
|
||||
filter={filterCountries}
|
||||
nothingFoundMessage="No countries found"
|
||||
nothingFoundMessage={t('country.notFound')}
|
||||
searchable
|
||||
clearable
|
||||
maxDropdownHeight={320}
|
||||
|
||||
Reference in New Issue
Block a user