private function resolveLanId(): void
  {
    $codes = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? null);

    // If HTTP_ACCEPT_LANGUAGE is not set or empty return the default language.
    if (empty($codes)) $this->lanIdDefault;

    $map = Abc::$babel->getInternalLanguageMap();

    // Try to find the language code. Examples: en, en-US, zh, zh-Hans.
    // BTW We assume HTTP_ACCEPT_LANGUAGE is sorted properly.
    foreach ($codes as &$code)
    {
      // The official language code for Dutch in the Netherlands is nl-NL (with hyphen). But in practice we encounter
      // nl_NL, nl_nl, nl-nl. Therefore, internal language codes are in lower case and with hyphen.

      // Remove sorting weight, replace underscore with dash, and convert to lower case.
      $code = strtolower(str_replace('_', '-', strtok($code, ';')));

      if (isset($map[$code]))
      {
        $this->lanId = $map[$code];

        return;
      }
    }

    // We did not find the language code. Try without county code. Examples: en, zh.
    foreach ($codes as $code)
    {
      $code = substr($code, 0, 2);

      if (isset($map[$code]))
      {
        $this->lanId = $map[$code];

        return;
      }
    }

    // We did not find the language code. Use the ID of the default language.
    $this->lanId = $this->lanIdDefault;
  }