BEAM Lab Countries
BeamLabCountries is a collection of all sorts of useful information for every country in the ISO 3166 standard. It includes country data, subdivisions (states/provinces), international organizations, language information, and country name translations.
It is based on the data from the pretty popular but abandoned Elixir library Countries and previously the Ruby Gem Countries.
Installation
defp deps do
[
{:beamlab_countries, "~> 2.0"}
]
end
After you are done, run mix deps.get in your shell to fetch and compile beamlab_countries.
Documentation
Full documentation is available at HexDocs.
- BeamLabCountries - Main country API
- BeamLabCountries.Unions - International organizations
- BeamLabCountries.Languages - Languages and locales
- BeamLabCountries.Translations - Country name translations
- BeamLabCountries.Subdivisions - States/provinces
- BeamLabCountries.Cities - Major cities
Usage
Countries
Get all countries:
countries = BeamLabCountries.all()
Enum.count(countries)
# 250
Get a single country by alpha2 or alpha3 code:
country = BeamLabCountries.get("PL")
# %BeamLabCountries.Country{name: "Poland", alpha2: "PL", alpha3: "POL", ...}
country = BeamLabCountries.get_by_alpha3("DEU")
# %BeamLabCountries.Country{name: "Germany", alpha2: "DE", alpha3: "DEU", ...}
Filter countries by attribute:
# By region
countries = BeamLabCountries.filter_by(:region, "Europe")
Enum.count(countries)
# 51
# By currency
eurozone = BeamLabCountries.filter_by(:currency_code, "EUR")
# By continent
asian_countries = BeamLabCountries.filter_by(:continent, "Asia")
# By EU membership
eu_countries = BeamLabCountries.filter_by(:eu_member, true)
# By language (countries where English is spoken)
english_speaking = BeamLabCountries.filter_by(:languages_spoken, "en")
Enum.count(english_speaking)
# 168
Time zones are IANA identifiers, and can be filtered like any other attribute:
BeamLabCountries.get("EE").timezones
# ["Europe/Tallinn"]
BeamLabCountries.get("US").timezones |> length()
# 29
BeamLabCountries.get_by(:timezones, "Europe/Tallinn").alpha2
# "EE"
eu_member and eea_member are always booleans, so non-members can be filtered with
filter_by(:eu_member, false). Lookups return nil for unknown or non-string codes, while
filter_by/1,2, get_by/2 and exists?/2 raise ArgumentError for attributes that are
not fields of BeamLabCountries.Country:
BeamLabCountries.get(nil)
# nil
BeamLabCountries.filter_by(:regoin, "Europe")
# ** (ArgumentError) unknown country attribute: :regoin, expected one of: ...
Check if a country exists:
BeamLabCountries.exists?(:name, "Poland")
# true
BeamLabCountries.exists?(:alpha2, "XX")
# false
Subdivisions
Get subdivisions (states, provinces, regions) for a country:
country = BeamLabCountries.get("BR")
subdivisions = BeamLabCountries.Subdivisions.all(country)
Enum.count(subdivisions)
# 27
# Each subdivision includes id, name, translations, and geo data
hd(subdivisions)
# %BeamLabCountries.Subdivision{id: "AC", name: "Acre", ...}
Cities
Up to ten major cities for each of 244 countries and territories, plus the capital when
identified by GeoNames, with coordinates, time zones and names in 23 languages.
for_country/2 returns those ten largest places and still includes the capital when it
ranks lower. All 50 US states and all 13 Canadian provinces and territories have at least
ten populated places, including smaller towns and villages where needed.
Populations and translations follow GeoNames and can be incomplete or outdated.
name uses the preferred English name when available, otherwise the primary GeoNames name.
get_name/2 falls back to name; English locales always return name.
alias BeamLabCountries.Cities
Cities.capital("AT").name
# "Vienna"
Cities.for_country("DE") |> Enum.map(& &1.name) |> Enum.take(4)
# ["Berlin", "Hamburg", "Munich", "Cologne"]
Cities.for_country("US") |> length()
# 11 (the 10 largest cities, plus Washington D.C.)
Cities.for_country("US", limit: :all) |> length()
# 501 (every state, plus Washington D.C.)
Cities.for_subdivision("US", "CA", limit: 5) |> Enum.map(& &1.name)
# ["Los Angeles", "San Diego", "San Jose", "San Francisco", "Fresno"]
Cities.for_subdivision("CA", "ON", limit: 2) |> Enum.map(& &1.name)
# ["Toronto", "Ottawa"]
Cities.for_subdivision("CA", "PE", limit: 10) |> length()
# 10 (every Canadian province and territory has at least ten entries)
# Names differ by language: English, native and translated
vienna = Cities.capital("AT")
{vienna.name, vienna.native_name}
# {"Vienna", "Wien"}
Cities.get_name(vienna, "fr")
# "Vienne"
Cities.get_name(Cities.capital("CZ"), "de")
# "Prag"
# GeoNames ID lookup
Cities.get(2761369).population
# 1691468
City data comes from GeoNames, licensed under CC BY 4.0.
International Organizations (Unions)
Query international organizations and their member countries:
alias BeamLabCountries.Unions
# Get all unions
Unions.all()
# Returns 29 unions: EU, EEA, EFTA, NATO, G7, G20, APEC, ASEAN, Mercosur, USMCA, African Union,
# OPEC, OECD, BRICS, CIS, OIC, Pacific Alliance, Commonwealth, Arab League, GCC, Schengen,
# Eurozone, SCO, CARICOM, ECOWAS, SADC, EAC, Council of Europe and CPTPP
# Get a specific union
eu = Unions.get("eu")
# %BeamLabCountries.Union{code: "eu", name: "European Union", type: :economic_political, ...}
# Check union membership
Unions.member?("DE", "eu")
# true
Unions.member?("US", "nato")
# true
# Get all unions a country belongs to
Unions.for_country("DE")
# [%Union{code: "eu", ...}, %Union{code: "nato", ...}, %Union{code: "g7", ...}, ...]
Unions.codes_for_country("DE")
# ["eu", "eea", "nato", "g7", "g20", "oecd"]
# Get all member countries of a union
eu_countries = Unions.member_countries("eu")
Enum.count(eu_countries)
# 27
# Filter unions by type
military_unions = Unions.filter_by(:type, :military)
# [%Union{code: "nato", name: "North Atlantic Treaty Organization", ...}]
Languages
Look up language information by ISO 639-1 code:
alias BeamLabCountries.Languages
# Get language name
Languages.get_name("de")
# "German"
Languages.get_name("ja")
# "Japanese"
# Get native language name
Languages.get_native_name("de")
# "Deutsch"
Languages.get_native_name("zh")
# "中文 (Zhōngwén), 汉语, 漢語"
# Get full language info as struct
Languages.get("fr")
# %BeamLabCountries.Language{code: "fr", name: "French", native_name: "Français", family: "Indo-European"}
# Get all languages
Languages.all()
# [%Language{code: "aa", name: "Afar", ...}, ...]
Languages.count()
# 184
# Check if a language code is valid
Languages.valid?("en")
# true
Locales
Work with regional language variants (e.g., "en-US", "es-MX", "pt-BR"):
alias BeamLabCountries.Languages
# Get a locale with full details including flag and country name
locale = Languages.get_locale("en-US")
# %BeamLabCountries.Locale{
# code: "en-US",
# base_code: "en",
# region_code: "US",
# name: "English (United States)",
# native_name: "English (US)",
# flag: "🇺🇸",
# country_name: "United States of America"
# }
# Get all locales
Languages.all_locales()
# Returns 140 locales sorted by name
Languages.locale_count()
# 140
# Get all regional variants for a language
Languages.locales_for_language("en")
# [%Locale{code: "en-AU", ...}, %Locale{code: "en-CA", ...}, %Locale{code: "en-GB", ...}, %Locale{code: "en-US", ...}]
Languages.locales_for_language("es")
# [%Locale{code: "es-AR", ...}, %Locale{code: "es-ES", ...}, %Locale{code: "es-MX", ...}, ...]
# Parse a locale code
Languages.parse_locale("pt-BR")
# {"pt", "BR"}
# Check if a locale is valid
Languages.valid_locale?("en-US")
# true
Country-Language Associations
Find countries where a language is spoken:
alias BeamLabCountries.Languages
# Get all countries where English is spoken
countries = Languages.countries_for_language("en")
length(countries)
# 168
# Get just the country names
Languages.country_names_for_language("es")
# ["Argentina", "Bolivia", "Chile", "Colombia", "Costa Rica", "Cuba", ...]
# Get flags for countries where a language is spoken
Languages.flags_for_language("fr")
# ["🇧🇪", "🇧🇫", "🇧🇮", "🇧🇯", "🇨🇦", "🇨🇩", "🇨🇫", "🇨🇬", "🇨🇭", "🇨🇮", "🇨🇲", "🇫🇷", ...]
Country Name Translations
Get country names in different languages:
alias BeamLabCountries.Translations
# Get country name in a specific language
Translations.get_name("DE", "fr")
# "Allemagne"
Translations.get_name("JP", "de")
# "Japan"
Translations.get_name("US", "zh")
# "美国"
Translations.get_name("FR", "ar")
# "فرنسا"
# Regional locales are reduced to their language, and a fallback can be given
Translations.get_name("AT", "de-AT")
# "Österreich"
Translations.get_name("AT", "xx", fallback: "en")
# "Austria"
# Get country name in all supported languages
Translations.get_all_names("IT")
# %{"ar" => "إيطاليا", "de" => "Italien", "en" => "Italy", "es" => "Italia",
# "fr" => "Italie", "ja" => "イタリア", "ko" => "이탈리아", ...}
# Check supported locales
Translations.supported_locales()
# ["ar", "cs", "de", "en", "es", "et", "fr", "hi", "id", "it", "ja", "ko", "nl", "pl", "pt",
# "ro", "ru", "sv", "th", "tr", "uk", "vi", "zh"]
Translations.locale_supported?("ja")
# true
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request
Copyright and License
Copyright (c) 2025 Dmitri Don / BeamLab
Copyright (c) 2015-2025 Sebastian Szturo
This software is licensed under the MIT license.