🌐 Preserve locale subtags in language redirects

This commit is contained in:
André Plöger committed 2026-05-10 11:14:37 -03:00
1 parent 3a86a7656e
commit 598905a36b
1 file changed
+120 -43
+120 -43
View File
@@ -24,19 +24,62 @@
return "";
}
return value.trim().toLowerCase();
return value.trim().toLowerCase().replace(/_/g, "-");
}
function normalizeLanguage(value) {
return normalizeLanguageTag(value).split("-")[0];
}
function getBaseLanguage(value) {
var languageTag = normalizeLanguageTag(value);
function getTranslationLanguage(translation) {
if (!translation) {
if (!languageTag) {
return "";
}
return normalizeLanguageTag(translation.lang || translation.languageCode);
return languageTag.split("-")[0];
}
function getTranslationTags(translation) {
if (!translation) {
return [];
}
var tags = [];
var values = [translation.lang, translation.languageCode];
for (var i = 0; i < values.length; i += 1) {
var languageTag = normalizeLanguageTag(values[i]);
if (languageTag && tags.indexOf(languageTag) === -1) {
tags.push(languageTag);
}
}
return tags;
}
function getCanonicalTranslationTag(translation) {
var tags = getTranslationTags(translation);
if (!tags.length) {
return "";
}
return tags.reduce(function (bestTag, languageTag) {
if (languageTag.split("-").length > bestTag.split("-").length) {
return languageTag;
}
return bestTag;
}, tags[0]);
}
function translationHasTag(translation, languageTag) {
var normalizedTag = normalizeLanguageTag(languageTag);
if (!normalizedTag) {
return false;
}
return getTranslationTags(translation).indexOf(normalizedTag) !== -1;
}
function getAvailableTranslations() {
@@ -45,45 +88,74 @@
}
return config.translations.filter(function (translation) {
return translation && translation.url && normalizeLanguage(translation.lang || translation.languageCode);
return translation && translation.url && getTranslationTags(translation).length > 0;
});
}
var translations = getAvailableTranslations();
function findTranslation(language) {
var languageTag = normalizeLanguageTag(language);
var baseLanguage = normalizeLanguage(language);
function findExactTranslation(languageTag) {
var normalizedTag = normalizeLanguageTag(languageTag);
if (!normalizedTag) {
return null;
}
for (var i = 0; i < translations.length; i += 1) {
if (translationHasTag(translations[i], normalizedTag)) {
return translations[i];
}
}
return null;
}
function findBaseTranslation(languageTag) {
var baseLanguage = getBaseLanguage(languageTag);
if (!baseLanguage) {
return null;
}
for (var i = 0; i < translations.length; i += 1) {
var translation = translations[i];
var tags = getTranslationTags(translations[i]);
if (
normalizeLanguageTag(translation.lang) === languageTag ||
normalizeLanguageTag(translation.languageCode) === languageTag
) {
return translation;
}
}
for (var j = 0; j < translations.length; j += 1) {
var baseTranslation = translations[j];
if (
normalizeLanguage(baseTranslation.lang) === baseLanguage ||
normalizeLanguage(baseTranslation.languageCode) === baseLanguage
) {
return baseTranslation;
for (var j = 0; j < tags.length; j += 1) {
if (getBaseLanguage(tags[j]) === baseLanguage) {
return translations[i];
}
}
}
return null;
}
function findBestTranslation(languageTag) {
var normalizedTag = normalizeLanguageTag(languageTag);
if (!normalizedTag) {
return null;
}
while (normalizedTag) {
var translation = findExactTranslation(normalizedTag);
if (translation) {
return translation;
}
var lastSubtagIndex = normalizedTag.lastIndexOf("-");
if (lastSubtagIndex === -1) {
break;
}
normalizedTag = normalizedTag.slice(0, lastSubtagIndex);
}
return findBaseTranslation(languageTag);
}
function getStoredLanguage() {
if (!storage || config.storedLanguageRedirect !== true) {
return null;
@@ -114,7 +186,7 @@
}
}
function getBrowserLanguage() {
function getBrowserTranslation() {
var languages = [];
if (Array.isArray(navigator.languages)) {
@@ -126,15 +198,15 @@
}
for (var i = 0; i < languages.length; i += 1) {
var baseLanguage = normalizeLanguage(languages[i]);
var translation = findBestTranslation(languages[i]);
if (findTranslation(baseLanguage)) {
return baseLanguage;
if (translation) {
return translation;
}
}
if (config.fallbackLanguage && findTranslation(config.fallbackLanguage)) {
return config.fallbackLanguage;
if (config.fallbackLanguage) {
return findBestTranslation(config.fallbackLanguage);
}
return null;
@@ -156,15 +228,16 @@
}
}
function redirectToLanguage(language) {
var translation = findTranslation(language);
function redirectToTranslation(translation) {
if (!translation || !translation.url) {
return false;
}
var currentLanguage = normalizeLanguageTag(config.currentLanguage || config.currentLanguageCode);
var targetLanguage = getTranslationLanguage(translation);
var currentLanguage = getCanonicalTranslationTag({
lang: config.currentLanguage,
languageCode: config.currentLanguageCode
});
var targetLanguage = getCanonicalTranslationTag(translation);
if (currentLanguage && targetLanguage && currentLanguage === targetLanguage) {
return false;
@@ -180,6 +253,10 @@
return true;
}
function redirectToLanguage(language) {
return redirectToTranslation(findBestTranslation(language));
}
function findTranslationByUrl(url) {
var linkUrl = getUrl(url);
@@ -213,7 +290,7 @@
var translation = findTranslationByUrl(link.href);
if (translation) {
setStoredLanguage(getTranslationLanguage(translation));
setStoredLanguage(getCanonicalTranslationTag(translation));
}
});
}
@@ -230,10 +307,10 @@
return;
}
var browserLanguage = getBrowserLanguage();
var browserTranslation = getBrowserTranslation();
if (browserLanguage) {
redirectToLanguage(browserLanguage);
if (browserTranslation) {
redirectToTranslation(browserTranslation);
}
}