/// <summary>
        /// Returns the path for a URL, minus the culture portion, and minus the query string.
        /// </summary>
        /// <param name="url">
        /// The URL (e.g., "http://www.rhythmagency.com/en-us/some-path?some=path").
        /// </param>
        /// <returns>
        /// The path, without the culture (e.g., "/some-path").
        /// </returns>
        public static string GetPathWithoutCulture(string url)
        {
            var path    = RhythmUrlParsing.GetPathFromUrl(url);
            var isMatch = CulturePrefixRegex.IsMatch(path);
            var newPath = isMatch
                ? CulturePrefixRegex.Replace(path, string.Empty)
                : path;

            return(newPath);
        }
        /// <summary>
        /// Prefixes a culture to a URL.
        /// </summary>
        /// <param name="url">
        /// The URL (e.g., "/about/company").
        /// </param>
        /// <param name="culture">
        /// The culture code (e.g., "en-us").
        /// </param>
        /// <returns>
        /// The URL with a prefixed culture (e.g., "/en-us/about/company").
        /// </returns>
        public static string PrefixCultureToUrl(string url, string culture)
        {
            var path = RhythmUrlParsing.GetPathAndQueryFromUrl(url) ?? string.Empty;

            if (path == "/" || path.StartsWith("/?"))
            {
                path = path.Substring(1);
            }
            path = $"/{culture}{path}";
            return(path);
        }
        /// <summary>
        /// Extracts the culture from the specified URL.
        /// </summary>
        /// <param name="url">
        /// The URL (e.g., "http://www.rhythmagency.com/en-us/some-path").
        /// </param>
        /// <param name="useDefault">
        /// Use the default culture as a fallback if a culture does not exist in the URL?
        /// </param>
        /// <returns>
        /// The culture (e.g., "en-us").
        /// </returns>
        /// <remarks>
        /// The URL doesn't need to include the domain.
        /// </remarks>
        public static string GetCultureFromUrl(string url, bool useDefault = true)
        {
            var path    = RhythmUrlParsing.GetPathFromUrl(url);
            var culture = CultureRegex.Match(path)?.Value;

            if (useDefault && Settings.ShouldExcludeDefaultCultureFromUrl() && string.IsNullOrEmpty(culture))
            {
                culture = Settings.GetDefaultCulture();
            }
            var hasCulture = !string.IsNullOrWhiteSpace(culture);

            return(hasCulture
                ? culture.ToLower()
                : null);
        }
        /// <summary>
        /// Extracts the region from the specified URL.
        /// </summary>
        /// <param name="url">
        /// The URL (e.g., "http://www.rhythmagency.com/en-us/some-path").
        /// </param>
        /// <returns>
        /// The region (e.g., "us").
        /// </returns>
        /// <remarks>
        /// The URL doesn't need to include the domain.
        /// </remarks>
        public static string GetRegionFromUrl(string url)
        {
            var path   = RhythmUrlParsing.GetPathFromUrl(url);
            var region = RegionRegex.Match(path)?.Value;

            if (Settings.ShouldExcludeDefaultCultureFromUrl() && string.IsNullOrEmpty(region))
            {
                var culture = Settings.GetDefaultCulture();
                if (!string.IsNullOrEmpty(culture) && culture.Length >= 2)
                {
                    region = culture.Substring(0, 2);
                }
            }
            var hasRegion = !string.IsNullOrWhiteSpace(region);

            return(hasRegion
                ? region.ToLower()
                : null);
        }