diff --git a/.github/workflows/update-data.yaml b/.github/workflows/update-data.yaml index 7ceee9f7..e9324378 100644 --- a/.github/workflows/update-data.yaml +++ b/.github/workflows/update-data.yaml @@ -204,7 +204,7 @@ jobs: - name: Build tlds.json if: steps.source-check.outputs.source_changed == 'true' id: build - run: ./bin/build + run: ./bin/build --all - name: Notification if build fails if: failure() && steps.build.outcome == 'failure' diff --git a/Makefile b/Makefile index 5156c0c2..4000f92a 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,8 @@ help: @echo " bin/setup Install dependencies (uv sync, pnpm install)" @echo " bin/lint Run ruff check, ruff format check, pyright" @echo " bin/test Run lint then pytest" - @echo " bin/build Build output files (--preserve-asn skips the iptoasn refresh)" + @echo " bin/build --preserve-asn Build, keeping committed ASN (local/dev; no iptoasn refresh)" + @echo " bin/build --all Full build, refreshing ASN from iptoasn (CI)" @echo " bin/fetch-coordinates Fetch geo-place lat/lon from Wikidata (--refresh to redo)" .PHONY: download-core diff --git a/README.md b/README.md index 27477cac..144cfdda 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ Alongside `tlds.json`, the build ships four derived reverse-index artifacts that - **Cultures**: ethno-linguistic communities like the Basques or Welsh (`cultures.json`). - **Agreement types**: the ICANN registry-agreement enum (`agreements.json`). -Each TLD relates to one or more Organizations through *roles* (Sponsor, Administrative Contact, Technical Contact, and ICANN Registry Operator for gTLDs), to zero or more Places (most ccTLDs map to one country; geographic gTLDs map to a city, subdivision, country, or supranational region), to an optional Culture, and to its agreement types. Each derived artifact is a deterministic reverse index of `tlds.json`: delete it and `./bin/build` rebuilds it. Every cross-file relationship is enforced by referential-integrity tests, so a foreign key can never dangle and no record is ever orphaned. +Each TLD relates to one or more Organizations through *roles* (Sponsor, Administrative Contact, Technical Contact, and ICANN Registry Operator for gTLDs), to zero or more Places (most ccTLDs map to one country; geographic gTLDs map to a city, subdivision, country, or supranational region), to an optional Culture, and to its agreement types. Each derived artifact is a deterministic reverse index of `tlds.json`: delete it and `./bin/build --preserve-asn` rebuilds it. Every cross-file relationship is enforced by referential-integrity tests, so a foreign key can never dangle and no record is ever orphaned. ## `organizations.json` diff --git a/bin/build b/bin/build index 0b7ebed1..786cd6e4 100755 --- a/bin/build +++ b/bin/build @@ -2,7 +2,37 @@ set -euo pipefail cd "$(dirname "$0")/.." -# Build all generated data files (regenerates the IDN script mapping first). -# Pass --preserve-asn to keep committed ASN and skip the local iptoasn file. +usage() { + cat <<'EOF' +Usage: bin/build + +Regenerates the data/generated artifacts. A mode is required on purpose: a bare +`bin/build` must never silently refresh ASN from a stale local iptoasn snapshot. + +Modes: + --preserve-asn Build, keeping the ASN already in the committed tlds.json + (skips the local iptoasn file). Use for local/dev builds so an + unrelated data change does not churn ASN. + --all Full build, refreshing ASN from the local iptoasn file. + Used by CI and the data-update workflow. + -h, --help Show this help. +EOF +} + +case "${1:-}" in + --preserve-asn) cli_args=(--build --preserve-asn) ;; + --all) cli_args=(--build) ;; + -h | --help | "") + usage + exit 0 + ;; + *) + printf 'bin/build: unknown option %s\n\n' "$1" >&2 + usage + exit 2 + ;; +esac + +# Regenerate the IDN script mapping, then build. uv run python scripts/idn_unicode_scripts/generate_idn_script_mapping.py -uv run python -m src.cli --build "$@" +uv run python -m src.cli "${cli_args[@]}" diff --git a/data/generated/places.json b/data/generated/places.json index c169a897..84ff8e8a 100644 --- a/data/generated/places.json +++ b/data/generated/places.json @@ -1,753 +1,769 @@ { "description": "Places associated with TLDs in the IANA root zone (countries, dependent territories, subdivisions, cities, and supranational regions), each with a reverse index of its TLDs. Country slugs are ISO 3166-1 alpha-2.", - "publication": "2026-05-30T02:19:01Z", + "publication": "2026-05-30T15:48:01Z", "sources": [ "pycountry (ISO 3166-1 / 3166-2)", "data/manual/places.json (editorial)", - "data/manual/dependent-territories.json (editorial; ISO 3166-1)" + "data/manual/dependent-territories.json (editorial; ISO 3166-1)", + "data/manual/country-coordinates.json (editorial; point overlay)" ], "places": [ { - "slug": "abudhabi", - "name_en": "Abu Dhabi", - "subtype": "city", + "coordinates": { + "lat": 24.45111, + "lon": 54.39694 + }, + "info_link": "https://en.wikipedia.org/wiki/Abu_Dhabi", "iso_code": null, + "name_en": "Abu Dhabi", "parent": "ae", - "info_link": "https://en.wikipedia.org/wiki/Abu_Dhabi", + "slug": "abudhabi", + "subtype": "city", "tlds": [ "abudhabi", "xn--mgbca7dzdo" - ], - "coordinates": { - "lat": 24.45111, - "lon": 54.39694 - } + ] }, { - "slug": "ac", - "name_en": "Ascension Island", - "subtype": "country", + "coordinates": { + "lat": -7.95, + "lon": -14.35 + }, + "info_link": "https://en.wikipedia.org/wiki/Ascension_Island", "iso_code": null, + "iso_designation": "exceptionally_reserved", "iso_numeric": null, + "name_en": "Ascension Island", "parent": "sh", + "slug": "ac", + "subtype": "country", "tlds": [ "ac" - ], - "iso_designation": "exceptionally_reserved" + ] }, { - "slug": "ad", - "name_en": "Andorra", - "subtype": "country", "iso_code": "AD", "iso_numeric": "020", + "name_en": "Andorra", "parent": null, + "slug": "ad", + "subtype": "country", "tlds": [ "ad" ] }, { - "slug": "ae", - "name_en": "United Arab Emirates", - "subtype": "country", "iso_code": "AE", "iso_numeric": "784", + "name_en": "United Arab Emirates", "parent": null, + "slug": "ae", + "subtype": "country", "tlds": [ "ae", "xn--mgbaam7a8h" ] }, { - "slug": "af", - "name_en": "Afghanistan", - "subtype": "country", "iso_code": "AF", "iso_numeric": "004", + "name_en": "Afghanistan", "parent": null, + "slug": "af", + "subtype": "country", "tlds": [ "af" ] }, { - "slug": "africa", - "name_en": "Africa", - "subtype": "supranational", + "coordinates": { + "lat": 21.09375, + "lon": 7.1881 + }, + "info_link": "https://en.wikipedia.org/wiki/Africa", "iso_code": null, + "name_en": "Africa", "parent": null, - "info_link": "https://en.wikipedia.org/wiki/Africa", + "slug": "africa", + "subtype": "supranational", "tlds": [ "africa" - ], - "coordinates": { - "lat": 21.09375, - "lon": 7.1881 - } + ] }, { - "slug": "ag", - "name_en": "Antigua and Barbuda", - "subtype": "country", "iso_code": "AG", "iso_numeric": "028", + "name_en": "Antigua and Barbuda", "parent": null, + "slug": "ag", + "subtype": "country", "tlds": [ "ag" ] }, { - "slug": "ai", - "name_en": "Anguilla", - "subtype": "country", "iso_code": "AI", + "iso_designation": "dependent_territory", "iso_numeric": "660", + "name_en": "Anguilla", "parent": "gb", + "slug": "ai", + "subtype": "country", "tlds": [ "ai" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "al", - "name_en": "Albania", - "subtype": "country", "iso_code": "AL", "iso_numeric": "008", + "name_en": "Albania", "parent": null, + "slug": "al", + "subtype": "country", "tlds": [ "al" ] }, { - "slug": "alsace", - "name_en": "Alsace", - "subtype": "subdivision", + "coordinates": { + "lat": 48.5, + "lon": 7.5 + }, + "info_link": "https://en.wikipedia.org/wiki/Alsace", "iso_code": null, + "name_en": "Alsace", "parent": "fr", - "info_link": "https://en.wikipedia.org/wiki/Alsace", + "slug": "alsace", + "subtype": "subdivision", "tlds": [ "alsace" - ], - "coordinates": { - "lat": 48.5, - "lon": 7.5 - } + ] }, { - "slug": "am", - "name_en": "Armenia", - "subtype": "country", "iso_code": "AM", "iso_numeric": "051", + "name_en": "Armenia", "parent": null, + "slug": "am", + "subtype": "country", "tlds": [ "am", "xn--y9a3aq" ] }, { - "slug": "amsterdam", - "name_en": "Amsterdam", - "subtype": "city", + "coordinates": { + "lat": 52.36667, + "lon": 4.88333 + }, + "info_link": "https://en.wikipedia.org/wiki/Amsterdam", "iso_code": null, + "name_en": "Amsterdam", "parent": "nl", - "info_link": "https://en.wikipedia.org/wiki/Amsterdam", + "slug": "amsterdam", + "subtype": "city", "tlds": [ "amsterdam" - ], - "coordinates": { - "lat": 52.36667, - "lon": 4.88333 - } + ] }, { - "slug": "ao", - "name_en": "Angola", - "subtype": "country", "iso_code": "AO", "iso_numeric": "024", + "name_en": "Angola", "parent": null, + "slug": "ao", + "subtype": "country", "tlds": [ "ao" ] }, { - "slug": "aq", - "name_en": "Antarctica", - "subtype": "country", "iso_code": "AQ", + "iso_designation": "special_area", "iso_numeric": "010", + "name_en": "Antarctica", "parent": null, + "slug": "aq", + "subtype": "country", "tlds": [ "aq" - ], - "iso_designation": "special_area" + ] }, { - "slug": "ar", - "name_en": "Argentina", - "subtype": "country", "iso_code": "AR", "iso_numeric": "032", + "name_en": "Argentina", "parent": null, + "slug": "ar", + "subtype": "country", "tlds": [ "ar" ] }, { - "slug": "as", - "name_en": "American Samoa", - "subtype": "country", "iso_code": "AS", + "iso_designation": "dependent_territory", "iso_numeric": "016", + "name_en": "American Samoa", "parent": "us", + "slug": "as", + "subtype": "country", "tlds": [ "as" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "asia", - "name_en": "Asia", - "subtype": "supranational", + "coordinates": { + "lat": 43.68111, + "lon": 87.33111 + }, + "info_link": "https://en.wikipedia.org/wiki/Asia", "iso_code": null, + "name_en": "Asia", "parent": null, - "info_link": "https://en.wikipedia.org/wiki/Asia", + "slug": "asia", + "subtype": "supranational", "tlds": [ "asia" - ], - "coordinates": { - "lat": 43.68111, - "lon": 87.33111 - } + ] }, { - "slug": "at", - "name_en": "Austria", - "subtype": "country", "iso_code": "AT", "iso_numeric": "040", + "name_en": "Austria", "parent": null, + "slug": "at", + "subtype": "country", "tlds": [ "at" ] }, { - "slug": "au", - "name_en": "Australia", - "subtype": "country", "iso_code": "AU", "iso_numeric": "036", + "name_en": "Australia", "parent": null, + "slug": "au", + "subtype": "country", "tlds": [ "au" ] }, { - "slug": "aw", - "name_en": "Aruba", - "subtype": "country", "iso_code": "AW", + "iso_designation": "dependent_territory", "iso_numeric": "533", + "name_en": "Aruba", "parent": "nl", + "slug": "aw", + "subtype": "country", "tlds": [ "aw" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "ax", - "name_en": "Åland Islands", - "subtype": "country", "iso_code": "AX", + "iso_designation": "dependent_territory", "iso_numeric": "248", + "name_en": "Åland Islands", "parent": "fi", + "slug": "ax", + "subtype": "country", "tlds": [ "ax" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "az", - "name_en": "Azerbaijan", - "subtype": "country", "iso_code": "AZ", "iso_numeric": "031", + "name_en": "Azerbaijan", "parent": null, + "slug": "az", + "subtype": "country", "tlds": [ "az" ] }, { - "slug": "ba", - "name_en": "Bosnia and Herzegovina", - "subtype": "country", "iso_code": "BA", "iso_numeric": "070", + "name_en": "Bosnia and Herzegovina", "parent": null, + "slug": "ba", + "subtype": "country", "tlds": [ "ba" ] }, { - "slug": "barcelona", - "name_en": "Barcelona", - "subtype": "city", + "coordinates": { + "lat": 41.3825, + "lon": 2.17694 + }, + "info_link": "https://en.wikipedia.org/wiki/Barcelona", "iso_code": null, + "name_en": "Barcelona", "parent": "es", - "info_link": "https://en.wikipedia.org/wiki/Barcelona", + "slug": "barcelona", + "subtype": "city", "tlds": [ "barcelona", "bcn" - ], - "coordinates": { - "lat": 41.3825, - "lon": 2.17694 - } + ] }, { - "slug": "basque-country", - "name_en": "Basque Country", - "subtype": "subdivision", + "coordinates": { + "lat": 42.98333, + "lon": -2.61667 + }, + "info_link": "https://en.wikipedia.org/wiki/Basque_Country_(autonomous_community)", "iso_code": "ES-PV", + "name_en": "Basque Country", "parent": "es", - "info_link": "https://en.wikipedia.org/wiki/Basque_Country_(autonomous_community)", + "slug": "basque-country", + "subtype": "subdivision", "tlds": [ "eus" - ], - "coordinates": { - "lat": 42.98333, - "lon": -2.61667 - } + ] }, { - "slug": "bayern", - "name_en": "Bavaria", - "subtype": "subdivision", + "coordinates": { + "lat": 49.07861, + "lon": 11.38556 + }, + "info_link": "https://en.wikipedia.org/wiki/Bavaria", "iso_code": "DE-BY", + "name_en": "Bavaria", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Bavaria", + "slug": "bayern", + "subtype": "subdivision", "tlds": [ "bayern" - ], - "coordinates": { - "lat": 49.07861, - "lon": 11.38556 - } + ] }, { - "slug": "bb", - "name_en": "Barbados", - "subtype": "country", "iso_code": "BB", "iso_numeric": "052", + "name_en": "Barbados", "parent": null, + "slug": "bb", + "subtype": "country", "tlds": [ "bb" ] }, { - "slug": "bd", - "name_en": "Bangladesh", - "subtype": "country", "iso_code": "BD", "iso_numeric": "050", + "name_en": "Bangladesh", "parent": null, + "slug": "bd", + "subtype": "country", "tlds": [ "bd", "xn--54b7fta0cc" ] }, { - "slug": "be", - "name_en": "Belgium", - "subtype": "country", "iso_code": "BE", "iso_numeric": "056", + "name_en": "Belgium", "parent": null, + "slug": "be", + "subtype": "country", "tlds": [ "be" ] }, { - "slug": "berlin", - "name_en": "Berlin", - "subtype": "city", + "coordinates": { + "lat": 52.51667, + "lon": 13.38333 + }, + "info_link": "https://en.wikipedia.org/wiki/Berlin", "iso_code": null, + "name_en": "Berlin", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Berlin", + "slug": "berlin", + "subtype": "city", "tlds": [ "berlin" - ], - "coordinates": { - "lat": 52.51667, - "lon": 13.38333 - } + ] }, { - "slug": "bf", - "name_en": "Burkina Faso", - "subtype": "country", "iso_code": "BF", "iso_numeric": "854", + "name_en": "Burkina Faso", "parent": null, + "slug": "bf", + "subtype": "country", "tlds": [ "bf" ] }, { - "slug": "bg", - "name_en": "Bulgaria", - "subtype": "country", "iso_code": "BG", "iso_numeric": "100", + "name_en": "Bulgaria", "parent": null, + "slug": "bg", + "subtype": "country", "tlds": [ "bg", "xn--90ae" ] }, { - "slug": "bh", - "name_en": "Bahrain", - "subtype": "country", "iso_code": "BH", "iso_numeric": "048", + "name_en": "Bahrain", "parent": null, + "slug": "bh", + "subtype": "country", "tlds": [ "bh", "xn--mgbcpq6gpa1a" ] }, { - "slug": "bi", - "name_en": "Burundi", - "subtype": "country", "iso_code": "BI", "iso_numeric": "108", + "name_en": "Burundi", "parent": null, + "slug": "bi", + "subtype": "country", "tlds": [ "bi" ] }, { - "slug": "bj", - "name_en": "Benin", - "subtype": "country", "iso_code": "BJ", "iso_numeric": "204", + "name_en": "Benin", "parent": null, + "slug": "bj", + "subtype": "country", "tlds": [ "bj" ] }, { - "slug": "bm", - "name_en": "Bermuda", - "subtype": "country", "iso_code": "BM", + "iso_designation": "dependent_territory", "iso_numeric": "060", + "name_en": "Bermuda", "parent": "gb", + "slug": "bm", + "subtype": "country", "tlds": [ "bm" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "bn", - "name_en": "Brunei Darussalam", - "subtype": "country", "iso_code": "BN", "iso_numeric": "096", + "name_en": "Brunei Darussalam", "parent": null, + "slug": "bn", + "subtype": "country", "tlds": [ "bn" ] }, { - "slug": "bo", - "name_en": "Bolivia, Plurinational State of", - "subtype": "country", "iso_code": "BO", "iso_numeric": "068", + "name_en": "Bolivia, Plurinational State of", "parent": null, + "slug": "bo", + "subtype": "country", "tlds": [ "bo" ] }, { - "slug": "boston", - "name_en": "Boston", - "subtype": "city", + "coordinates": { + "lat": 42.36028, + "lon": -71.05778 + }, + "info_link": "https://en.wikipedia.org/wiki/Boston", "iso_code": null, + "name_en": "Boston", "parent": "us", - "info_link": "https://en.wikipedia.org/wiki/Boston", + "slug": "boston", + "subtype": "city", "tlds": [ "boston" - ], - "coordinates": { - "lat": 42.36028, - "lon": -71.05778 - } + ] }, { - "slug": "br", - "name_en": "Brazil", - "subtype": "country", "iso_code": "BR", "iso_numeric": "076", + "name_en": "Brazil", "parent": null, + "slug": "br", + "subtype": "country", "tlds": [ "br" ] }, { - "slug": "brittany", - "name_en": "Brittany", - "subtype": "subdivision", + "coordinates": { + "lat": 48.0, + "lon": -3.0 + }, + "info_link": "https://en.wikipedia.org/wiki/Brittany", "iso_code": "FR-BRE", + "name_en": "Brittany", "parent": "fr", - "info_link": "https://en.wikipedia.org/wiki/Brittany", + "slug": "brittany", + "subtype": "subdivision", "tlds": [ "bzh" - ], - "coordinates": { - "lat": 48.0, - "lon": -3.0 - } + ] }, { - "slug": "brussels", - "name_en": "Brussels", - "subtype": "city", + "coordinates": { + "lat": 50.84667, + "lon": 4.3525 + }, + "info_link": "https://en.wikipedia.org/wiki/Brussels", "iso_code": null, + "name_en": "Brussels", "parent": "be", - "info_link": "https://en.wikipedia.org/wiki/Brussels", + "slug": "brussels", + "subtype": "city", "tlds": [ "brussels" - ], - "coordinates": { - "lat": 50.84667, - "lon": 4.3525 - } + ] }, { - "slug": "bs", - "name_en": "Bahamas", - "subtype": "country", "iso_code": "BS", "iso_numeric": "044", + "name_en": "Bahamas", "parent": null, + "slug": "bs", + "subtype": "country", "tlds": [ "bs" ] }, { - "slug": "bt", - "name_en": "Bhutan", - "subtype": "country", "iso_code": "BT", "iso_numeric": "064", + "name_en": "Bhutan", "parent": null, + "slug": "bt", + "subtype": "country", "tlds": [ "bt" ] }, { - "slug": "bv", - "name_en": "Bouvet Island", - "subtype": "country", + "coordinates": { + "lat": -54.42, + "lon": 3.36 + }, + "info_link": "https://en.wikipedia.org/wiki/Bouvet_Island", "iso_code": "BV", + "iso_designation": "dependent_territory", "iso_numeric": "074", + "name_en": "Bouvet Island", "parent": "no", + "slug": "bv", + "subtype": "country", "tlds": [ "bv" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "bw", - "name_en": "Botswana", - "subtype": "country", "iso_code": "BW", "iso_numeric": "072", + "name_en": "Botswana", "parent": null, + "slug": "bw", + "subtype": "country", "tlds": [ "bw" ] }, { - "slug": "by", - "name_en": "Belarus", - "subtype": "country", "iso_code": "BY", "iso_numeric": "112", + "name_en": "Belarus", "parent": null, + "slug": "by", + "subtype": "country", "tlds": [ "by", "xn--90ais" ] }, { - "slug": "bz", - "name_en": "Belize", - "subtype": "country", "iso_code": "BZ", "iso_numeric": "084", + "name_en": "Belize", "parent": null, + "slug": "bz", + "subtype": "country", "tlds": [ "bz" ] }, { - "slug": "ca", - "name_en": "Canada", - "subtype": "country", "iso_code": "CA", "iso_numeric": "124", + "name_en": "Canada", "parent": null, + "slug": "ca", + "subtype": "country", "tlds": [ "ca" ] }, { - "slug": "capetown", - "name_en": "Cape Town", - "subtype": "city", + "coordinates": { + "lat": -33.92528, + "lon": 18.42389 + }, + "info_link": "https://en.wikipedia.org/wiki/Cape_Town", "iso_code": null, + "name_en": "Cape Town", "parent": "za", - "info_link": "https://en.wikipedia.org/wiki/Cape_Town", + "slug": "capetown", + "subtype": "city", "tlds": [ "capetown" - ], - "coordinates": { - "lat": -33.92528, - "lon": 18.42389 - } + ] }, { - "slug": "catalonia", - "name_en": "Catalonia", - "subtype": "subdivision", + "coordinates": { + "lat": 41.85, + "lon": 1.56667 + }, + "info_link": "https://en.wikipedia.org/wiki/Catalonia", "iso_code": "ES-CT", + "name_en": "Catalonia", "parent": "es", - "info_link": "https://en.wikipedia.org/wiki/Catalonia", + "slug": "catalonia", + "subtype": "subdivision", "tlds": [ "cat" - ], - "coordinates": { - "lat": 41.85, - "lon": 1.56667 - } + ] }, { - "slug": "cc", - "name_en": "Cocos (Keeling) Islands", - "subtype": "country", + "coordinates": { + "lat": -12.1175, + "lon": 96.895 + }, + "info_link": "https://en.wikipedia.org/wiki/Cocos_(Keeling)_Islands", "iso_code": "CC", + "iso_designation": "dependent_territory", "iso_numeric": "166", + "name_en": "Cocos (Keeling) Islands", "parent": "au", + "slug": "cc", + "subtype": "country", "tlds": [ "cc" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "cd", - "name_en": "Congo, The Democratic Republic of the", - "subtype": "country", "iso_code": "CD", "iso_numeric": "180", + "name_en": "Congo, The Democratic Republic of the", "parent": null, + "slug": "cd", + "subtype": "country", "tlds": [ "cd" ] }, { - "slug": "cf", - "name_en": "Central African Republic", - "subtype": "country", "iso_code": "CF", "iso_numeric": "140", + "name_en": "Central African Republic", "parent": null, + "slug": "cf", + "subtype": "country", "tlds": [ "cf" ] }, { - "slug": "cg", - "name_en": "Congo", - "subtype": "country", "iso_code": "CG", "iso_numeric": "178", + "name_en": "Congo", "parent": null, + "slug": "cg", + "subtype": "country", "tlds": [ "cg" ] }, { - "slug": "ch", - "name_en": "Switzerland", - "subtype": "country", "iso_code": "CH", "iso_numeric": "756", + "name_en": "Switzerland", "parent": null, + "slug": "ch", + "subtype": "country", "tlds": [ "ch" ] }, { - "slug": "ci", - "name_en": "Côte d'Ivoire", - "subtype": "country", "iso_code": "CI", "iso_numeric": "384", + "name_en": "Côte d'Ivoire", "parent": null, + "slug": "ci", + "subtype": "country", "tlds": [ "ci" ] }, { - "slug": "ck", - "name_en": "Cook Islands", - "subtype": "country", "iso_code": "CK", + "iso_designation": "dependent_territory", "iso_numeric": "184", + "name_en": "Cook Islands", "parent": "nz", + "slug": "ck", + "subtype": "country", "tlds": [ "ck" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "cl", - "name_en": "Chile", - "subtype": "country", "iso_code": "CL", "iso_numeric": "152", + "name_en": "Chile", "parent": null, + "slug": "cl", + "subtype": "country", "tlds": [ "cl" ] }, { - "slug": "cm", - "name_en": "Cameroon", - "subtype": "country", "iso_code": "CM", "iso_numeric": "120", + "name_en": "Cameroon", "parent": null, + "slug": "cm", + "subtype": "country", "tlds": [ "cm" ] }, { - "slug": "cn", - "name_en": "China", - "subtype": "country", "iso_code": "CN", "iso_numeric": "156", + "name_en": "China", "parent": null, + "slug": "cn", + "subtype": "country", "tlds": [ "cn", "xn--fiqs8s", @@ -755,806 +771,826 @@ ] }, { - "slug": "co", - "name_en": "Colombia", - "subtype": "country", "iso_code": "CO", "iso_numeric": "170", + "name_en": "Colombia", "parent": null, + "slug": "co", + "subtype": "country", "tlds": [ "co" ] }, { - "slug": "cologne", - "name_en": "Cologne", - "subtype": "city", + "coordinates": { + "lat": 50.94222, + "lon": 6.95778 + }, + "info_link": "https://en.wikipedia.org/wiki/Cologne", "iso_code": null, + "name_en": "Cologne", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Cologne", + "slug": "cologne", + "subtype": "city", "tlds": [ "cologne", "koeln" - ], - "coordinates": { - "lat": 50.94222, - "lon": 6.95778 - } + ] }, { - "slug": "corsica", - "name_en": "Corsica", - "subtype": "subdivision", + "coordinates": { + "lat": 42.15, + "lon": 9.08333 + }, + "info_link": "https://en.wikipedia.org/wiki/Corsica", "iso_code": "FR-20R", + "name_en": "Corsica", "parent": "fr", - "info_link": "https://en.wikipedia.org/wiki/Corsica", + "slug": "corsica", + "subtype": "subdivision", "tlds": [ "corsica" - ], - "coordinates": { - "lat": 42.15, - "lon": 9.08333 - } + ] }, { - "slug": "cr", - "name_en": "Costa Rica", - "subtype": "country", "iso_code": "CR", "iso_numeric": "188", + "name_en": "Costa Rica", "parent": null, + "slug": "cr", + "subtype": "country", "tlds": [ "cr" ] }, { - "slug": "cu", - "name_en": "Cuba", - "subtype": "country", "iso_code": "CU", "iso_numeric": "192", + "name_en": "Cuba", "parent": null, + "slug": "cu", + "subtype": "country", "tlds": [ "cu" ] }, { - "slug": "cv", - "name_en": "Cabo Verde", - "subtype": "country", "iso_code": "CV", "iso_numeric": "132", + "name_en": "Cabo Verde", "parent": null, + "slug": "cv", + "subtype": "country", "tlds": [ "cv" ] }, { - "slug": "cw", - "name_en": "Curaçao", - "subtype": "country", "iso_code": "CW", + "iso_designation": "dependent_territory", "iso_numeric": "531", + "name_en": "Curaçao", "parent": "nl", + "slug": "cw", + "subtype": "country", "tlds": [ "cw" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "cx", - "name_en": "Christmas Island", - "subtype": "country", + "coordinates": { + "lat": -10.49, + "lon": 105.6275 + }, + "info_link": "https://en.wikipedia.org/wiki/Christmas_Island", "iso_code": "CX", + "iso_designation": "dependent_territory", "iso_numeric": "162", + "name_en": "Christmas Island", "parent": "au", + "slug": "cx", + "subtype": "country", "tlds": [ "cx" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "cy", - "name_en": "Cyprus", - "subtype": "country", "iso_code": "CY", "iso_numeric": "196", + "name_en": "Cyprus", "parent": null, + "slug": "cy", + "subtype": "country", "tlds": [ "cy" ] }, { - "slug": "cz", - "name_en": "Czechia", - "subtype": "country", "iso_code": "CZ", "iso_numeric": "203", + "name_en": "Czechia", "parent": null, + "slug": "cz", + "subtype": "country", "tlds": [ "cz" ] }, { - "slug": "de", - "name_en": "Germany", - "subtype": "country", "iso_code": "DE", "iso_numeric": "276", + "name_en": "Germany", "parent": null, + "slug": "de", + "subtype": "country", "tlds": [ "de" ] }, { - "slug": "dj", - "name_en": "Djibouti", - "subtype": "country", "iso_code": "DJ", "iso_numeric": "262", + "name_en": "Djibouti", "parent": null, + "slug": "dj", + "subtype": "country", "tlds": [ "dj" ] }, { - "slug": "dk", - "name_en": "Denmark", - "subtype": "country", "iso_code": "DK", "iso_numeric": "208", + "name_en": "Denmark", "parent": null, + "slug": "dk", + "subtype": "country", "tlds": [ "dk" ] }, { - "slug": "dm", - "name_en": "Dominica", - "subtype": "country", "iso_code": "DM", "iso_numeric": "212", + "name_en": "Dominica", "parent": null, + "slug": "dm", + "subtype": "country", "tlds": [ "dm" ] }, { - "slug": "do", - "name_en": "Dominican Republic", - "subtype": "country", "iso_code": "DO", "iso_numeric": "214", + "name_en": "Dominican Republic", "parent": null, + "slug": "do", + "subtype": "country", "tlds": [ "do" ] }, { - "slug": "dubai", - "name_en": "Dubai", - "subtype": "city", + "coordinates": { + "lat": 25.26972, + "lon": 55.30944 + }, + "info_link": "https://en.wikipedia.org/wiki/Dubai", "iso_code": null, + "name_en": "Dubai", "parent": "ae", - "info_link": "https://en.wikipedia.org/wiki/Dubai", + "slug": "dubai", + "subtype": "city", "tlds": [ "dubai" - ], - "coordinates": { - "lat": 25.26972, - "lon": 55.30944 - } + ] }, { - "slug": "durban", - "name_en": "Durban", - "subtype": "city", + "coordinates": { + "lat": -29.85833, + "lon": 31.025 + }, + "info_link": "https://en.wikipedia.org/wiki/Durban", "iso_code": null, + "name_en": "Durban", "parent": "za", - "info_link": "https://en.wikipedia.org/wiki/Durban", + "slug": "durban", + "subtype": "city", "tlds": [ "durban" - ], - "coordinates": { - "lat": -29.85833, - "lon": 31.025 - } + ] }, { - "slug": "dz", - "name_en": "Algeria", - "subtype": "country", "iso_code": "DZ", "iso_numeric": "012", + "name_en": "Algeria", "parent": null, + "slug": "dz", + "subtype": "country", "tlds": [ "dz", "xn--lgbbat1ad8j" ] }, { - "slug": "ec", - "name_en": "Ecuador", - "subtype": "country", "iso_code": "EC", "iso_numeric": "218", + "name_en": "Ecuador", "parent": null, + "slug": "ec", + "subtype": "country", "tlds": [ "ec" ] }, { - "slug": "ee", - "name_en": "Estonia", - "subtype": "country", "iso_code": "EE", "iso_numeric": "233", + "name_en": "Estonia", "parent": null, + "slug": "ee", + "subtype": "country", "tlds": [ "ee" ] }, { - "slug": "eg", - "name_en": "Egypt", - "subtype": "country", "iso_code": "EG", "iso_numeric": "818", + "name_en": "Egypt", "parent": null, + "slug": "eg", + "subtype": "country", "tlds": [ "eg", "xn--wgbh1c" ] }, { - "slug": "er", - "name_en": "Eritrea", - "subtype": "country", "iso_code": "ER", "iso_numeric": "232", + "name_en": "Eritrea", "parent": null, + "slug": "er", + "subtype": "country", "tlds": [ "er" ] }, { - "slug": "es", - "name_en": "Spain", - "subtype": "country", "iso_code": "ES", "iso_numeric": "724", + "name_en": "Spain", "parent": null, + "slug": "es", + "subtype": "country", "tlds": [ "es" ] }, { - "slug": "et", - "name_en": "Ethiopia", - "subtype": "country", "iso_code": "ET", "iso_numeric": "231", + "name_en": "Ethiopia", "parent": null, + "slug": "et", + "subtype": "country", "tlds": [ "et" ] }, { - "slug": "eu", - "name_en": "European Union", - "subtype": "supranational", + "coordinates": { + "lat": 50.11694, + "lon": 9.24778 + }, + "info_link": "https://en.wikipedia.org/wiki/European_Union", "iso_code": "EU", + "name_en": "European Union", "parent": null, - "info_link": "https://en.wikipedia.org/wiki/European_Union", + "slug": "eu", + "subtype": "supranational", "tlds": [ "eu", "xn--e1a4c", "xn--qxa6a" - ], - "coordinates": { - "lat": 50.11694, - "lon": 9.24778 - } + ] }, { - "slug": "fi", - "name_en": "Finland", - "subtype": "country", "iso_code": "FI", "iso_numeric": "246", + "name_en": "Finland", "parent": null, + "slug": "fi", + "subtype": "country", "tlds": [ "fi" ] }, { - "slug": "fj", - "name_en": "Fiji", - "subtype": "country", "iso_code": "FJ", "iso_numeric": "242", + "name_en": "Fiji", "parent": null, + "slug": "fj", + "subtype": "country", "tlds": [ "fj" ] }, { - "slug": "fk", - "name_en": "Falkland Islands (Malvinas)", - "subtype": "country", "iso_code": "FK", + "iso_designation": "dependent_territory", "iso_numeric": "238", + "name_en": "Falkland Islands (Malvinas)", "parent": "gb", + "slug": "fk", + "subtype": "country", "tlds": [ "fk" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "flanders", - "name_en": "Flanders", - "subtype": "subdivision", + "coordinates": { + "lat": 51.0, + "lon": 4.5 + }, + "info_link": "https://en.wikipedia.org/wiki/Flanders", "iso_code": "BE-VLG", + "name_en": "Flanders", "parent": "be", - "info_link": "https://en.wikipedia.org/wiki/Flanders", + "slug": "flanders", + "subtype": "subdivision", "tlds": [ "vlaanderen" - ], - "coordinates": { - "lat": 51.0, - "lon": 4.5 - } + ] }, { - "slug": "fm", - "name_en": "Micronesia, Federated States of", - "subtype": "country", "iso_code": "FM", "iso_numeric": "583", + "name_en": "Micronesia, Federated States of", "parent": null, + "slug": "fm", + "subtype": "country", "tlds": [ "fm" ] }, { - "slug": "fo", - "name_en": "Faroe Islands", - "subtype": "country", "iso_code": "FO", + "iso_designation": "dependent_territory", "iso_numeric": "234", + "name_en": "Faroe Islands", "parent": "dk", + "slug": "fo", + "subtype": "country", "tlds": [ "fo" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "fr", - "name_en": "France", - "subtype": "country", "iso_code": "FR", "iso_numeric": "250", + "name_en": "France", "parent": null, + "slug": "fr", + "subtype": "country", "tlds": [ "fr" ] }, { - "slug": "friesland", - "name_en": "Friesland", - "subtype": "subdivision", + "coordinates": { + "lat": 53.20139, + "lon": 5.8 + }, + "info_link": "https://en.wikipedia.org/wiki/Friesland", "iso_code": "NL-FR", + "name_en": "Friesland", "parent": "nl", - "info_link": "https://en.wikipedia.org/wiki/Friesland", + "slug": "friesland", + "subtype": "subdivision", "tlds": [ "frl" - ], - "coordinates": { - "lat": 53.20139, - "lon": 5.8 - } + ] }, { - "slug": "ga", - "name_en": "Gabon", - "subtype": "country", "iso_code": "GA", "iso_numeric": "266", + "name_en": "Gabon", "parent": null, + "slug": "ga", + "subtype": "country", "tlds": [ "ga" ] }, { - "slug": "galicia", - "name_en": "Galicia", - "subtype": "subdivision", + "coordinates": { + "lat": 42.8, + "lon": -7.9 + }, + "info_link": "https://en.wikipedia.org/wiki/Galicia_(Spain)", "iso_code": "ES-GA", + "name_en": "Galicia", "parent": "es", - "info_link": "https://en.wikipedia.org/wiki/Galicia_(Spain)", + "slug": "galicia", + "subtype": "subdivision", "tlds": [ "gal" - ], - "coordinates": { - "lat": 42.8, - "lon": -7.9 - } + ] }, { - "slug": "gb", - "name_en": "United Kingdom", - "subtype": "country", "iso_code": "GB", "iso_numeric": "826", + "name_en": "United Kingdom", "parent": null, + "slug": "gb", + "subtype": "country", "tlds": [ "gb", "uk" ] }, { - "slug": "gd", - "name_en": "Grenada", - "subtype": "country", "iso_code": "GD", "iso_numeric": "308", + "name_en": "Grenada", "parent": null, + "slug": "gd", + "subtype": "country", "tlds": [ "gd" ] }, { - "slug": "ge", - "name_en": "Georgia", - "subtype": "country", "iso_code": "GE", "iso_numeric": "268", + "name_en": "Georgia", "parent": null, + "slug": "ge", + "subtype": "country", "tlds": [ "ge", "xn--node" ] }, { - "slug": "gent", - "name_en": "Ghent", - "subtype": "city", + "coordinates": { + "lat": 51.05361, + "lon": 3.72528 + }, + "info_link": "https://en.wikipedia.org/wiki/Ghent", "iso_code": null, + "name_en": "Ghent", "parent": "be", - "info_link": "https://en.wikipedia.org/wiki/Ghent", + "slug": "gent", + "subtype": "city", "tlds": [ "gent" - ], - "coordinates": { - "lat": 51.05361, - "lon": 3.72528 - } + ] }, { - "slug": "gf", - "name_en": "French Guiana", - "subtype": "country", + "coordinates": { + "lat": 4.0, + "lon": -53.0 + }, + "info_link": "https://en.wikipedia.org/wiki/French_Guiana", "iso_code": "GF", + "iso_designation": "dependent_territory", "iso_numeric": "254", + "name_en": "French Guiana", "parent": "fr", + "slug": "gf", + "subtype": "country", "tlds": [ "gf" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gg", - "name_en": "Guernsey", - "subtype": "country", "iso_code": "GG", + "iso_designation": "dependent_territory", "iso_numeric": "831", + "name_en": "Guernsey", "parent": "gb", + "slug": "gg", + "subtype": "country", "tlds": [ "gg" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gh", - "name_en": "Ghana", - "subtype": "country", "iso_code": "GH", "iso_numeric": "288", + "name_en": "Ghana", "parent": null, + "slug": "gh", + "subtype": "country", "tlds": [ "gh" ] }, { - "slug": "gi", - "name_en": "Gibraltar", - "subtype": "country", + "coordinates": { + "lat": 36.14, + "lon": -5.35 + }, + "info_link": "https://en.wikipedia.org/wiki/Gibraltar", "iso_code": "GI", + "iso_designation": "dependent_territory", "iso_numeric": "292", + "name_en": "Gibraltar", "parent": "gb", + "slug": "gi", + "subtype": "country", "tlds": [ "gi" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gl", - "name_en": "Greenland", - "subtype": "country", "iso_code": "GL", + "iso_designation": "dependent_territory", "iso_numeric": "304", + "name_en": "Greenland", "parent": "dk", + "slug": "gl", + "subtype": "country", "tlds": [ "gl" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gm", - "name_en": "Gambia", - "subtype": "country", "iso_code": "GM", "iso_numeric": "270", + "name_en": "Gambia", "parent": null, + "slug": "gm", + "subtype": "country", "tlds": [ "gm" ] }, { - "slug": "gn", - "name_en": "Guinea", - "subtype": "country", "iso_code": "GN", "iso_numeric": "324", + "name_en": "Guinea", "parent": null, + "slug": "gn", + "subtype": "country", "tlds": [ "gn" ] }, { - "slug": "gp", - "name_en": "Guadeloupe", - "subtype": "country", + "coordinates": { + "lat": 16.2595, + "lon": -61.5605 + }, + "info_link": "https://en.wikipedia.org/wiki/Guadeloupe", "iso_code": "GP", + "iso_designation": "dependent_territory", "iso_numeric": "312", + "name_en": "Guadeloupe", "parent": "fr", + "slug": "gp", + "subtype": "country", "tlds": [ "gp" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gq", - "name_en": "Equatorial Guinea", - "subtype": "country", "iso_code": "GQ", "iso_numeric": "226", + "name_en": "Equatorial Guinea", "parent": null, + "slug": "gq", + "subtype": "country", "tlds": [ "gq" ] }, { - "slug": "gr", - "name_en": "Greece", - "subtype": "country", "iso_code": "GR", "iso_numeric": "300", + "name_en": "Greece", "parent": null, + "slug": "gr", + "subtype": "country", "tlds": [ "gr", "xn--qxam" ] }, { - "slug": "gs", - "name_en": "South Georgia and the South Sandwich Islands", - "subtype": "country", "iso_code": "GS", + "iso_designation": "dependent_territory", "iso_numeric": "239", + "name_en": "South Georgia and the South Sandwich Islands", "parent": "gb", + "slug": "gs", + "subtype": "country", "tlds": [ "gs" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gt", - "name_en": "Guatemala", - "subtype": "country", "iso_code": "GT", "iso_numeric": "320", + "name_en": "Guatemala", "parent": null, + "slug": "gt", + "subtype": "country", "tlds": [ "gt" ] }, { - "slug": "gu", - "name_en": "Guam", - "subtype": "country", "iso_code": "GU", + "iso_designation": "dependent_territory", "iso_numeric": "316", + "name_en": "Guam", "parent": "us", + "slug": "gu", + "subtype": "country", "tlds": [ "gu" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "gw", - "name_en": "Guinea-Bissau", - "subtype": "country", "iso_code": "GW", "iso_numeric": "624", + "name_en": "Guinea-Bissau", "parent": null, + "slug": "gw", + "subtype": "country", "tlds": [ "gw" ] }, { - "slug": "gy", - "name_en": "Guyana", - "subtype": "country", "iso_code": "GY", "iso_numeric": "328", + "name_en": "Guyana", "parent": null, + "slug": "gy", + "subtype": "country", "tlds": [ "gy" ] }, { - "slug": "hamburg", - "name_en": "Hamburg", - "subtype": "city", + "coordinates": { + "lat": 53.55, + "lon": 10.0 + }, + "info_link": "https://en.wikipedia.org/wiki/Hamburg", "iso_code": null, + "name_en": "Hamburg", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Hamburg", + "slug": "hamburg", + "subtype": "city", "tlds": [ "hamburg" - ], - "coordinates": { - "lat": 53.55, - "lon": 10.0 - } + ] }, { - "slug": "helsinki", - "name_en": "Helsinki", - "subtype": "city", + "coordinates": { + "lat": 60.17083, + "lon": 24.9375 + }, + "info_link": "https://en.wikipedia.org/wiki/Helsinki", "iso_code": null, + "name_en": "Helsinki", "parent": "fi", - "info_link": "https://en.wikipedia.org/wiki/Helsinki", + "slug": "helsinki", + "subtype": "city", "tlds": [ "helsinki" - ], - "coordinates": { - "lat": 60.17083, - "lon": 24.9375 - } + ] }, { - "slug": "hk", - "name_en": "Hong Kong", - "subtype": "country", "iso_code": "HK", + "iso_designation": "dependent_territory", "iso_numeric": "344", + "name_en": "Hong Kong", "parent": "cn", + "slug": "hk", + "subtype": "country", "tlds": [ "hk", "xn--j6w193g" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "hm", - "name_en": "Heard Island and McDonald Islands", - "subtype": "country", "iso_code": "HM", + "iso_designation": "dependent_territory", "iso_numeric": "334", + "name_en": "Heard Island and McDonald Islands", "parent": "au", + "slug": "hm", + "subtype": "country", "tlds": [ "hm" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "hn", - "name_en": "Honduras", - "subtype": "country", "iso_code": "HN", "iso_numeric": "340", + "name_en": "Honduras", "parent": null, + "slug": "hn", + "subtype": "country", "tlds": [ "hn" ] }, { - "slug": "hr", - "name_en": "Croatia", - "subtype": "country", "iso_code": "HR", "iso_numeric": "191", + "name_en": "Croatia", "parent": null, + "slug": "hr", + "subtype": "country", "tlds": [ "hr" ] }, { - "slug": "ht", - "name_en": "Haiti", - "subtype": "country", "iso_code": "HT", "iso_numeric": "332", + "name_en": "Haiti", "parent": null, + "slug": "ht", + "subtype": "country", "tlds": [ "ht" ] }, { - "slug": "hu", - "name_en": "Hungary", - "subtype": "country", "iso_code": "HU", "iso_numeric": "348", + "name_en": "Hungary", "parent": null, + "slug": "hu", + "subtype": "country", "tlds": [ "hu" ] }, { - "slug": "id", - "name_en": "Indonesia", - "subtype": "country", "iso_code": "ID", "iso_numeric": "360", + "name_en": "Indonesia", "parent": null, + "slug": "id", + "subtype": "country", "tlds": [ "id" ] }, { - "slug": "ie", - "name_en": "Ireland", - "subtype": "country", "iso_code": "IE", "iso_numeric": "372", + "name_en": "Ireland", "parent": null, + "slug": "ie", + "subtype": "country", "tlds": [ "ie" ] }, { - "slug": "il", - "name_en": "Israel", - "subtype": "country", "iso_code": "IL", "iso_numeric": "376", + "name_en": "Israel", "parent": null, + "slug": "il", + "subtype": "country", "tlds": [ "il", "xn--4dbrk0ce" ] }, { - "slug": "im", - "name_en": "Isle of Man", - "subtype": "country", "iso_code": "IM", + "iso_designation": "dependent_territory", "iso_numeric": "833", + "name_en": "Isle of Man", "parent": "gb", + "slug": "im", + "subtype": "country", "tlds": [ "im" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "in", - "name_en": "India", - "subtype": "country", "iso_code": "IN", "iso_numeric": "356", + "name_en": "India", "parent": null, + "slug": "in", + "subtype": "country", "tlds": [ "in", "xn--2scrj9c", @@ -1575,346 +1611,346 @@ ] }, { - "slug": "io", - "name_en": "British Indian Ocean Territory", - "subtype": "country", "iso_code": "IO", + "iso_designation": "dependent_territory", "iso_numeric": "086", + "name_en": "British Indian Ocean Territory", "parent": "gb", + "slug": "io", + "subtype": "country", "tlds": [ "io" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "iq", - "name_en": "Iraq", - "subtype": "country", "iso_code": "IQ", "iso_numeric": "368", + "name_en": "Iraq", "parent": null, + "slug": "iq", + "subtype": "country", "tlds": [ "iq", "xn--mgbtx2b" ] }, { - "slug": "ir", - "name_en": "Iran, Islamic Republic of", - "subtype": "country", "iso_code": "IR", "iso_numeric": "364", + "name_en": "Iran, Islamic Republic of", "parent": null, + "slug": "ir", + "subtype": "country", "tlds": [ "ir", "xn--mgba3a4f16a" ] }, { - "slug": "is", - "name_en": "Iceland", - "subtype": "country", "iso_code": "IS", "iso_numeric": "352", + "name_en": "Iceland", "parent": null, + "slug": "is", + "subtype": "country", "tlds": [ "is" ] }, { - "slug": "istanbul", - "name_en": "Istanbul", - "subtype": "city", + "coordinates": { + "lat": 41.01, + "lon": 28.96028 + }, + "info_link": "https://en.wikipedia.org/wiki/Istanbul", "iso_code": null, + "name_en": "Istanbul", "parent": "tr", - "info_link": "https://en.wikipedia.org/wiki/Istanbul", + "slug": "istanbul", + "subtype": "city", "tlds": [ "ist", "istanbul" - ], - "coordinates": { - "lat": 41.01, - "lon": 28.96028 - } + ] }, { - "slug": "it", - "name_en": "Italy", - "subtype": "country", "iso_code": "IT", "iso_numeric": "380", + "name_en": "Italy", "parent": null, + "slug": "it", + "subtype": "country", "tlds": [ "it" ] }, { - "slug": "je", - "name_en": "Jersey", - "subtype": "country", "iso_code": "JE", + "iso_designation": "dependent_territory", "iso_numeric": "832", + "name_en": "Jersey", "parent": "gb", + "slug": "je", + "subtype": "country", "tlds": [ "je" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "jm", - "name_en": "Jamaica", - "subtype": "country", "iso_code": "JM", "iso_numeric": "388", + "name_en": "Jamaica", "parent": null, + "slug": "jm", + "subtype": "country", "tlds": [ "jm" ] }, { - "slug": "jo", - "name_en": "Jordan", - "subtype": "country", "iso_code": "JO", "iso_numeric": "400", + "name_en": "Jordan", "parent": null, + "slug": "jo", + "subtype": "country", "tlds": [ "jo", "xn--mgbayh7gpa" ] }, { - "slug": "joburg", - "name_en": "Johannesburg", - "subtype": "city", + "coordinates": { + "lat": -26.20436, + "lon": 28.04164 + }, + "info_link": "https://en.wikipedia.org/wiki/Johannesburg", "iso_code": null, + "name_en": "Johannesburg", "parent": "za", - "info_link": "https://en.wikipedia.org/wiki/Johannesburg", + "slug": "joburg", + "subtype": "city", "tlds": [ "joburg" - ], - "coordinates": { - "lat": -26.20436, - "lon": 28.04164 - } + ] }, { - "slug": "jp", - "name_en": "Japan", - "subtype": "country", "iso_code": "JP", "iso_numeric": "392", + "name_en": "Japan", "parent": null, + "slug": "jp", + "subtype": "country", "tlds": [ "jp" ] }, { - "slug": "ke", - "name_en": "Kenya", - "subtype": "country", "iso_code": "KE", "iso_numeric": "404", + "name_en": "Kenya", "parent": null, + "slug": "ke", + "subtype": "country", "tlds": [ "ke" ] }, { - "slug": "kg", - "name_en": "Kyrgyzstan", - "subtype": "country", "iso_code": "KG", "iso_numeric": "417", + "name_en": "Kyrgyzstan", "parent": null, + "slug": "kg", + "subtype": "country", "tlds": [ "kg" ] }, { - "slug": "kh", - "name_en": "Cambodia", - "subtype": "country", "iso_code": "KH", "iso_numeric": "116", + "name_en": "Cambodia", "parent": null, + "slug": "kh", + "subtype": "country", "tlds": [ "kh" ] }, { - "slug": "ki", - "name_en": "Kiribati", - "subtype": "country", "iso_code": "KI", "iso_numeric": "296", + "name_en": "Kiribati", "parent": null, + "slug": "ki", + "subtype": "country", "tlds": [ "ki" ] }, { - "slug": "km", - "name_en": "Comoros", - "subtype": "country", "iso_code": "KM", "iso_numeric": "174", + "name_en": "Comoros", "parent": null, + "slug": "km", + "subtype": "country", "tlds": [ "km" ] }, { - "slug": "kn", - "name_en": "Saint Kitts and Nevis", - "subtype": "country", "iso_code": "KN", "iso_numeric": "659", + "name_en": "Saint Kitts and Nevis", "parent": null, + "slug": "kn", + "subtype": "country", "tlds": [ "kn" ] }, { - "slug": "kp", - "name_en": "Korea, Democratic People's Republic of", - "subtype": "country", "iso_code": "KP", "iso_numeric": "408", + "name_en": "Korea, Democratic People's Republic of", "parent": null, + "slug": "kp", + "subtype": "country", "tlds": [ "kp" ] }, { - "slug": "kr", - "name_en": "Korea, Republic of", - "subtype": "country", "iso_code": "KR", "iso_numeric": "410", + "name_en": "Korea, Republic of", "parent": null, + "slug": "kr", + "subtype": "country", "tlds": [ "kr", "xn--3e0b707e" ] }, { - "slug": "kw", - "name_en": "Kuwait", - "subtype": "country", "iso_code": "KW", "iso_numeric": "414", + "name_en": "Kuwait", "parent": null, + "slug": "kw", + "subtype": "country", "tlds": [ "kw" ] }, { - "slug": "ky", - "name_en": "Cayman Islands", - "subtype": "country", "iso_code": "KY", + "iso_designation": "dependent_territory", "iso_numeric": "136", + "name_en": "Cayman Islands", "parent": "gb", + "slug": "ky", + "subtype": "country", "tlds": [ "ky" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "kyoto", - "name_en": "Kyoto", - "subtype": "city", + "coordinates": { + "lat": 35.01161, + "lon": 135.76811 + }, + "info_link": "https://en.wikipedia.org/wiki/Kyoto", "iso_code": null, + "name_en": "Kyoto", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Kyoto", + "slug": "kyoto", + "subtype": "city", "tlds": [ "kyoto" - ], - "coordinates": { - "lat": 35.01161, - "lon": 135.76811 - } + ] }, { - "slug": "kz", - "name_en": "Kazakhstan", - "subtype": "country", "iso_code": "KZ", "iso_numeric": "398", + "name_en": "Kazakhstan", "parent": null, + "slug": "kz", + "subtype": "country", "tlds": [ "kz", "xn--80ao21a" ] }, { - "slug": "la", - "name_en": "Lao People's Democratic Republic", - "subtype": "country", "iso_code": "LA", "iso_numeric": "418", + "name_en": "Lao People's Democratic Republic", "parent": null, + "slug": "la", + "subtype": "country", "tlds": [ "la", "xn--q7ce6a" ] }, { - "slug": "latin-america", - "name_en": "Latin America", - "subtype": "supranational", + "coordinates": { + "lat": -1.10689, + "lon": -68.09739 + }, + "info_link": "https://en.wikipedia.org/wiki/Latin_America", "iso_code": null, + "name_en": "Latin America", "parent": null, - "info_link": "https://en.wikipedia.org/wiki/Latin_America", + "slug": "latin-america", + "subtype": "supranational", "tlds": [ "lat" - ], - "coordinates": { - "lat": -1.10689, - "lon": -68.09739 - } + ] }, { - "slug": "lb", - "name_en": "Lebanon", - "subtype": "country", "iso_code": "LB", "iso_numeric": "422", + "name_en": "Lebanon", "parent": null, + "slug": "lb", + "subtype": "country", "tlds": [ "lb" ] }, { - "slug": "lc", - "name_en": "Saint Lucia", - "subtype": "country", "iso_code": "LC", "iso_numeric": "662", + "name_en": "Saint Lucia", "parent": null, + "slug": "lc", + "subtype": "country", "tlds": [ "lc" ] }, { - "slug": "li", - "name_en": "Liechtenstein", - "subtype": "country", "iso_code": "LI", "iso_numeric": "438", + "name_en": "Liechtenstein", "parent": null, + "slug": "li", + "subtype": "country", "tlds": [ "li" ] }, { - "slug": "lk", - "name_en": "Sri Lanka", - "subtype": "country", "iso_code": "LK", "iso_numeric": "144", + "name_en": "Sri Lanka", "parent": null, + "slug": "lk", + "subtype": "country", "tlds": [ "lk", "xn--fzc2c9e2c", @@ -1922,1020 +1958,1030 @@ ] }, { - "slug": "london", - "name_en": "London", - "subtype": "city", + "coordinates": { + "lat": 51.50722, + "lon": -0.1275 + }, + "info_link": "https://en.wikipedia.org/wiki/London", "iso_code": null, + "name_en": "London", "parent": "gb", - "info_link": "https://en.wikipedia.org/wiki/London", + "slug": "london", + "subtype": "city", "tlds": [ "london" - ], - "coordinates": { - "lat": 51.50722, - "lon": -0.1275 - } + ] }, { - "slug": "lr", - "name_en": "Liberia", - "subtype": "country", "iso_code": "LR", "iso_numeric": "430", + "name_en": "Liberia", "parent": null, + "slug": "lr", + "subtype": "country", "tlds": [ "lr" ] }, { - "slug": "ls", - "name_en": "Lesotho", - "subtype": "country", "iso_code": "LS", "iso_numeric": "426", + "name_en": "Lesotho", "parent": null, + "slug": "ls", + "subtype": "country", "tlds": [ "ls" ] }, { - "slug": "lt", - "name_en": "Lithuania", - "subtype": "country", "iso_code": "LT", "iso_numeric": "440", + "name_en": "Lithuania", "parent": null, + "slug": "lt", + "subtype": "country", "tlds": [ "lt" ] }, { - "slug": "lu", - "name_en": "Luxembourg", - "subtype": "country", "iso_code": "LU", "iso_numeric": "442", + "name_en": "Luxembourg", "parent": null, + "slug": "lu", + "subtype": "country", "tlds": [ "lu" ] }, { - "slug": "lv", - "name_en": "Latvia", - "subtype": "country", "iso_code": "LV", "iso_numeric": "428", + "name_en": "Latvia", "parent": null, + "slug": "lv", + "subtype": "country", "tlds": [ "lv" ] }, { - "slug": "ly", - "name_en": "Libya", - "subtype": "country", "iso_code": "LY", "iso_numeric": "434", + "name_en": "Libya", "parent": null, + "slug": "ly", + "subtype": "country", "tlds": [ "ly" ] }, { - "slug": "ma", - "name_en": "Morocco", - "subtype": "country", "iso_code": "MA", "iso_numeric": "504", + "name_en": "Morocco", "parent": null, + "slug": "ma", + "subtype": "country", "tlds": [ "ma", "xn--mgbc0a9azcg" ] }, { - "slug": "madrid", - "name_en": "Madrid", - "subtype": "city", + "coordinates": { + "lat": 40.41694, + "lon": -3.70333 + }, + "info_link": "https://en.wikipedia.org/wiki/Madrid", "iso_code": null, + "name_en": "Madrid", "parent": "es", - "info_link": "https://en.wikipedia.org/wiki/Madrid", + "slug": "madrid", + "subtype": "city", "tlds": [ "madrid" - ], - "coordinates": { - "lat": 40.41694, - "lon": -3.70333 - } + ] }, { - "slug": "mc", - "name_en": "Monaco", - "subtype": "country", "iso_code": "MC", "iso_numeric": "492", + "name_en": "Monaco", "parent": null, + "slug": "mc", + "subtype": "country", "tlds": [ "mc" ] }, { - "slug": "md", - "name_en": "Moldova, Republic of", - "subtype": "country", "iso_code": "MD", "iso_numeric": "498", + "name_en": "Moldova, Republic of", "parent": null, + "slug": "md", + "subtype": "country", "tlds": [ "md" ] }, { - "slug": "me", - "name_en": "Montenegro", - "subtype": "country", "iso_code": "ME", "iso_numeric": "499", + "name_en": "Montenegro", "parent": null, + "slug": "me", + "subtype": "country", "tlds": [ "me" ] }, { - "slug": "melbourne", - "name_en": "Melbourne", - "subtype": "city", + "coordinates": { + "lat": -37.81417, + "lon": 144.96306 + }, + "info_link": "https://en.wikipedia.org/wiki/Melbourne", "iso_code": null, + "name_en": "Melbourne", "parent": "au", - "info_link": "https://en.wikipedia.org/wiki/Melbourne", + "slug": "melbourne", + "subtype": "city", "tlds": [ "melbourne" - ], - "coordinates": { - "lat": -37.81417, - "lon": 144.96306 - } + ] }, { - "slug": "mg", - "name_en": "Madagascar", - "subtype": "country", "iso_code": "MG", "iso_numeric": "450", + "name_en": "Madagascar", "parent": null, + "slug": "mg", + "subtype": "country", "tlds": [ "mg" ] }, { - "slug": "mh", - "name_en": "Marshall Islands", - "subtype": "country", "iso_code": "MH", "iso_numeric": "584", + "name_en": "Marshall Islands", "parent": null, + "slug": "mh", + "subtype": "country", "tlds": [ "mh" ] }, { - "slug": "miami", - "name_en": "Miami", - "subtype": "city", + "coordinates": { + "lat": 25.78333, + "lon": -80.21667 + }, + "info_link": "https://en.wikipedia.org/wiki/Miami", "iso_code": null, + "name_en": "Miami", "parent": "us", - "info_link": "https://en.wikipedia.org/wiki/Miami", + "slug": "miami", + "subtype": "city", "tlds": [ "miami" - ], - "coordinates": { - "lat": 25.78333, - "lon": -80.21667 - } + ] }, { - "slug": "mk", - "name_en": "North Macedonia", - "subtype": "country", "iso_code": "MK", "iso_numeric": "807", + "name_en": "North Macedonia", "parent": null, + "slug": "mk", + "subtype": "country", "tlds": [ "mk", "xn--d1alf" ] }, { - "slug": "ml", - "name_en": "Mali", - "subtype": "country", "iso_code": "ML", "iso_numeric": "466", + "name_en": "Mali", "parent": null, + "slug": "ml", + "subtype": "country", "tlds": [ "ml" ] }, { - "slug": "mm", - "name_en": "Myanmar", - "subtype": "country", "iso_code": "MM", "iso_numeric": "104", + "name_en": "Myanmar", "parent": null, + "slug": "mm", + "subtype": "country", "tlds": [ "mm" ] }, { - "slug": "mn", - "name_en": "Mongolia", - "subtype": "country", "iso_code": "MN", "iso_numeric": "496", + "name_en": "Mongolia", "parent": null, + "slug": "mn", + "subtype": "country", "tlds": [ "mn", "xn--l1acc" ] }, { - "slug": "mo", - "name_en": "Macao", - "subtype": "country", "iso_code": "MO", + "iso_designation": "dependent_territory", "iso_numeric": "446", + "name_en": "Macao", "parent": "cn", + "slug": "mo", + "subtype": "country", "tlds": [ "mo", "xn--mix891f" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "moscow", - "name_en": "Moscow", - "subtype": "city", + "coordinates": { + "lat": 55.75056, + "lon": 37.6175 + }, + "info_link": "https://en.wikipedia.org/wiki/Moscow", "iso_code": null, + "name_en": "Moscow", "parent": "ru", - "info_link": "https://en.wikipedia.org/wiki/Moscow", + "slug": "moscow", + "subtype": "city", "tlds": [ "moscow", "xn--80adxhks" - ], - "coordinates": { - "lat": 55.75056, - "lon": 37.6175 - } + ] }, { - "slug": "mp", - "name_en": "Northern Mariana Islands", - "subtype": "country", "iso_code": "MP", + "iso_designation": "dependent_territory", "iso_numeric": "580", + "name_en": "Northern Mariana Islands", "parent": "us", + "slug": "mp", + "subtype": "country", "tlds": [ "mp" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "mq", - "name_en": "Martinique", - "subtype": "country", + "coordinates": { + "lat": 14.65, + "lon": -61.015 + }, + "info_link": "https://en.wikipedia.org/wiki/Martinique", "iso_code": "MQ", + "iso_designation": "dependent_territory", "iso_numeric": "474", + "name_en": "Martinique", "parent": "fr", + "slug": "mq", + "subtype": "country", "tlds": [ "mq" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "mr", - "name_en": "Mauritania", - "subtype": "country", "iso_code": "MR", "iso_numeric": "478", + "name_en": "Mauritania", "parent": null, + "slug": "mr", + "subtype": "country", "tlds": [ "mr", "xn--mgbah1a3hjkrd" ] }, { - "slug": "ms", - "name_en": "Montserrat", - "subtype": "country", "iso_code": "MS", + "iso_designation": "dependent_territory", "iso_numeric": "500", + "name_en": "Montserrat", "parent": "gb", + "slug": "ms", + "subtype": "country", "tlds": [ "ms" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "mt", - "name_en": "Malta", - "subtype": "country", "iso_code": "MT", "iso_numeric": "470", + "name_en": "Malta", "parent": null, + "slug": "mt", + "subtype": "country", "tlds": [ "mt" ] }, { - "slug": "mu", - "name_en": "Mauritius", - "subtype": "country", "iso_code": "MU", "iso_numeric": "480", + "name_en": "Mauritius", "parent": null, + "slug": "mu", + "subtype": "country", "tlds": [ "mu" ] }, { - "slug": "mv", - "name_en": "Maldives", - "subtype": "country", "iso_code": "MV", "iso_numeric": "462", + "name_en": "Maldives", "parent": null, + "slug": "mv", + "subtype": "country", "tlds": [ "mv" ] }, { - "slug": "mw", - "name_en": "Malawi", - "subtype": "country", "iso_code": "MW", "iso_numeric": "454", + "name_en": "Malawi", "parent": null, + "slug": "mw", + "subtype": "country", "tlds": [ "mw" ] }, { - "slug": "mx", - "name_en": "Mexico", - "subtype": "country", "iso_code": "MX", "iso_numeric": "484", + "name_en": "Mexico", "parent": null, + "slug": "mx", + "subtype": "country", "tlds": [ "mx" ] }, { - "slug": "my", - "name_en": "Malaysia", - "subtype": "country", "iso_code": "MY", "iso_numeric": "458", + "name_en": "Malaysia", "parent": null, + "slug": "my", + "subtype": "country", "tlds": [ "my", "xn--mgbx4cd0ab" ] }, { - "slug": "mz", - "name_en": "Mozambique", - "subtype": "country", "iso_code": "MZ", "iso_numeric": "508", + "name_en": "Mozambique", "parent": null, + "slug": "mz", + "subtype": "country", "tlds": [ "mz" ] }, { - "slug": "na", - "name_en": "Namibia", - "subtype": "country", "iso_code": "NA", "iso_numeric": "516", + "name_en": "Namibia", "parent": null, + "slug": "na", + "subtype": "country", "tlds": [ "na" ] }, { - "slug": "nagoya", - "name_en": "Nagoya", - "subtype": "city", + "coordinates": { + "lat": 35.18139, + "lon": 136.90639 + }, + "info_link": "https://en.wikipedia.org/wiki/Nagoya", "iso_code": null, + "name_en": "Nagoya", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Nagoya", + "slug": "nagoya", + "subtype": "city", "tlds": [ "nagoya" - ], - "coordinates": { - "lat": 35.18139, - "lon": 136.90639 - } + ] }, { - "slug": "nc", - "name_en": "New Caledonia", - "subtype": "country", "iso_code": "NC", + "iso_designation": "dependent_territory", "iso_numeric": "540", + "name_en": "New Caledonia", "parent": "fr", + "slug": "nc", + "subtype": "country", "tlds": [ "nc" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "ne", - "name_en": "Niger", - "subtype": "country", "iso_code": "NE", "iso_numeric": "562", + "name_en": "Niger", "parent": null, + "slug": "ne", + "subtype": "country", "tlds": [ "ne" ] }, { - "slug": "nf", - "name_en": "Norfolk Island", - "subtype": "country", "iso_code": "NF", + "iso_designation": "dependent_territory", "iso_numeric": "574", + "name_en": "Norfolk Island", "parent": "au", + "slug": "nf", + "subtype": "country", "tlds": [ "nf" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "ng", - "name_en": "Nigeria", - "subtype": "country", "iso_code": "NG", "iso_numeric": "566", + "name_en": "Nigeria", "parent": null, + "slug": "ng", + "subtype": "country", "tlds": [ "ng" ] }, { - "slug": "ni", - "name_en": "Nicaragua", - "subtype": "country", "iso_code": "NI", "iso_numeric": "558", + "name_en": "Nicaragua", "parent": null, + "slug": "ni", + "subtype": "country", "tlds": [ "ni" ] }, { - "slug": "nl", - "name_en": "Netherlands", - "subtype": "country", "iso_code": "NL", "iso_numeric": "528", + "name_en": "Netherlands", "parent": null, + "slug": "nl", + "subtype": "country", "tlds": [ "nl" ] }, { - "slug": "no", - "name_en": "Norway", - "subtype": "country", "iso_code": "NO", "iso_numeric": "578", + "name_en": "Norway", "parent": null, + "slug": "no", + "subtype": "country", "tlds": [ "no" ] }, { - "slug": "north-rhine-westphalia", - "name_en": "North Rhine-Westphalia", - "subtype": "subdivision", + "coordinates": { + "lat": 51.46667, + "lon": 7.55 + }, + "info_link": "https://en.wikipedia.org/wiki/North_Rhine-Westphalia", "iso_code": "DE-NW", + "name_en": "North Rhine-Westphalia", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/North_Rhine-Westphalia", + "slug": "north-rhine-westphalia", + "subtype": "subdivision", "tlds": [ "nrw" - ], - "coordinates": { - "lat": 51.46667, - "lon": 7.55 - } + ] }, { - "slug": "np", - "name_en": "Nepal", - "subtype": "country", "iso_code": "NP", "iso_numeric": "524", + "name_en": "Nepal", "parent": null, + "slug": "np", + "subtype": "country", "tlds": [ "np" ] }, { - "slug": "nr", - "name_en": "Nauru", - "subtype": "country", "iso_code": "NR", "iso_numeric": "520", + "name_en": "Nauru", "parent": null, + "slug": "nr", + "subtype": "country", "tlds": [ "nr" ] }, { - "slug": "nu", - "name_en": "Niue", - "subtype": "country", "iso_code": "NU", + "iso_designation": "dependent_territory", "iso_numeric": "570", + "name_en": "Niue", "parent": "nz", + "slug": "nu", + "subtype": "country", "tlds": [ "nu" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "nyc", - "name_en": "New York City", - "subtype": "city", + "coordinates": { + "lat": 40.71278, + "lon": -74.00611 + }, + "info_link": "https://en.wikipedia.org/wiki/New_York_City", "iso_code": null, + "name_en": "New York City", "parent": "us", - "info_link": "https://en.wikipedia.org/wiki/New_York_City", + "slug": "nyc", + "subtype": "city", "tlds": [ "nyc" - ], - "coordinates": { - "lat": 40.71278, - "lon": -74.00611 - } + ] }, { - "slug": "nz", - "name_en": "New Zealand", - "subtype": "country", "iso_code": "NZ", "iso_numeric": "554", + "name_en": "New Zealand", "parent": null, + "slug": "nz", + "subtype": "country", "tlds": [ "nz" ] }, { - "slug": "okinawa", - "name_en": "Okinawa", - "subtype": "subdivision", + "coordinates": { + "lat": 26.21222, + "lon": 127.68083 + }, + "info_link": "https://en.wikipedia.org/wiki/Okinawa_Prefecture", "iso_code": "JP-47", + "name_en": "Okinawa", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Okinawa_Prefecture", + "slug": "okinawa", + "subtype": "subdivision", "tlds": [ "okinawa" - ], - "coordinates": { - "lat": 26.21222, - "lon": 127.68083 - } + ] }, { - "slug": "om", - "name_en": "Oman", - "subtype": "country", "iso_code": "OM", "iso_numeric": "512", + "name_en": "Oman", "parent": null, + "slug": "om", + "subtype": "country", "tlds": [ "om", "xn--mgb9awbf" ] }, { - "slug": "osaka", - "name_en": "Osaka", - "subtype": "city", + "coordinates": { + "lat": 34.69375, + "lon": 135.50211 + }, + "info_link": "https://en.wikipedia.org/wiki/Osaka", "iso_code": null, + "name_en": "Osaka", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Osaka", + "slug": "osaka", + "subtype": "city", "tlds": [ "osaka" - ], - "coordinates": { - "lat": 34.69375, - "lon": 135.50211 - } + ] }, { - "slug": "pa", - "name_en": "Panama", - "subtype": "country", "iso_code": "PA", "iso_numeric": "591", + "name_en": "Panama", "parent": null, + "slug": "pa", + "subtype": "country", "tlds": [ "pa" ] }, { - "slug": "paris", - "name_en": "Paris", - "subtype": "city", + "coordinates": { + "lat": 48.85667, + "lon": 2.35222 + }, + "info_link": "https://en.wikipedia.org/wiki/Paris", "iso_code": null, + "name_en": "Paris", "parent": "fr", - "info_link": "https://en.wikipedia.org/wiki/Paris", + "slug": "paris", + "subtype": "city", "tlds": [ "paris" - ], - "coordinates": { - "lat": 48.85667, - "lon": 2.35222 - } + ] }, { - "slug": "pe", - "name_en": "Peru", - "subtype": "country", "iso_code": "PE", "iso_numeric": "604", + "name_en": "Peru", "parent": null, + "slug": "pe", + "subtype": "country", "tlds": [ "pe" ] }, { - "slug": "pf", - "name_en": "French Polynesia", - "subtype": "country", "iso_code": "PF", + "iso_designation": "dependent_territory", "iso_numeric": "258", + "name_en": "French Polynesia", "parent": "fr", + "slug": "pf", + "subtype": "country", "tlds": [ "pf" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "pg", - "name_en": "Papua New Guinea", - "subtype": "country", "iso_code": "PG", "iso_numeric": "598", + "name_en": "Papua New Guinea", "parent": null, + "slug": "pg", + "subtype": "country", "tlds": [ "pg" ] }, { - "slug": "ph", - "name_en": "Philippines", - "subtype": "country", "iso_code": "PH", "iso_numeric": "608", + "name_en": "Philippines", "parent": null, + "slug": "ph", + "subtype": "country", "tlds": [ "ph" ] }, { - "slug": "pk", - "name_en": "Pakistan", - "subtype": "country", "iso_code": "PK", "iso_numeric": "586", + "name_en": "Pakistan", "parent": null, + "slug": "pk", + "subtype": "country", "tlds": [ "pk", "xn--mgbai9azgqp6j" ] }, { - "slug": "pl", - "name_en": "Poland", - "subtype": "country", "iso_code": "PL", "iso_numeric": "616", + "name_en": "Poland", "parent": null, + "slug": "pl", + "subtype": "country", "tlds": [ "pl" ] }, { - "slug": "pm", - "name_en": "Saint Pierre and Miquelon", - "subtype": "country", "iso_code": "PM", + "iso_designation": "dependent_territory", "iso_numeric": "666", + "name_en": "Saint Pierre and Miquelon", "parent": "fr", + "slug": "pm", + "subtype": "country", "tlds": [ "pm" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "pn", - "name_en": "Pitcairn", - "subtype": "country", "iso_code": "PN", + "iso_designation": "dependent_territory", "iso_numeric": "612", + "name_en": "Pitcairn", "parent": "gb", + "slug": "pn", + "subtype": "country", "tlds": [ "pn" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "pr", - "name_en": "Puerto Rico", - "subtype": "country", "iso_code": "PR", + "iso_designation": "dependent_territory", "iso_numeric": "630", + "name_en": "Puerto Rico", "parent": "us", + "slug": "pr", + "subtype": "country", "tlds": [ "pr" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "ps", - "name_en": "Palestine, State of", - "subtype": "country", "iso_code": "PS", "iso_numeric": "275", + "name_en": "Palestine, State of", "parent": null, + "slug": "ps", + "subtype": "country", "tlds": [ "ps", "xn--ygbi2ammx" ] }, { - "slug": "pt", - "name_en": "Portugal", - "subtype": "country", "iso_code": "PT", "iso_numeric": "620", + "name_en": "Portugal", "parent": null, + "slug": "pt", + "subtype": "country", "tlds": [ "pt" ] }, { - "slug": "pw", - "name_en": "Palau", - "subtype": "country", "iso_code": "PW", "iso_numeric": "585", + "name_en": "Palau", "parent": null, + "slug": "pw", + "subtype": "country", "tlds": [ "pw" ] }, { - "slug": "py", - "name_en": "Paraguay", - "subtype": "country", "iso_code": "PY", "iso_numeric": "600", + "name_en": "Paraguay", "parent": null, + "slug": "py", + "subtype": "country", "tlds": [ "py" ] }, { - "slug": "qa", - "name_en": "Qatar", - "subtype": "country", "iso_code": "QA", "iso_numeric": "634", + "name_en": "Qatar", "parent": null, + "slug": "qa", + "subtype": "country", "tlds": [ "qa", "xn--wgbl6a" ] }, { - "slug": "quebec", - "name_en": "Quebec", - "subtype": "subdivision", + "coordinates": { + "lat": 52.0, + "lon": -72.0 + }, + "info_link": "https://en.wikipedia.org/wiki/Quebec", "iso_code": "CA-QC", + "name_en": "Quebec", "parent": "ca", - "info_link": "https://en.wikipedia.org/wiki/Quebec", + "slug": "quebec", + "subtype": "subdivision", "tlds": [ "quebec" - ], - "coordinates": { - "lat": 52.0, - "lon": -72.0 - } + ] }, { - "slug": "re", - "name_en": "Réunion", - "subtype": "country", + "coordinates": { + "lat": -21.11444, + "lon": 55.5325 + }, + "info_link": "https://en.wikipedia.org/wiki/Réunion", "iso_code": "RE", + "iso_designation": "dependent_territory", "iso_numeric": "638", + "name_en": "Réunion", "parent": "fr", + "slug": "re", + "subtype": "country", "tlds": [ "re" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "rio", - "name_en": "Rio de Janeiro", - "subtype": "city", + "coordinates": { + "lat": -22.91111, + "lon": -43.20556 + }, + "info_link": "https://en.wikipedia.org/wiki/Rio_de_Janeiro", "iso_code": null, + "name_en": "Rio de Janeiro", "parent": "br", - "info_link": "https://en.wikipedia.org/wiki/Rio_de_Janeiro", + "slug": "rio", + "subtype": "city", "tlds": [ "rio" - ], - "coordinates": { - "lat": -22.91111, - "lon": -43.20556 - } + ] }, { - "slug": "ro", - "name_en": "Romania", - "subtype": "country", "iso_code": "RO", "iso_numeric": "642", + "name_en": "Romania", "parent": null, + "slug": "ro", + "subtype": "country", "tlds": [ "ro" ] }, { - "slug": "rs", - "name_en": "Serbia", - "subtype": "country", "iso_code": "RS", "iso_numeric": "688", + "name_en": "Serbia", "parent": null, + "slug": "rs", + "subtype": "country", "tlds": [ "rs", "xn--90a3ac" ] }, { - "slug": "ru", - "name_en": "Russian Federation", - "subtype": "country", "iso_code": "RU", "iso_numeric": "643", + "name_en": "Russian Federation", "parent": null, + "slug": "ru", + "subtype": "country", "tlds": [ "ru", "xn--p1ai" ] }, { - "slug": "ruhr", - "name_en": "Ruhr", - "subtype": "subdivision", + "coordinates": { + "lat": 51.5, + "lon": 7.5 + }, + "info_link": "https://en.wikipedia.org/wiki/Ruhr", "iso_code": null, + "name_en": "Ruhr", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Ruhr", + "slug": "ruhr", + "subtype": "subdivision", "tlds": [ "ruhr" - ], - "coordinates": { - "lat": 51.5, - "lon": 7.5 - } + ] }, { - "slug": "rw", - "name_en": "Rwanda", - "subtype": "country", "iso_code": "RW", "iso_numeric": "646", + "name_en": "Rwanda", "parent": null, + "slug": "rw", + "subtype": "country", "tlds": [ "rw" ] }, { - "slug": "ryukyu", - "name_en": "Ryukyu Islands", - "subtype": "subdivision", + "coordinates": { + "lat": 26.33281, + "lon": 127.74902 + }, + "info_link": "https://en.wikipedia.org/wiki/Ryukyu_Islands", "iso_code": null, + "name_en": "Ryukyu Islands", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Ryukyu_Islands", + "slug": "ryukyu", + "subtype": "subdivision", "tlds": [ "ryukyu" - ], - "coordinates": { - "lat": 26.33281, - "lon": 127.74902 - } + ] }, { - "slug": "sa", - "name_en": "Saudi Arabia", - "subtype": "country", "iso_code": "SA", "iso_numeric": "682", + "name_en": "Saudi Arabia", "parent": null, + "slug": "sa", + "subtype": "country", "tlds": [ "sa", "xn--mgberp4a5d4ar" ] }, { - "slug": "saarland", - "name_en": "Saarland", - "subtype": "subdivision", + "coordinates": { + "lat": 49.37715, + "lon": 6.87838 + }, + "info_link": "https://en.wikipedia.org/wiki/Saarland", "iso_code": "DE-SL", + "name_en": "Saarland", "parent": "de", - "info_link": "https://en.wikipedia.org/wiki/Saarland", + "slug": "saarland", + "subtype": "subdivision", "tlds": [ "saarland" - ], - "coordinates": { - "lat": 49.37715, - "lon": 6.87838 - } + ] }, { - "slug": "sb", - "name_en": "Solomon Islands", - "subtype": "country", "iso_code": "SB", "iso_numeric": "090", + "name_en": "Solomon Islands", "parent": null, + "slug": "sb", + "subtype": "country", "tlds": [ "sb" ] }, { - "slug": "sc", - "name_en": "Seychelles", - "subtype": "country", "iso_code": "SC", "iso_numeric": "690", + "name_en": "Seychelles", "parent": null, + "slug": "sc", + "subtype": "country", "tlds": [ "sc" ] }, { - "slug": "scotland", - "name_en": "Scotland", - "subtype": "subdivision", + "coordinates": { + "lat": 57.0, + "lon": -5.0 + }, + "info_link": "https://en.wikipedia.org/wiki/Scotland", "iso_code": "GB-SCT", + "name_en": "Scotland", "parent": "gb", - "info_link": "https://en.wikipedia.org/wiki/Scotland", + "slug": "scotland", + "subtype": "subdivision", "tlds": [ "scot" - ], - "coordinates": { - "lat": 57.0, - "lon": -5.0 - } + ] }, { - "slug": "sd", - "name_en": "Sudan", - "subtype": "country", "iso_code": "SD", "iso_numeric": "729", + "name_en": "Sudan", "parent": null, + "slug": "sd", + "subtype": "country", "tlds": [ "sd", "xn--mgbpl2fh" ] }, { - "slug": "se", - "name_en": "Sweden", - "subtype": "country", "iso_code": "SE", "iso_numeric": "752", + "name_en": "Sweden", "parent": null, + "slug": "se", + "subtype": "country", "tlds": [ "se" ] }, { - "slug": "sg", - "name_en": "Singapore", - "subtype": "country", "iso_code": "SG", "iso_numeric": "702", + "name_en": "Singapore", "parent": null, + "slug": "sg", + "subtype": "country", "tlds": [ "sg", "xn--clchc0ea0b2g2a9gcd", @@ -2943,427 +2989,437 @@ ] }, { - "slug": "sh", - "name_en": "Saint Helena, Ascension and Tristan da Cunha", - "subtype": "country", "iso_code": "SH", + "iso_designation": "dependent_territory", "iso_numeric": "654", + "name_en": "Saint Helena, Ascension and Tristan da Cunha", "parent": "gb", + "slug": "sh", + "subtype": "country", "tlds": [ "sh" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "si", - "name_en": "Slovenia", - "subtype": "country", "iso_code": "SI", "iso_numeric": "705", + "name_en": "Slovenia", "parent": null, + "slug": "si", + "subtype": "country", "tlds": [ "si" ] }, { - "slug": "sj", - "name_en": "Svalbard and Jan Mayen", - "subtype": "country", + "coordinates": { + "lat": 78.15706, + "lon": 15.86426 + }, + "info_link": "https://en.wikipedia.org/wiki/Svalbard", "iso_code": "SJ", + "iso_designation": "dependent_territory", "iso_numeric": "744", + "name_en": "Svalbard and Jan Mayen", "parent": "no", + "slug": "sj", + "subtype": "country", "tlds": [ "sj" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "sk", - "name_en": "Slovakia", - "subtype": "country", "iso_code": "SK", "iso_numeric": "703", + "name_en": "Slovakia", "parent": null, + "slug": "sk", + "subtype": "country", "tlds": [ "sk" ] }, { - "slug": "sl", - "name_en": "Sierra Leone", - "subtype": "country", "iso_code": "SL", "iso_numeric": "694", + "name_en": "Sierra Leone", "parent": null, + "slug": "sl", + "subtype": "country", "tlds": [ "sl" ] }, { - "slug": "sm", - "name_en": "San Marino", - "subtype": "country", "iso_code": "SM", "iso_numeric": "674", + "name_en": "San Marino", "parent": null, + "slug": "sm", + "subtype": "country", "tlds": [ "sm" ] }, { - "slug": "sn", - "name_en": "Senegal", - "subtype": "country", "iso_code": "SN", "iso_numeric": "686", + "name_en": "Senegal", "parent": null, + "slug": "sn", + "subtype": "country", "tlds": [ "sn" ] }, { - "slug": "so", - "name_en": "Somalia", - "subtype": "country", "iso_code": "SO", "iso_numeric": "706", + "name_en": "Somalia", "parent": null, + "slug": "so", + "subtype": "country", "tlds": [ "so" ] }, { - "slug": "sr", - "name_en": "Suriname", - "subtype": "country", "iso_code": "SR", "iso_numeric": "740", + "name_en": "Suriname", "parent": null, + "slug": "sr", + "subtype": "country", "tlds": [ "sr" ] }, { - "slug": "ss", - "name_en": "South Sudan", - "subtype": "country", "iso_code": "SS", "iso_numeric": "728", + "name_en": "South Sudan", "parent": null, + "slug": "ss", + "subtype": "country", "tlds": [ "ss" ] }, { - "slug": "st", - "name_en": "Sao Tome and Principe", - "subtype": "country", "iso_code": "ST", "iso_numeric": "678", + "name_en": "Sao Tome and Principe", "parent": null, + "slug": "st", + "subtype": "country", "tlds": [ "st" ] }, { - "slug": "stockholm", - "name_en": "Stockholm", - "subtype": "city", + "coordinates": { + "lat": 59.32944, + "lon": 18.06861 + }, + "info_link": "https://en.wikipedia.org/wiki/Stockholm", "iso_code": null, + "name_en": "Stockholm", "parent": "se", - "info_link": "https://en.wikipedia.org/wiki/Stockholm", + "slug": "stockholm", + "subtype": "city", "tlds": [ "stockholm" - ], - "coordinates": { - "lat": 59.32944, - "lon": 18.06861 - } + ] }, { - "slug": "su", - "name_en": "Soviet Union", - "subtype": "country", "iso_code": null, + "iso_designation": "transitionally_reserved", "iso_numeric": null, + "name_en": "Soviet Union", "parent": null, + "slug": "su", + "subtype": "country", "tlds": [ "su" - ], - "iso_designation": "transitionally_reserved" + ] }, { - "slug": "sv", - "name_en": "El Salvador", - "subtype": "country", "iso_code": "SV", "iso_numeric": "222", + "name_en": "El Salvador", "parent": null, + "slug": "sv", + "subtype": "country", "tlds": [ "sv" ] }, { - "slug": "sx", - "name_en": "Sint Maarten (Dutch part)", - "subtype": "country", "iso_code": "SX", + "iso_designation": "dependent_territory", "iso_numeric": "534", + "name_en": "Sint Maarten (Dutch part)", "parent": "nl", + "slug": "sx", + "subtype": "country", "tlds": [ "sx" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "sy", - "name_en": "Syrian Arab Republic", - "subtype": "country", "iso_code": "SY", "iso_numeric": "760", + "name_en": "Syrian Arab Republic", "parent": null, + "slug": "sy", + "subtype": "country", "tlds": [ "sy", "xn--ogbpf8fl" ] }, { - "slug": "sydney", - "name_en": "Sydney", - "subtype": "city", + "coordinates": { + "lat": -33.86778, + "lon": 151.21 + }, + "info_link": "https://en.wikipedia.org/wiki/Sydney", "iso_code": null, + "name_en": "Sydney", "parent": "au", - "info_link": "https://en.wikipedia.org/wiki/Sydney", + "slug": "sydney", + "subtype": "city", "tlds": [ "sydney" - ], - "coordinates": { - "lat": -33.86778, - "lon": 151.21 - } + ] }, { - "slug": "sz", - "name_en": "Eswatini", - "subtype": "country", "iso_code": "SZ", "iso_numeric": "748", + "name_en": "Eswatini", "parent": null, + "slug": "sz", + "subtype": "country", "tlds": [ "sz" ] }, { - "slug": "taipei", - "name_en": "Taipei", - "subtype": "city", + "coordinates": { + "lat": 25.0375, + "lon": 121.5625 + }, + "info_link": "https://en.wikipedia.org/wiki/Taipei", "iso_code": null, + "name_en": "Taipei", "parent": "tw", - "info_link": "https://en.wikipedia.org/wiki/Taipei", + "slug": "taipei", + "subtype": "city", "tlds": [ "taipei" - ], - "coordinates": { - "lat": 25.0375, - "lon": 121.5625 - } + ] }, { - "slug": "tatarstan", - "name_en": "Tatarstan", - "subtype": "subdivision", + "coordinates": { + "lat": 55.55, + "lon": 50.93333 + }, + "info_link": "https://en.wikipedia.org/wiki/Tatarstan", "iso_code": "RU-TA", + "name_en": "Tatarstan", "parent": "ru", - "info_link": "https://en.wikipedia.org/wiki/Tatarstan", + "slug": "tatarstan", + "subtype": "subdivision", "tlds": [ "tatar" - ], - "coordinates": { - "lat": 55.55, - "lon": 50.93333 - } + ] }, { - "slug": "tc", - "name_en": "Turks and Caicos Islands", - "subtype": "country", "iso_code": "TC", + "iso_designation": "dependent_territory", "iso_numeric": "796", + "name_en": "Turks and Caicos Islands", "parent": "gb", + "slug": "tc", + "subtype": "country", "tlds": [ "tc" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "td", - "name_en": "Chad", - "subtype": "country", "iso_code": "TD", "iso_numeric": "148", + "name_en": "Chad", "parent": null, + "slug": "td", + "subtype": "country", "tlds": [ "td" ] }, { - "slug": "tf", - "name_en": "French Southern Territories", - "subtype": "country", "iso_code": "TF", + "iso_designation": "dependent_territory", "iso_numeric": "260", + "name_en": "French Southern Territories", "parent": "fr", + "slug": "tf", + "subtype": "country", "tlds": [ "tf" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "tg", - "name_en": "Togo", - "subtype": "country", "iso_code": "TG", "iso_numeric": "768", + "name_en": "Togo", "parent": null, + "slug": "tg", + "subtype": "country", "tlds": [ "tg" ] }, { - "slug": "th", - "name_en": "Thailand", - "subtype": "country", "iso_code": "TH", "iso_numeric": "764", + "name_en": "Thailand", "parent": null, + "slug": "th", + "subtype": "country", "tlds": [ "th", "xn--o3cw4h" ] }, { - "slug": "tj", - "name_en": "Tajikistan", - "subtype": "country", "iso_code": "TJ", "iso_numeric": "762", + "name_en": "Tajikistan", "parent": null, + "slug": "tj", + "subtype": "country", "tlds": [ "tj" ] }, { - "slug": "tk", - "name_en": "Tokelau", - "subtype": "country", + "coordinates": { + "lat": -9.16667, + "lon": -171.83333 + }, + "info_link": "https://en.wikipedia.org/wiki/Tokelau", "iso_code": "TK", + "iso_designation": "dependent_territory", "iso_numeric": "772", + "name_en": "Tokelau", "parent": "nz", + "slug": "tk", + "subtype": "country", "tlds": [ "tk" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "tl", - "name_en": "Timor-Leste", - "subtype": "country", "iso_code": "TL", "iso_numeric": "626", + "name_en": "Timor-Leste", "parent": null, + "slug": "tl", + "subtype": "country", "tlds": [ "tl" ] }, { - "slug": "tm", - "name_en": "Turkmenistan", - "subtype": "country", "iso_code": "TM", "iso_numeric": "795", + "name_en": "Turkmenistan", "parent": null, + "slug": "tm", + "subtype": "country", "tlds": [ "tm" ] }, { - "slug": "tn", - "name_en": "Tunisia", - "subtype": "country", "iso_code": "TN", "iso_numeric": "788", + "name_en": "Tunisia", "parent": null, + "slug": "tn", + "subtype": "country", "tlds": [ "tn", "xn--pgbs0dh" ] }, { - "slug": "to", - "name_en": "Tonga", - "subtype": "country", "iso_code": "TO", "iso_numeric": "776", + "name_en": "Tonga", "parent": null, + "slug": "to", + "subtype": "country", "tlds": [ "to" ] }, { - "slug": "tokyo", - "name_en": "Tokyo", - "subtype": "city", + "coordinates": { + "lat": 35.68944, + "lon": 139.69167 + }, + "info_link": "https://en.wikipedia.org/wiki/Tokyo", "iso_code": null, + "name_en": "Tokyo", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Tokyo", + "slug": "tokyo", + "subtype": "city", "tlds": [ "tokyo" - ], - "coordinates": { - "lat": 35.68944, - "lon": 139.69167 - } + ] }, { - "slug": "tr", - "name_en": "Türkiye", - "subtype": "country", "iso_code": "TR", "iso_numeric": "792", + "name_en": "Türkiye", "parent": null, + "slug": "tr", + "subtype": "country", "tlds": [ "tr" ] }, { - "slug": "tt", - "name_en": "Trinidad and Tobago", - "subtype": "country", "iso_code": "TT", "iso_numeric": "780", + "name_en": "Trinidad and Tobago", "parent": null, + "slug": "tt", + "subtype": "country", "tlds": [ "tt" ] }, { - "slug": "tv", - "name_en": "Tuvalu", - "subtype": "country", "iso_code": "TV", "iso_numeric": "798", + "name_en": "Tuvalu", "parent": null, + "slug": "tv", + "subtype": "country", "tlds": [ "tv" ] }, { - "slug": "tw", - "name_en": "Taiwan, Province of China", - "subtype": "country", "iso_code": "TW", "iso_numeric": "158", + "name_en": "Taiwan, Province of China", "parent": null, + "slug": "tw", + "subtype": "country", "tlds": [ "tw", "xn--kprw13d", @@ -3371,317 +3427,322 @@ ] }, { - "slug": "tyrol", - "name_en": "Tyrol", - "subtype": "subdivision", + "coordinates": { + "lat": 47.26667, + "lon": 11.4 + }, + "info_link": "https://en.wikipedia.org/wiki/Tyrol_(state)", "iso_code": "AT-7", + "name_en": "Tyrol", "parent": "at", - "info_link": "https://en.wikipedia.org/wiki/Tyrol_(state)", + "slug": "tyrol", + "subtype": "subdivision", "tlds": [ "tirol" - ], - "coordinates": { - "lat": 47.26667, - "lon": 11.4 - } + ] }, { - "slug": "tz", - "name_en": "Tanzania, United Republic of", - "subtype": "country", "iso_code": "TZ", "iso_numeric": "834", + "name_en": "Tanzania, United Republic of", "parent": null, + "slug": "tz", + "subtype": "country", "tlds": [ "tz" ] }, { - "slug": "ua", - "name_en": "Ukraine", - "subtype": "country", "iso_code": "UA", "iso_numeric": "804", + "name_en": "Ukraine", "parent": null, + "slug": "ua", + "subtype": "country", "tlds": [ "ua", "xn--j1amh" ] }, { - "slug": "ug", - "name_en": "Uganda", - "subtype": "country", "iso_code": "UG", "iso_numeric": "800", + "name_en": "Uganda", "parent": null, + "slug": "ug", + "subtype": "country", "tlds": [ "ug" ] }, { - "slug": "us", - "name_en": "United States", - "subtype": "country", "iso_code": "US", "iso_numeric": "840", + "name_en": "United States", "parent": null, + "slug": "us", + "subtype": "country", "tlds": [ "us" ] }, { - "slug": "uy", - "name_en": "Uruguay", - "subtype": "country", "iso_code": "UY", "iso_numeric": "858", + "name_en": "Uruguay", "parent": null, + "slug": "uy", + "subtype": "country", "tlds": [ "uy" ] }, { - "slug": "uz", - "name_en": "Uzbekistan", - "subtype": "country", "iso_code": "UZ", "iso_numeric": "860", + "name_en": "Uzbekistan", "parent": null, + "slug": "uz", + "subtype": "country", "tlds": [ "uz" ] }, { - "slug": "va", - "name_en": "Holy See (Vatican City State)", - "subtype": "country", "iso_code": "VA", "iso_numeric": "336", + "name_en": "Holy See (Vatican City State)", "parent": null, + "slug": "va", + "subtype": "country", "tlds": [ "va" ] }, { - "slug": "vc", - "name_en": "Saint Vincent and the Grenadines", - "subtype": "country", "iso_code": "VC", "iso_numeric": "670", + "name_en": "Saint Vincent and the Grenadines", "parent": null, + "slug": "vc", + "subtype": "country", "tlds": [ "vc" ] }, { - "slug": "ve", - "name_en": "Venezuela, Bolivarian Republic of", - "subtype": "country", "iso_code": "VE", "iso_numeric": "862", + "name_en": "Venezuela, Bolivarian Republic of", "parent": null, + "slug": "ve", + "subtype": "country", "tlds": [ "ve" ] }, { - "slug": "vegas", - "name_en": "Las Vegas", - "subtype": "city", + "coordinates": { + "lat": 36.16722, + "lon": -115.14861 + }, + "info_link": "https://en.wikipedia.org/wiki/Las_Vegas", "iso_code": null, + "name_en": "Las Vegas", "parent": "us", - "info_link": "https://en.wikipedia.org/wiki/Las_Vegas", + "slug": "vegas", + "subtype": "city", "tlds": [ "vegas" - ], - "coordinates": { - "lat": 36.16722, - "lon": -115.14861 - } + ] }, { - "slug": "vg", - "name_en": "Virgin Islands, British", - "subtype": "country", "iso_code": "VG", + "iso_designation": "dependent_territory", "iso_numeric": "092", + "name_en": "Virgin Islands, British", "parent": "gb", + "slug": "vg", + "subtype": "country", "tlds": [ "vg" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "vi", - "name_en": "Virgin Islands, U.S.", - "subtype": "country", "iso_code": "VI", + "iso_designation": "dependent_territory", "iso_numeric": "850", + "name_en": "Virgin Islands, U.S.", "parent": "us", + "slug": "vi", + "subtype": "country", "tlds": [ "vi" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "vn", - "name_en": "Viet Nam", - "subtype": "country", "iso_code": "VN", "iso_numeric": "704", + "name_en": "Viet Nam", "parent": null, + "slug": "vn", + "subtype": "country", "tlds": [ "vn" ] }, { - "slug": "vu", - "name_en": "Vanuatu", - "subtype": "country", "iso_code": "VU", "iso_numeric": "548", + "name_en": "Vanuatu", "parent": null, + "slug": "vu", + "subtype": "country", "tlds": [ "vu" ] }, { - "slug": "wales", - "name_en": "Wales", - "subtype": "subdivision", + "coordinates": { + "lat": 52.35, + "lon": -3.63333 + }, + "info_link": "https://en.wikipedia.org/wiki/Wales", "iso_code": "GB-WLS", + "name_en": "Wales", "parent": "gb", - "info_link": "https://en.wikipedia.org/wiki/Wales", + "slug": "wales", + "subtype": "subdivision", "tlds": [ "cymru", "wales" - ], - "coordinates": { - "lat": 52.35, - "lon": -3.63333 - } + ] }, { - "slug": "wf", - "name_en": "Wallis and Futuna", - "subtype": "country", "iso_code": "WF", + "iso_designation": "dependent_territory", "iso_numeric": "876", + "name_en": "Wallis and Futuna", "parent": "fr", + "slug": "wf", + "subtype": "country", "tlds": [ "wf" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "wien", - "name_en": "Vienna", - "subtype": "city", + "coordinates": { + "lat": 48.20833, + "lon": 16.3725 + }, + "info_link": "https://en.wikipedia.org/wiki/Vienna", "iso_code": null, + "name_en": "Vienna", "parent": "at", - "info_link": "https://en.wikipedia.org/wiki/Vienna", + "slug": "wien", + "subtype": "city", "tlds": [ "wien" - ], - "coordinates": { - "lat": 48.20833, - "lon": 16.3725 - } + ] }, { - "slug": "ws", - "name_en": "Samoa", - "subtype": "country", "iso_code": "WS", "iso_numeric": "882", + "name_en": "Samoa", "parent": null, + "slug": "ws", + "subtype": "country", "tlds": [ "ws" ] }, { - "slug": "ye", - "name_en": "Yemen", - "subtype": "country", "iso_code": "YE", "iso_numeric": "887", + "name_en": "Yemen", "parent": null, + "slug": "ye", + "subtype": "country", "tlds": [ "ye" ] }, { - "slug": "yokohama", - "name_en": "Yokohama", - "subtype": "city", + "coordinates": { + "lat": 35.45033, + "lon": 139.63422 + }, + "info_link": "https://en.wikipedia.org/wiki/Yokohama", "iso_code": null, + "name_en": "Yokohama", "parent": "jp", - "info_link": "https://en.wikipedia.org/wiki/Yokohama", + "slug": "yokohama", + "subtype": "city", "tlds": [ "yokohama" - ], - "coordinates": { - "lat": 35.45033, - "lon": 139.63422 - } + ] }, { - "slug": "yt", - "name_en": "Mayotte", - "subtype": "country", + "coordinates": { + "lat": -12.84306, + "lon": 45.13833 + }, + "info_link": "https://en.wikipedia.org/wiki/Mayotte", "iso_code": "YT", + "iso_designation": "dependent_territory", "iso_numeric": "175", + "name_en": "Mayotte", "parent": "fr", + "slug": "yt", + "subtype": "country", "tlds": [ "yt" - ], - "iso_designation": "dependent_territory" + ] }, { - "slug": "za", - "name_en": "South Africa", - "subtype": "country", "iso_code": "ZA", "iso_numeric": "710", + "name_en": "South Africa", "parent": null, + "slug": "za", + "subtype": "country", "tlds": [ "za" ] }, { - "slug": "zm", - "name_en": "Zambia", - "subtype": "country", "iso_code": "ZM", "iso_numeric": "894", + "name_en": "Zambia", "parent": null, + "slug": "zm", + "subtype": "country", "tlds": [ "zm" ] }, { - "slug": "zuerich", - "name_en": "Zurich", - "subtype": "city", + "coordinates": { + "lat": 47.37444, + "lon": 8.54111 + }, + "info_link": "https://en.wikipedia.org/wiki/Zurich", "iso_code": null, + "name_en": "Zurich", "parent": "ch", - "info_link": "https://en.wikipedia.org/wiki/Zurich", + "slug": "zuerich", + "subtype": "city", "tlds": [ "zuerich" - ], - "coordinates": { - "lat": 47.37444, - "lon": 8.54111 - } + ] }, { - "slug": "zw", - "name_en": "Zimbabwe", - "subtype": "country", "iso_code": "ZW", "iso_numeric": "716", + "name_en": "Zimbabwe", "parent": null, + "slug": "zw", + "subtype": "country", "tlds": [ "zw" ] diff --git a/data/manual/country-coordinates.json b/data/manual/country-coordinates.json new file mode 100644 index 00000000..37db387b --- /dev/null +++ b/data/manual/country-coordinates.json @@ -0,0 +1,86 @@ +{ + "ac": { + "info_link": "https://en.wikipedia.org/wiki/Ascension_Island", + "coordinates": { + "lat": -7.95, + "lon": -14.35 + } + }, + "bv": { + "info_link": "https://en.wikipedia.org/wiki/Bouvet_Island", + "coordinates": { + "lat": -54.42, + "lon": 3.36 + } + }, + "cc": { + "info_link": "https://en.wikipedia.org/wiki/Cocos_(Keeling)_Islands", + "coordinates": { + "lat": -12.1175, + "lon": 96.895 + } + }, + "cx": { + "info_link": "https://en.wikipedia.org/wiki/Christmas_Island", + "coordinates": { + "lat": -10.49, + "lon": 105.6275 + } + }, + "gf": { + "info_link": "https://en.wikipedia.org/wiki/French_Guiana", + "coordinates": { + "lat": 4.0, + "lon": -53.0 + } + }, + "gi": { + "info_link": "https://en.wikipedia.org/wiki/Gibraltar", + "coordinates": { + "lat": 36.14, + "lon": -5.35 + } + }, + "gp": { + "info_link": "https://en.wikipedia.org/wiki/Guadeloupe", + "coordinates": { + "lat": 16.2595, + "lon": -61.5605 + } + }, + "mq": { + "info_link": "https://en.wikipedia.org/wiki/Martinique", + "coordinates": { + "lat": 14.65, + "lon": -61.015 + } + }, + "re": { + "info_link": "https://en.wikipedia.org/wiki/Réunion", + "coordinates": { + "lat": -21.11444, + "lon": 55.5325 + } + }, + "sj": { + "info_link": "https://en.wikipedia.org/wiki/Svalbard", + "coordinates": { + "lat": 78.15706, + "lon": 15.86426 + } + }, + "tk": { + "info_link": "https://en.wikipedia.org/wiki/Tokelau", + "coordinates": { + "lat": -9.16667, + "lon": -171.83333 + } + }, + "yt": { + "info_link": "https://en.wikipedia.org/wiki/Mayotte", + "coordinates": { + "lat": -12.84306, + "lon": 45.13833 + } + } +} diff --git a/docs/memory/log/2026-05-17-tech-aliases.md b/docs/memory/log/2026-05-17-tech-aliases.md index d713d98d..09b439b9 100644 --- a/docs/memory/log/2026-05-17-tech-aliases.md +++ b/docs/memory/log/2026-05-17-tech-aliases.md @@ -12,7 +12,7 @@ A second manual-alias file, `data/manual/tech-aliases.json`, canonicalizes orgs. ## Why -A downstream consumer (how-domains-work) reverse-indexes TLDs by tech operator for an Ecosystem → Technical Operators page. Without dedup, "Identity Digital Limited" (309 TLDs) and "Identity Digital Inc." (83 TLDs) fragment what should be one entity at ~455 TLDs. The manager-alias plumbing solves the same problem for managers; this is the parallel mechanism for tech operators. +A downstream consumer reverse-indexes TLDs by tech operator for an Ecosystem → Technical Operators page. Without dedup, "Identity Digital Limited" (309 TLDs) and "Identity Digital Inc." (83 TLDs) fragment what should be one entity at ~455 TLDs. The manager-alias plumbing solves the same problem for managers; this is the parallel mechanism for tech operators. ## Shape diff --git a/docs/memory/log/2026-05-27-brand-status-pinned.md b/docs/memory/log/2026-05-27-brand-status-pinned.md index b4fd75b4..2e021e7e 100644 --- a/docs/memory/log/2026-05-27-brand-status-pinned.md +++ b/docs/memory/log/2026-05-27-brand-status-pinned.md @@ -21,7 +21,7 @@ The two ICANN sources answer different questions about "is this a Brand TLD": | Brand owner opened to general | `.gmo`, `.nexus` | Original brand owner (GMO Internet, Google) opted into general registration | | ICANN gtlds.json stale | `.baidu` | Still a closed Brand TLD operated by Baidu; gtlds.json `specification_13: false` is wrong | -For all 8, **the CSV is correct for current state**. Consumers wanting a brand-restricted filter (e.g. for the how-domains-work site) must use `annotations.registry_agreement_types`, NOT `specification_13`. +For all 8, **the CSV is correct for current state**. Consumers wanting a brand-restricted filter must use `annotations.registry_agreement_types`, NOT `specification_13`. - **Pinning test:** `tests/integration/test_agreements_integrity.py::test_known_brand_status_mismatches_are_pinned` locks the divergent set. New mismatches (or ICANN fixing one of the sources) surface as a test failure with a clear remediation message. - **README:** new "Interpreting the data" section documents this plus four other semantic nuances (`icann_translation_en`, `tld_unicode`, `delegated: false` retention, `language_code` derivation). diff --git a/docs/memory/log/2026-05-30-build-modes.md b/docs/memory/log/2026-05-30-build-modes.md new file mode 100644 index 00000000..656e8b3c --- /dev/null +++ b/docs/memory/log/2026-05-30-build-modes.md @@ -0,0 +1,20 @@ +--- +title: bin/build requires an explicit mode +summary: bare bin/build prints help; --preserve-asn (local, keep committed ASN) vs --all (full, refresh ASN from iptoasn, used by CI); stops a plain build silently churning ASN from a stale local snapshot +created: 2026-05-30 +author: Eric Case +tags: [bin-scripts, build, iptoasn, asn, ci] +--- + +# bin/build requires an explicit mode (2026-05-30) + +`bin/build` used to build unconditionally and read the local `data/source/iptoasn` snapshot, so any unrelated local build (e.g. refreshing places data) recomputed every nameserver IP's ASN and churned `asn`/`as_org` across ~290 per-TLD files plus `tlds.json` and `organizations.json`. The `--preserve-asn` flag (added in `40973e16`) avoided this, but it was opt-in, so the default `bin/build` kept re-introducing the churn. + +The change makes the mode mandatory: + +- **`bin/build`** (no args) and `-h`/`--help` print usage and exit 0; they build nothing. A bare invocation can no longer silently refresh ASN. +- **`bin/build --preserve-asn`** — build, keeping the ASN already in the committed `tlds.json` (`_asn_lookup_from_committed`, reads the on-disk file, so restore a flapped `tlds.json` *before* relying on it). Local/dev default. +- **`bin/build --all`** — full build, refreshing ASN from the local iptoasn file. The data-update workflow (`.github/workflows/update-data.yaml`) uses this; it is the only place ASN is meant to move. +- Unknown option → usage on stderr + exit 2. + +Also updated the Makefile help and the `README.md` "delete it and rebuilds it" line to `--preserve-asn`. Note: the script no longer forwards extra args to `src.cli` (it maps each mode to a fixed arg list). diff --git a/docs/memory/log/2026-05-30-country-coordinates.md b/docs/memory/log/2026-05-30-country-coordinates.md new file mode 100644 index 00000000..6068ab17 --- /dev/null +++ b/docs/memory/log/2026-05-30-country-coordinates.md @@ -0,0 +1,19 @@ +--- +title: Country point-coordinate overlay for no-polygon territories +summary: data/manual/country-coordinates.json overlays info_link + Wikidata P625 coordinates onto derived country records that have no map polygon; identity stays pycountry-derived +created: 2026-05-30 +author: Eric Case +tags: [places, coordinates, wikidata, build, maps] +--- + +# Country coordinate overlay (2026-05-30) + +Countries are derived mechanically from pycountry and were intentionally *areas* with no stored point ("rendered from geometry, so not here"). Downstream consumers need to render every ccTLD, but ~12 territories have **no boundary polygon** in the Natural Earth 50m dataset — either too small (`bv cc cx tk gi`), folded into their sovereign (`gf gp mq re yt` → France, `sj` → Norway), or non-ISO (`ac`). Those can only be shown as a **map pin**, which needs a lat/lon the geometry can't supply. + +The decision (driven by a downstream consumer's needs; augment over move): + +- **`data/manual/country-coordinates.json`** — editorial overlay keyed by country slug, each entry an `info_link` (Wikipedia URL) and, once fetched, `coordinates: {lat, lon}`. Currently the 12 no-polygon territories. +- **Augment, not move.** These slugs stay pycountry-derived countries; the build overlays only `info_link` + `coordinates` onto the existing record (`src/build/places.py:_overlay_country_coordinates`). Rejected the alternative of moving them into `data/manual/places.json` (the `claimed`-reroute), which would have dropped their derived `iso_numeric`/`iso_designation` and forced hand-maintaining identity fields — a drift surface. +- **Coordinates from Wikidata P625**, same mechanism as the 57 geo places. `scripts/fetch_place_coordinates.py` now processes both files: `places.json` (subtype-filtered) and the overlay (`subtypes=None`, no subtype field). Run `bin/fetch-coordinates` on demand; never in the build. + +**Why it matters:** revises the "countries carry no coordinates" invariant to "countries carry no coordinates *except* no-polygon territories, via an additive overlay." Scope is driven by the consumer's polygon coverage, but iana-data stays decoupled — the overlay is just an explicit editorial list, no Natural Earth knowledge upstream. diff --git a/docs/memory/memory-index.md b/docs/memory/memory-index.md index e1587352..cc5a987a 100644 --- a/docs/memory/memory-index.md +++ b/docs/memory/memory-index.md @@ -9,6 +9,8 @@ Agents: consult before suggesting layout, naming, dependencies, vendors, or conv - [Architecture](architecture.md) - current implementation: stack, layout, conventions ## Log (newest first) +- [2026-05-30 bin/build requires explicit mode](log/2026-05-30-build-modes.md) - bare bin/build prints help; --preserve-asn (local, keep committed ASN) vs --all (full ASN refresh, CI); stops silent ASN churn from a stale iptoasn snapshot +- [2026-05-30 Country coordinate overlay](log/2026-05-30-country-coordinates.md) - data/manual/country-coordinates.json overlays info_link + P625 coordinates onto no-polygon derived countries (bv cc cx tk gi gf gp mq re yt sj ac); augment not move, identity stays derived - [2026-05-27 Brand-status pinned](log/2026-05-27-brand-status-pinned.md) - specification_13 is application-era, CSV is current; 8 known mismatches pinned by test; README "Interpreting the data" added - [2026-05-27 IDN language](log/2026-05-27-idn-language.md) - language_code + language_name_en for all 151 IDNs via CLDR likelySubtags + per-(script, region) and per-TLD overrides; Han-CJK Simplified/Traditional/Taiwan distinctions - [2026-05-25 Tier 1 artifacts live](log/2026-05-25-tier1-artifacts-live.md) - all four typed-graph artifacts built and consumed; legacy alias files deleted; new annotation primitives added; supersedes 2026-05-24 SEED ONLY note diff --git a/scripts/fetch_place_coordinates.py b/scripts/fetch_place_coordinates.py index 060f1205..a633c20e 100644 --- a/scripts/fetch_place_coordinates.py +++ b/scripts/fetch_place_coordinates.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -"""Fetch geo-place coordinates from Wikidata into data/manual/places.json. - -For each place lacking lat/lon, looks up its Wikipedia article's P625 coordinate -and writes it back. Idempotent (--refresh forces); run on demand, not in the build. +"""Fetch geo-place coordinates from Wikidata into data/manual/places.json and +data/manual/country-coordinates.json, looking up each record's P625 coordinate via +its Wikipedia article. Idempotent (--refresh forces); run on demand, not the build. """ import argparse @@ -29,9 +28,9 @@ REQUEST_DELAY = 0.5 # politeness between Wikidata calls COORD_PRECISION = 5 # ~1 m; ample for a map pin -# data/manual/places.json holds only non-country geo places; every one is a -# point we pin. Countries are areas (rendered from geometry), so not here. -GEO_SUBTYPES = {"city", "subdivision", "supranational"} +# Point geo-places we pin; countries (areas) live elsewhere, except no-polygon +# territories via the country-coordinates overlay. frozenset: it's a default arg. +GEO_SUBTYPES = frozenset({"city", "subdivision", "supranational"}) def enwiki_title_from_url(info_link: str) -> str | None: @@ -87,13 +86,16 @@ def enrich_places( client: httpx.Client, *, refresh: bool, + subtypes: frozenset[str] | None = GEO_SUBTYPES, delay: float = REQUEST_DELAY, ) -> tuple[int, list[str]]: - """Add lat/lon to geo places in place. Returns (added_count, failed_slugs).""" + """Add lat/lon to records lacking them, in place. Returns (added, failed_slugs). + ``subtypes`` filters by the ``subtype`` field; None processes all (the overlay has none).""" pending = [ (slug, rec) for slug, rec in places.items() - if rec.get("subtype") in GEO_SUBTYPES and (refresh or "coordinates" not in rec) + if (subtypes is None or rec.get("subtype") in subtypes) + and (refresh or "coordinates" not in rec) ] added = 0 failed: list[str] = [] @@ -136,17 +138,34 @@ def main() -> int: ) args = parser.parse_args() - path = Path(MANUAL_DIR) / MANUAL_FILES["PLACES"] - places = read_json_file(path, default={}) + places_path = Path(MANUAL_DIR) / MANUAL_FILES["PLACES"] + places = read_json_file(places_path, default={}) if not places: - logger.error("no places loaded from %s", path) + logger.error("no places loaded from %s", places_path) return 1 + overlay_path = Path(MANUAL_DIR) / MANUAL_FILES["COUNTRY_COORDINATES"] + overlay = read_json_file(overlay_path, default={}) + failed: list[str] = [] + # 30s per request: Wikidata's wbgetentities is normally sub-second, so this only + # bounds a stalled connection on an interactive, maintenance-time run. with httpx.Client(timeout=30.0, follow_redirects=True) as client: - added, failed = enrich_places(places, client, refresh=args.refresh) + # Non-country geo places (cities, subdivisions, supranational regions). + added, place_failed = enrich_places(places, client, refresh=args.refresh) + _, status = write_json_if_changed(places_path, places) + logger.info("places.json: added=%d write=%s", added, status) + failed += place_failed + # Point overlay for no-polygon country territories (entries carry no subtype). + if overlay: + added, overlay_failed = enrich_places( + overlay, client, refresh=args.refresh, subtypes=None + ) + _, status = write_json_if_changed(overlay_path, overlay) + logger.info("country-coordinates.json: added=%d write=%s", added, status) + failed += overlay_failed + else: + logger.warning("country-coordinates: %s missing or empty", overlay_path) - _, status = write_json_if_changed(path, places) - logger.info("added=%d failed=%d write=%s", added, len(failed), status) if failed: logger.warning("no coordinates for: %s", ", ".join(sorted(failed))) return 0 diff --git a/src/build/places.py b/src/build/places.py index c26fd55b..d3de9c37 100644 --- a/src/build/places.py +++ b/src/build/places.py @@ -4,6 +4,9 @@ subdivisions, cities, and supranational regions come from the editorial data/manual/places.json (keyed by slug, carrying their own tlds[]). Dependent territories and the ISO special-status codes enrich the country records. + +data/manual/country-coordinates.json overlays a lat/lon + info_link onto derived +countries that have no boundary polygon (e.g. Bouvet), so consumers can pin them. """ import logging @@ -27,6 +30,7 @@ "pycountry (ISO 3166-1 / 3166-2)", "data/manual/places.json (editorial)", "data/manual/dependent-territories.json (editorial; ISO 3166-1)", + "data/manual/country-coordinates.json (editorial; point overlay)", ] # Delegated ccTLDs that are not ordinary sovereign countries. ISO 3166-1 @@ -38,10 +42,17 @@ } +def _ordered_place(record: dict) -> dict: + """Return ``record`` with its fields alphabetized, for one consistent order + across all record types (the byte-equality writer makes field order matter).""" + return {key: record[key] for key in sorted(record)} + + def build_places_json( tlds: list[dict], manual_places: dict[str, dict], dependent_territories: dict[str, list[str]], + country_coordinates: dict[str, dict], output_path: Path, ) -> tuple[bool, str]: """Combine derived country records with editorial places and write the file. @@ -51,6 +62,8 @@ def build_places_json( manual_places: Editorial subdivisions/cities/supranational, keyed by slug. dependent_territories: Map of sovereign slug to its list of dependent territory slugs (e.g. ``{"gb": ["ai", "bm", ...], ...}``). + country_coordinates: Point overlay keyed by slug (info_link + fetched + coordinates) for polygon-less territories. output_path: Destination for the generated artifact. Returns: @@ -58,8 +71,12 @@ def build_places_json( """ claimed = {tld for rec in manual_places.values() for tld in rec["tlds"]} countries = _build_countries(tlds, claimed, dependent_territories) + _overlay_country_coordinates(countries, country_coordinates) - records = [*countries.values(), *_manual_records(manual_places)] + records = [ + _ordered_place(rec) + for rec in (*countries.values(), *_manual_records(manual_places)) + ] records.sort(key=lambda r: r["slug"]) output = { @@ -130,6 +147,21 @@ def ensure(slug: str) -> dict: return by_slug +def _overlay_country_coordinates( + countries: dict[str, dict], overlay: dict[str, dict] +) -> None: + """Add `info_link` + `coordinates` from the overlay onto matching derived + countries (additive; identity stays derived). Unknown slugs are logged, skipped.""" + for slug, data in overlay.items(): + record = countries.get(slug) + if record is None: + logger.warning("country-coordinates: no country %r to overlay", slug) + continue + for field in ("info_link", "coordinates"): + if field in data: + record[field] = data[field] + + def _manual_records(manual_places: dict[str, dict]) -> list[dict]: """Normalize the editorial places into output records (sorted tlds). diff --git a/src/build/tlds.py b/src/build/tlds.py index 365a44a0..023433a1 100644 --- a/src/build/tlds.py +++ b/src/build/tlds.py @@ -116,6 +116,9 @@ def build_tlds_json( dependent_territories = read_json_file( Path(MANUAL_DIR) / MANUAL_FILES["DEPENDENT_TERRITORIES"], default={} ) + country_coordinates = read_json_file( + Path(MANUAL_DIR) / MANUAL_FILES["COUNTRY_COORDINATES"], default={} + ) manual_cultures = read_json_file( Path(MANUAL_DIR) / MANUAL_FILES["CULTURES"], default={} ) @@ -284,7 +287,11 @@ def build_tlds_json( ( "places.json", lambda: build_places_json( - tlds, manual_places, dependent_territories, output_paths.places_json + tlds, + manual_places, + dependent_territories, + country_coordinates, + output_paths.places_json, ), ), ( diff --git a/src/config.py b/src/config.py index d7d936b8..1909af0d 100644 --- a/src/config.py +++ b/src/config.py @@ -46,6 +46,7 @@ "ORGANIZATIONS": "organizations.json", "SUPPLEMENTAL_CCTLD_RDAP": "supplemental-cctld-rdap.json", "PLACES": "places.json", + "COUNTRY_COORDINATES": "country-coordinates.json", "CULTURES": "cultures.json", "DEPENDENT_TERRITORIES": "dependent-territories.json", } diff --git a/tests/build/test_places.py b/tests/build/test_places.py index 22ca26b8..c69d607b 100644 --- a/tests/build/test_places.py +++ b/tests/build/test_places.py @@ -7,7 +7,11 @@ import pytest from _pytest.monkeypatch import MonkeyPatch -from src.build.places import _manual_records +from src.build.places import ( + _manual_records, + _ordered_place, + _overlay_country_coordinates, +) from src.build.tlds import OutputPaths, build_tlds_json @@ -88,3 +92,46 @@ def test_manual_records_omits_coordinates_when_absent(): } ) assert "coordinates" not in out[0] + + +def test_overlay_country_coordinates_adds_fields_without_touching_identity(): + countries = {"cc": {"slug": "cc", "subtype": "country", "iso_numeric": "166"}} + overlay = { + "cc": { + "info_link": "https://en.wikipedia.org/wiki/Cocos_(Keeling)_Islands", + "coordinates": {"lat": -12.17, "lon": 96.83}, + } + } + _overlay_country_coordinates(countries, overlay) + assert countries["cc"]["coordinates"] == {"lat": -12.17, "lon": 96.83} + assert countries["cc"]["info_link"].endswith("Cocos_(Keeling)_Islands") + assert countries["cc"]["iso_numeric"] == "166" # identity stays derived + + +def test_overlay_country_coordinates_skips_unknown_slug(caplog): + countries: dict[str, dict] = {} + with caplog.at_level("WARNING"): + _overlay_country_coordinates( + countries, {"zz": {"coordinates": {"lat": 1.0, "lon": 2.0}}} + ) + assert countries == {} + assert "zz" in caplog.text # the skip is logged, not silent + + +def test_ordered_place_sorts_fields_alphabetically(): + out = _ordered_place({"tlds": ["cc"], "slug": "cc", "iso_numeric": "166"}) + assert list(out) == ["iso_numeric", "slug", "tlds"] + + +def test_no_polygon_territory_keeps_iso_numeric_and_gets_overlay(places): + # cc (Cocos) has no 50m polygon, so it carries a point overlay. Its identity + # (iso_numeric) must stay pycountry-derived, and the overlay info_link applies. + cc = places.by_slug["cc"] + assert cc["iso_numeric"] == "166" + assert cc["info_link"].endswith("Cocos_(Keeling)_Islands") + + +def test_place_records_have_alphabetical_fields(places): + # One consistent field order across every record type, applied at build time. + for rec in (places.by_slug["za"], places.by_slug["cc"], places.by_slug["durban"]): + assert list(rec) == sorted(rec) diff --git a/tests/test_fetch_place_coordinates.py b/tests/test_fetch_place_coordinates.py index 831ea8d7..ce3ab9a2 100644 --- a/tests/test_fetch_place_coordinates.py +++ b/tests/test_fetch_place_coordinates.py @@ -203,6 +203,32 @@ def test_enrich_places_skips_place_without_info_link(): assert failed == ["x"] +def test_enrich_places_subtypes_none_processes_subtypeless_entries(): + # The country-coordinates overlay entries carry an info_link but no subtype. + overlay: dict = { + "bv": {"info_link": "https://en.wikipedia.org/wiki/Bouvet_Island"}, + "tk": {"info_link": "https://en.wikipedia.org/wiki/Tokelau"}, + } + with _client(_coords_handler) as client: + added, failed = fpc.enrich_places( + overlay, client, refresh=False, subtypes=None, delay=0 + ) + assert added == 2 + assert failed == [] + assert overlay["bv"]["coordinates"]["lat"] == round(1.23456789, fpc.COORD_PRECISION) + + +def test_enrich_places_default_filter_skips_subtypeless_entries(): + # Guard: under the default GEO_SUBTYPES filter, a subtypeless overlay-style + # entry is not processed (so the two files don't cross-contaminate). + overlay: dict = {"bv": {"info_link": "https://en.wikipedia.org/wiki/Bouvet_Island"}} + with _client(_coords_handler) as client: + added, failed = fpc.enrich_places(overlay, client, refresh=False, delay=0) + assert added == 0 + assert failed == [] + assert "coordinates" not in overlay["bv"] + + def test_main_populates_places_file(tmp_path, monkeypatch): places_file = tmp_path / "places.json" places_file.write_text( diff --git a/tests/test_production_smoke.py b/tests/test_production_smoke.py index 4ea14e2f..e169c032 100644 --- a/tests/test_production_smoke.py +++ b/tests/test_production_smoke.py @@ -41,7 +41,7 @@ def test_cli_module_can_run(): This is how GitHub Actions runs the CLI: - make download-core → uv run python -m src.cli --download - make download-tld-pages → uv run python -m src.cli --download-tld-pages - - ./bin/build → generate-idn-mapping + uv run python -m src.cli --build + - ./bin/build --all → generate-idn-mapping + uv run python -m src.cli --build """ result = subprocess.run( [sys.executable, "-m", "src.cli", "--help"],