Drupal is a registered trademark of Dries Buytaert
drupal 11.4.2 Update released for Drupal core (11.4.2)! drupal 11.4.1 Update released for Drupal core (11.4.1)! drupal 11.4.0 Update released for Drupal core (11.4.0)! drupal 10.6.12 Update released for Drupal core (10.6.12)! drupal 11.3.13 Update released for Drupal core (11.3.13)! drupal 10.6.11 Update released for Drupal core (10.6.11)! drupal 11.3.12 Update released for Drupal core (11.3.12)! drupal 11.2.14 Update released for Drupal core (11.2.14)! drupal 10.5.12 Update released for Drupal core (10.5.12)! cms 2.1.3 Update released for Drupal core (2.1.3)! drupal 10.5.11 Update released for Drupal core (10.5.11)! drupal 11.3.11 Update released for Drupal core (11.3.11)! drupal 11.2.13 Update released for Drupal core (11.2.13)! drupal 10.6.10 Update released for Drupal core (10.6.10)! cms 2.1.2 Update released for Drupal core (2.1.2)! drupal 11.1.10 Update released for Drupal core (11.1.10)! drupal 10.5.10 Update released for Drupal core (10.5.10)! drupal 10.4.10 Update released for Drupal core (10.4.10)! drupal 11.2.12 Update released for Drupal core (11.2.12)! drupal 11.3.10 Update released for Drupal core (11.3.10)!

Reference data and tooling for Saudi Arabia's MOMRAH Unified Municipal Coding — regions → cities → districts — with Arabic/English names, dependent address fields, and a central address-resolution
service.

Data comes from the yasseralsamman/saudi-municipal-coding package (13 regions, 15,513 cities, 21,235 districts).

Installation

composer require yasseralsamman/saudi-municipal-coding
  drush en saudi_municipal_coding -y
  drush smc:import          # seed regions/cities/districts (idempotent)

You can also import from Configuration » Regional » Saudi Municipal Coding.

Drush commands:

Command Purpose drush smc:import Create/update SMC terms from the dataset. drush smc:import --purge Wipe and re-import. drush smc:purge Delete all SMC terms. drush smc:resolve <districtId> Resolve a full address (smoke test).

The taxonomy

Three vocabularies are installed: smc_region, smc_city, smc_district. Each term stores field_smc_id (the numeric municipal-coding ID) plus parent references. Because
municipal-coding district IDs are non-composite (plain integers, not encodable), the parent hierarchy is stored, not decoded: a smc_city references its region via field_parent_region,
and a smc_district references its city via field_parent_city and its region via field_parent_region (denormalized, always the parent city's region). Term names are
translatable (English default, Arabic translation).

The AddressResolver service

saudi_municipal_coding.address_resolver is the single source of address logic. Highlights:

$resolver = \Drupal::service('saudi_municipal_coding.address_resolver');

  // Full hierarchy from a district ID:
  $address = $resolver->resolveByDistrictId(1001);
  $address->fullName();        // "العليا، الرياض، منطقة الرياض" (current language)
  $address->region->smcId;     // 1

  // Lookups, hierarchy, search, validation:
  $resolver->getCity(3, 'ar');
  $resolver->getCitiesInRegion(1);
  $resolver->getDistrictsInCity(3);
  $resolver->getCityOfDistrict(1001);
  $resolver->getRegionOfDistrict(1001);
  $resolver->searchCities('Riy');
  $resolver->isValidHierarchy(1, 3, 1001);

Because a municipal-coding district ID cannot be decoded, resolveByDistrictId() requires the district term to exist (run the import first); an unknown ID resolves to NULL.

Adding dependent address fields to your entity

Attach plain entity reference fields to any entity (node, etc.) and wire the cascade through the field's reference settings + widget:

  1. Add a field_region reference field (target: taxonomy term, bundle smc_region). Reference method: default. Widget: SMC dependent term (cascading select).
  2. Add a field_city reference field (bundle smc_city). Reference method: SMC dependent (filter by parent term), and set Parent field machine name to
    field_region. Widget: SMC dependent term.
  3. Add a field_district reference field (bundle smc_district). Reference method SMC dependent, parent field field_city. Widget: SMC dependent term.

On the form, choosing a region filters the city options, and choosing a city filters the district options. The selection handler scopes the option list to the selected parent on both the initial render and live cascade, and
also rejects, on submit, any child that does not belong to the selected parent.

Searchable widget (select2)

The city and district lists are large (thousands of terms), so a plain select is hard to use. Enable the Saudi Municipal Coding — Searchable (select2) submodule (requires the href="https://www.drupal.org/project/select2">select2 module + library) to get a second widget, SMC dependent term (searchable, select2), which renders the same cascading, parent-scoped list with a search box. Both
widgets are available — pick either per field in Manage form display.

Duplicate district names

Some districts share a name. Across different cities this is harmless once the list is filtered to one city. A number of cities contain two districts with the identical name; for those, the district ID is appended to the
colliding option labels (e.g. Governmental (1055)) so they stay distinguishable. Unique labels are left untouched, and term names are not modified.

Activity

Total releases
1
First release
Jul 2026
Latest release
14 hours ago
Release cadence
Stability
0% stable

Releases

Version Type Release date
1.0.0-alpha1 Pre-release Jul 12, 2026