How does Drupal identify a language from the requested URL?

The Citead team, updated

In short. Drupal selects a URL language by matching either the first path segment or the request hostname with configured language values.

Definition: Drupal's URL language negotiation method identifies a configured language from either the first path segment or the request hostname. The selected mode is stored in the URL negotiation configuration, alongside the language-specific prefixes and domains.

Key facts

  • Drupal's LanguageNegotiationUrl plugin describes its job as identifying language via a URL prefix or domain and supports interface, content, and URL language types in its plugin declaration. The 11.x implementation documents these roles.
  • The plugin has two source values: path_prefix for a path prefix and domain for a domain. Its configuration schema calls the URL setting “Language from the URL (Path prefix or domain).”
  • In prefix mode, Drupal decodes the request path, takes its first slash-separated part, and compares it with the configured prefixes of added languages.
  • In domain mode, Drupal reads the request host without its port and compares it with the host parsed from each configured language domain.

How does path-prefix detection work?

The implementation reads language.negotiation.url.source. When that value selects path_prefix, it applies urldecode() to the trimmed path, splits the result at /, and removes the first part as the candidate prefix. Drupal then iterates over the languages returned by its language manager. A language is selected when it has a configured prefix and that prefix equals the candidate. The method returns that language's identifier.

The same mode also changes path processing. During inbound processing, Drupal removes the first path part when it matches a configured language prefix, then rebuilds the remaining path with a leading slash. During outbound processing, a language object with a configured prefix adds that prefix, followed by /, to the URL options. The outbound method adds the languages:url cache context when it adds a prefix.

The two mode names are defined in the implementation as follows:

const CONFIG_PATH_PREFIX = 'path_prefix';
const CONFIG_DOMAIN = 'domain';

How does hostname detection work?

When the source is domain, Drupal obtains the request host and checks each added language with a non-empty configured domain. Before comparing, it removes an http:// or https:// prefix from the configured value, prepends http://, and passes the result to parse_url() with PHP_URL_HOST. The request host and parsed configured host are compared exactly. The first matching language supplies the language identifier.

For links generated for another configured domain, the outbound method sets the URL as absolute when the current request host differs. It builds the base URL from the current request scheme and the target language's configured domain. The implementation retains a port when one is present, applies an explicit HTTPS or HTTP option, and appends Drupal's base path. It adds languages:url and url.site cache contexts when it changes the base URL.

Where are the settings represented?

Drupal's language module schema defines language.negotiation.url as a mapping with source, prefixes, and domains. The schema labels prefixes as a sequence of strings called path prefixes and domains as a sequence of strings called domains. The implementation uses the language identifier as the key when it looks up each prefix or domain, so the configured value must be associated with a language that Drupal has added.

The schema exposes the structure without selecting a mode:

url:
  source:
  prefixes:
  domains:

An unrecognized path prefix or hostname leaves this URL negotiation method without a selected language. The source files do not document a fallback language in this method itself.

FAQ

Does Drupal use both a path prefix and a hostname at the same time?

The implementation selects one source from language.negotiation.url.source and branches to either path_prefix or domain. The two values are separate configuration modes.

Does a hostname match include the port number?

Drupal reads the request host without the port before comparing it with the parsed configured host. Outbound URL generation can retain a port when it builds a base URL.

Sources

  1. Drupal, "LanguageNegotiationUrl.php", 11.x
  2. Drupal, "language.schema.yml", 11.x

Check how a page reads to answer engines. Open the GEO score analyzer

Test a page and see what to fix first

The analysis usually takes less than 10 seconds and needs no account.

400,000+ pages scored in the public benchmark