diff --git a/_includes/2020/templates/Head.php b/_includes/2020/templates/Head.php index 769a9294..4c4cb9ae 100644 --- a/_includes/2020/templates/Head.php +++ b/_includes/2020/templates/Head.php @@ -39,10 +39,7 @@ static function render($fields = []) { // Redirect to /en/... if not a supported locale; this needs to be emitted // as a HTTP header before first content byte. if(Locale::invalidLocale()) { - if(preg_match('/^\\/[^\/]+\\/(.+)$/', $_SERVER['REQUEST_URI'], $matches)) { - header("Location: /" . Locale::DEFAULT_LOCALE . "/" . $matches[1]); - return; - } + Locale::redirectLocale(); } ?> diff --git a/_includes/2020/templates/Menu.php b/_includes/2020/templates/Menu.php index c6cdf1b6..04c7c40a 100644 --- a/_includes/2020/templates/Menu.php +++ b/_includes/2020/templates/Menu.php @@ -35,7 +35,7 @@ public static function render(array $fields): void { /** * Modify link of the current URL for a given UI language. - * Skip if current URL isn't localized (e.g. _legacy) + * If current URL isn't localized (e.g. _legacy or no BCP-47 in path), return original URL * @param language - language tag to use * @return string - modified URL */ @@ -45,14 +45,16 @@ private static function change_ui_language($language): string { $parts = parse_url($url); $path = ''; - // Replace language if current language in path is valid BCP-47 + // Replace $path[1] if a fallback locale of $language is in DISPLAY_NAMES if (!empty($parts['path'])) { $path = explode("/", $parts['path']); - if ($path[1] == Locale::pageLocale()) { + $matchingLanguages = isset($path[1]) ? + array_intersect(Locale::calculateFallbackLocales($path[1]), array_keys(DISPLAY_NAMES)) : []; + if (count($matchingLanguages) > 0) { $path[1] = $language; - } else if (preg_match('/^\/(_legacy)\/.*$/i', $path[1], $matches)) { + } else if (preg_match('/^(?!_legacy|go|mac|web)([^\/]+)$/i', $path[1], $matches)) { // original URL didn't have a valid BCP-47, so insert new langage - // Skip for certain paths like: _legacy + // Skip for certain paths like: _legacy or 2-3 letter paths array_splice($path, 1, 0, $language); } } diff --git a/_includes/locale/Locale.php b/_includes/locale/Locale.php index 558bba75..6dedab63 100644 --- a/_includes/locale/Locale.php +++ b/_includes/locale/Locale.php @@ -62,22 +62,39 @@ public static function invalidLocale() { return self::$invalidLocale; } + /** + * Redirect page to specified locale. Default to en + * @param $newLocale + */ + public static function redirectLocale($newLocale = Locale::DEFAULT_LOCALE) { + if(preg_match('/^\\/[^\/]+\\/(.+)$/', $_SERVER['REQUEST_URI'], $matches)) { + header("Location: /" . $newLocale . "/" . $matches[1]); + return; + } + } + /** * Set the current locale based on the first path component * //rest/of/path for the current page URL */ private static function setLocaleFromURL() { // First component of the URL is always the locale - if(preg_match('/^\\/(([a-z]{2,3})(-([A-Za-z]{4}))?(-([a-z]{2}|[0-9]{3}))?)\\//', $_SERVER['REQUEST_URI'], $matches)) { - if(!isset(DISPLAY_NAMES[$matches[1]])) { + if(preg_match('/^\/(([a-z]{2,3})(-([A-Z][a-z]{3}))?(-([A-Z]{2}|[0-9]{3}))?)\//', $_SERVER['REQUEST_URI'], $matches)) { + $fallbackLocales = self::calculateFallbackLocales($matches[1]); + if (isset($fallbackLocales[0])) { + $pageLocale = $fallbackLocales[0]; + if ($pageLocale != $matches[1]) { + // Redirect if using a fallback locale + Locale::redirectLocale($pageLocale); + }; + } else { // Note: this is an unsupported locale, so we'll end up redirecting in head.php to /en/... $pageLocale = Locale::DEFAULT_LOCALE; self::$invalidLocale = true; - } else { - $pageLocale = $matches[1]; } } else { $pageLocale = Locale::DEFAULT_LOCALE; + // Don't set invalidLocale so pages like /_test/ work } self::setLocale($pageLocale); } @@ -178,7 +195,7 @@ public static function definePageScope($define, $id) { * @param $locale - the locale to determine fallback locales * @return array of fallback locales */ - private static function calculateFallbackLocales($locale) { + public static function calculateFallbackLocales($locale) { // Start with the given locale $fallback = [$locale]; diff --git a/build.sh b/build.sh index 09a113d6..6db57502 100755 --- a/build.sh +++ b/build.sh @@ -38,7 +38,7 @@ function preprocess_htaccess() { local locales localesregex locales=($(cat ./_includes/locale/locales.json | grep '"' | cut -d\" -f 2 -)) localesregex=$(IFS=\| ; echo "${locales[*]}") - sed -e "s/@locales/${localesregex}/g" .htaccess.in >> .htaccess + sed -e "s/(@locales)/(([a-z]{2,3})(-([A-Z][a-z]{3}))?(-([A-Z]{2}|[0-9]{3}))?)/g" .htaccess.in >> .htaccess } function do_configure() {