mirror of
https://github.com/nunocoracao/blowfish.git
synced 2026-10-10 22:09:31 +00:00
320 lines
6.8 KiB
JavaScript
320 lines
6.8 KiB
JavaScript
(function () {
|
|
var config = window.BlowfishLanguageRedirectConfig;
|
|
|
|
if (!config || config.enabled !== true) {
|
|
return;
|
|
}
|
|
|
|
function getStorage() {
|
|
if (!config.storageKey) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return window.localStorage;
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
var storage = getStorage();
|
|
|
|
function normalizeLanguageTag(value) {
|
|
if (typeof value !== "string") {
|
|
return "";
|
|
}
|
|
|
|
return value.trim().toLowerCase().replace(/_/g, "-");
|
|
}
|
|
|
|
function getBaseLanguage(value) {
|
|
var languageTag = normalizeLanguageTag(value);
|
|
|
|
if (!languageTag) {
|
|
return "";
|
|
}
|
|
|
|
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() {
|
|
if (!Array.isArray(config.translations)) {
|
|
return [];
|
|
}
|
|
|
|
return config.translations.filter(function (translation) {
|
|
return translation && translation.url && getTranslationTags(translation).length > 0;
|
|
});
|
|
}
|
|
|
|
var translations = getAvailableTranslations();
|
|
|
|
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 tags = getTranslationTags(translations[i]);
|
|
|
|
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;
|
|
}
|
|
|
|
try {
|
|
return storage.getItem(config.storageKey);
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function setStoredLanguage(language) {
|
|
if (!storage) {
|
|
return;
|
|
}
|
|
|
|
var languageTag = normalizeLanguageTag(language);
|
|
|
|
if (!languageTag) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
storage.setItem(config.storageKey, languageTag);
|
|
} catch (error) {
|
|
// Ignore storage errors so the language link keeps its normal behavior.
|
|
}
|
|
}
|
|
|
|
function getBrowserTranslation() {
|
|
var languages = [];
|
|
|
|
if (Array.isArray(navigator.languages)) {
|
|
languages = languages.concat(navigator.languages);
|
|
}
|
|
|
|
if (navigator.language) {
|
|
languages.push(navigator.language);
|
|
}
|
|
|
|
for (var i = 0; i < languages.length; i += 1) {
|
|
var translation = findBestTranslation(languages[i]);
|
|
|
|
if (translation) {
|
|
return translation;
|
|
}
|
|
}
|
|
|
|
if (config.fallbackLanguage) {
|
|
return findBestTranslation(config.fallbackLanguage);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function normalizePath(pathname) {
|
|
if (pathname.length > 1 && pathname.charAt(pathname.length - 1) === "/") {
|
|
return pathname.slice(0, -1);
|
|
}
|
|
|
|
return pathname;
|
|
}
|
|
|
|
function getUrl(value) {
|
|
try {
|
|
return new URL(value, window.location.origin);
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function redirectToTranslation(translation) {
|
|
if (!translation || !translation.url) {
|
|
return false;
|
|
}
|
|
|
|
var currentLanguage = getCanonicalTranslationTag({
|
|
lang: config.currentLanguage,
|
|
languageCode: config.currentLanguageCode
|
|
});
|
|
var targetLanguage = getCanonicalTranslationTag(translation);
|
|
|
|
if (currentLanguage && targetLanguage && currentLanguage === targetLanguage) {
|
|
return false;
|
|
}
|
|
|
|
var targetUrl = getUrl(translation.url);
|
|
|
|
if (!targetUrl || normalizePath(targetUrl.pathname) === normalizePath(window.location.pathname)) {
|
|
return false;
|
|
}
|
|
|
|
window.location.replace(targetUrl.href);
|
|
return true;
|
|
}
|
|
|
|
function redirectToLanguage(language) {
|
|
return redirectToTranslation(findBestTranslation(language));
|
|
}
|
|
|
|
function findTranslationByUrl(url) {
|
|
var linkUrl = getUrl(url);
|
|
|
|
if (!linkUrl) {
|
|
return null;
|
|
}
|
|
|
|
for (var i = 0; i < translations.length; i += 1) {
|
|
var translationUrl = getUrl(translations[i].url);
|
|
|
|
if (translationUrl && normalizePath(translationUrl.pathname) === normalizePath(linkUrl.pathname)) {
|
|
return translations[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function bindLanguageSwitcher() {
|
|
document.addEventListener("click", function (event) {
|
|
if (!event.target || !event.target.closest) {
|
|
return;
|
|
}
|
|
|
|
var link = event.target.closest(".translation a[href]");
|
|
|
|
if (!link) {
|
|
return;
|
|
}
|
|
|
|
var translation = findTranslationByUrl(link.href);
|
|
|
|
if (translation) {
|
|
setStoredLanguage(getCanonicalTranslationTag(translation));
|
|
}
|
|
});
|
|
}
|
|
|
|
function maybeRedirect() {
|
|
var storedLanguage = getStoredLanguage();
|
|
|
|
if (storedLanguage) {
|
|
redirectToLanguage(storedLanguage);
|
|
return;
|
|
}
|
|
|
|
if (config.browserRedirectHomeOnly === true && config.isHome !== true) {
|
|
return;
|
|
}
|
|
|
|
var browserTranslation = getBrowserTranslation();
|
|
|
|
if (browserTranslation) {
|
|
redirectToTranslation(browserTranslation);
|
|
}
|
|
}
|
|
|
|
bindLanguageSwitcher();
|
|
maybeRedirect();
|
|
})();
|