mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	* Fix: Auto language detection #2122 * add LanguageService and AdditionalLanguageJsController * hidden swagger
This commit is contained in:
		
							parent
							
								
									68c9601245
								
							
						
					
					
						commit
						1a19024961
					
				@ -0,0 +1,65 @@
 | 
			
		||||
package stirling.software.SPDF.controller.api;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.PrintWriter;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.Hidden;
 | 
			
		||||
 | 
			
		||||
import jakarta.servlet.http.HttpServletResponse;
 | 
			
		||||
import stirling.software.SPDF.service.LanguageService;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/js")
 | 
			
		||||
public class AdditionalLanguageJsController {
 | 
			
		||||
 | 
			
		||||
    @Autowired private LanguageService languageService;
 | 
			
		||||
 | 
			
		||||
    @Hidden
 | 
			
		||||
    @GetMapping(value = "/additionalLanguageCode.js", produces = "application/javascript")
 | 
			
		||||
    public void generateAdditionalLanguageJs(HttpServletResponse response) throws IOException {
 | 
			
		||||
        List<String> supportedLanguages = languageService.getSupportedLanguages();
 | 
			
		||||
 | 
			
		||||
        response.setContentType("application/javascript");
 | 
			
		||||
        PrintWriter writer = response.getWriter();
 | 
			
		||||
 | 
			
		||||
        // Erstelle das JavaScript dynamisch
 | 
			
		||||
        writer.println("const supportedLanguages = " + toJsonArray(supportedLanguages) + ";");
 | 
			
		||||
 | 
			
		||||
        // Generiere die `getDetailedLanguageCode`-Funktion
 | 
			
		||||
        writer.println(
 | 
			
		||||
                """
 | 
			
		||||
                function getDetailedLanguageCode() {
 | 
			
		||||
                    const userLanguages = navigator.languages ? navigator.languages : [navigator.language];
 | 
			
		||||
                    for (let lang of userLanguages) {
 | 
			
		||||
                        let matchedLang = supportedLanguages.find(supportedLang => supportedLang.startsWith(lang.replace('-', '_')));
 | 
			
		||||
                        if (matchedLang) {
 | 
			
		||||
                            return matchedLang;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // Fallback
 | 
			
		||||
                    return "en_GB";
 | 
			
		||||
                }
 | 
			
		||||
                """);
 | 
			
		||||
 | 
			
		||||
        writer.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Hilfsfunktion zum Konvertieren der Liste in ein JSON-Array
 | 
			
		||||
    private String toJsonArray(List<String> list) {
 | 
			
		||||
        StringBuilder jsonArray = new StringBuilder("[");
 | 
			
		||||
        for (int i = 0; i < list.size(); i++) {
 | 
			
		||||
            jsonArray.append("\"").append(list.get(i)).append("\"");
 | 
			
		||||
            if (i < list.size() - 1) {
 | 
			
		||||
                jsonArray.append(",");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        jsonArray.append("]");
 | 
			
		||||
        return jsonArray.toString();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
package stirling.software.SPDF.service;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
public class LanguageService {
 | 
			
		||||
 | 
			
		||||
    private final PathMatchingResourcePatternResolver resourcePatternResolver =
 | 
			
		||||
            new PathMatchingResourcePatternResolver();
 | 
			
		||||
 | 
			
		||||
    public List<String> getSupportedLanguages() {
 | 
			
		||||
        List<String> supportedLanguages = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            Resource[] resources =
 | 
			
		||||
                    resourcePatternResolver.getResources("classpath*:messages_*.properties");
 | 
			
		||||
            for (Resource resource : resources) {
 | 
			
		||||
                if (resource.exists() && resource.isReadable()) {
 | 
			
		||||
                    String filename = resource.getFilename();
 | 
			
		||||
                    if (filename != null
 | 
			
		||||
                            && filename.startsWith("messages_")
 | 
			
		||||
                            && filename.endsWith(".properties")) {
 | 
			
		||||
                        String languageCode =
 | 
			
		||||
                                filename.replace("messages_", "").replace(".properties", "");
 | 
			
		||||
                        supportedLanguages.add(languageCode);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return supportedLanguages;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,89 +1,86 @@
 | 
			
		||||
document.addEventListener("DOMContentLoaded", function () {
 | 
			
		||||
  setLanguageForDropdown(".lang_dropdown-item");
 | 
			
		||||
 | 
			
		||||
  // Detect the browser's preferred language
 | 
			
		||||
  let browserLang = navigator.language || navigator.userLanguage;
 | 
			
		||||
  // Convert to a format consistent with your language codes (e.g., en-GB, fr-FR)
 | 
			
		||||
  browserLang = browserLang.replace("-", "_");
 | 
			
		||||
 | 
			
		||||
  // Check if the dropdown contains the browser's language
 | 
			
		||||
  const dropdownLangExists = document.querySelector(`.lang_dropdown-item[data-language-code="${browserLang}"]`);
 | 
			
		||||
 | 
			
		||||
  // Set the default language to browser's language or 'en_GB' if not found in the dropdown
 | 
			
		||||
  const defaultLocale = dropdownLangExists ? browserLang : "en_GB";
 | 
			
		||||
  const storedLocale = localStorage.getItem("languageCode") || defaultLocale;
 | 
			
		||||
 | 
			
		||||
  const dropdownItems = document.querySelectorAll(".lang_dropdown-item");
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < dropdownItems.length; i++) {
 | 
			
		||||
    const item = dropdownItems[i];
 | 
			
		||||
    item.classList.remove("active");
 | 
			
		||||
    if (item.dataset.languageCode === storedLocale) {
 | 
			
		||||
      item.classList.add("active");
 | 
			
		||||
    }
 | 
			
		||||
    item.addEventListener("click", handleDropdownItemClick);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
function getStoredOrDefaultLocale() {
 | 
			
		||||
  const storedLocale = localStorage.getItem("languageCode");
 | 
			
		||||
  return storedLocale || getDetailedLanguageCode();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setLanguageForDropdown(dropdownClass) {
 | 
			
		||||
  const defaultLocale = document.documentElement.getAttribute("data-language") || "en_GB";
 | 
			
		||||
  const storedLocale = localStorage.getItem("languageCode") || defaultLocale;
 | 
			
		||||
  const storedLocale = getStoredOrDefaultLocale();
 | 
			
		||||
  const dropdownItems = document.querySelectorAll(dropdownClass);
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < dropdownItems.length; i++) {
 | 
			
		||||
    const item = dropdownItems[i];
 | 
			
		||||
    item.classList.remove("active");
 | 
			
		||||
    if (item.dataset.languageCode === storedLocale) {
 | 
			
		||||
      item.classList.add("active");
 | 
			
		||||
    }
 | 
			
		||||
    item.addEventListener("click", handleDropdownItemClick);
 | 
			
		||||
  }
 | 
			
		||||
  dropdownItems.forEach(item => {
 | 
			
		||||
      item.classList.toggle("active", item.dataset.bsLanguageCode === storedLocale);
 | 
			
		||||
      item.removeEventListener("click", handleDropdownItemClick);
 | 
			
		||||
      item.addEventListener("click", handleDropdownItemClick);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateUrlWithLanguage(languageCode) {
 | 
			
		||||
  const currentURL = new URL(window.location.href);
 | 
			
		||||
  currentURL.searchParams.set('lang', languageCode);
 | 
			
		||||
  window.location.href = currentURL.toString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function handleDropdownItemClick(event) {
 | 
			
		||||
  event.preventDefault();
 | 
			
		||||
  const languageCode = event.currentTarget.dataset.bsLanguageCode; // change this to event.currentTarget
 | 
			
		||||
  const languageCode = event.currentTarget.dataset.bsLanguageCode;
 | 
			
		||||
  if (languageCode) {
 | 
			
		||||
    localStorage.setItem("languageCode", languageCode);
 | 
			
		||||
 | 
			
		||||
    const currentUrl = window.location.href;
 | 
			
		||||
    if (currentUrl.indexOf("?lang=") === -1 && currentUrl.indexOf("&lang=") === -1) {
 | 
			
		||||
      window.location.href = currentUrl + "?lang=" + languageCode;
 | 
			
		||||
    } else if (currentUrl.indexOf("&lang=") !== -1 && currentUrl.indexOf("?lang=") === -1) {
 | 
			
		||||
      window.location.href = currentUrl.replace(/&lang=\w{2,}/, "&lang=" + languageCode);
 | 
			
		||||
    } else {
 | 
			
		||||
      window.location.href = currentUrl.replace(/\?lang=\w{2,}/, "?lang=" + languageCode);
 | 
			
		||||
    }
 | 
			
		||||
      localStorage.setItem("languageCode", languageCode);
 | 
			
		||||
      updateUrlWithLanguage(languageCode);
 | 
			
		||||
  } else {
 | 
			
		||||
    console.error("Language code is not set for this item."); // for debugging
 | 
			
		||||
      console.error("Language code is not set for this item.");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
document.addEventListener("DOMContentLoaded", function () {
 | 
			
		||||
function checkUserLanguage(defaultLocale) {
 | 
			
		||||
  if (!localStorage.getItem("languageCode") || document.documentElement.getAttribute("data-language") != defaultLocale) {
 | 
			
		||||
      localStorage.setItem("languageCode", defaultLocale);
 | 
			
		||||
      updateUrlWithLanguage(defaultLocale);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  document.querySelectorAll(".col-lg-2.col-sm-6").forEach((element) => {
 | 
			
		||||
      const dropdownItems = element.querySelectorAll(".dropdown-item");
 | 
			
		||||
      const items = Array.from(dropdownItems).filter(item => !item.querySelector("hr.dropdown-divider"));
 | 
			
		||||
function initLanguageSettings() {
 | 
			
		||||
  document.addEventListener("DOMContentLoaded", function () {
 | 
			
		||||
      setLanguageForDropdown(".lang_dropdown-item");
 | 
			
		||||
 | 
			
		||||
      if (items.length <= 2) {
 | 
			
		||||
          if (
 | 
			
		||||
              element.previousElementSibling &&
 | 
			
		||||
              element.previousElementSibling.classList.contains("col-lg-2") &&
 | 
			
		||||
              element.previousElementSibling.classList.contains("nav-item-separator")
 | 
			
		||||
          ) {
 | 
			
		||||
              element.previousElementSibling.remove();
 | 
			
		||||
      const defaultLocale = getStoredOrDefaultLocale();
 | 
			
		||||
      checkUserLanguage(defaultLocale);
 | 
			
		||||
 | 
			
		||||
      const dropdownItems = document.querySelectorAll(".lang_dropdown-item");
 | 
			
		||||
      dropdownItems.forEach(item => {
 | 
			
		||||
          item.classList.toggle("active", item.dataset.bsLanguageCode === defaultLocale);
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function removeElements() {
 | 
			
		||||
  document.addEventListener("DOMContentLoaded", function () {
 | 
			
		||||
      document.querySelectorAll(".navbar-item").forEach((element) => {
 | 
			
		||||
          const dropdownItems = element.querySelectorAll(".dropdown-item");
 | 
			
		||||
          const items = Array.from(dropdownItems).filter(item => !item.querySelector("hr.dropdown-divider"));
 | 
			
		||||
 | 
			
		||||
          if (items.length <= 2) {
 | 
			
		||||
              if (
 | 
			
		||||
                  element.previousElementSibling &&
 | 
			
		||||
                  element.previousElementSibling.classList.contains("navbar-item") &&
 | 
			
		||||
                  element.previousElementSibling.classList.contains("nav-item-separator")
 | 
			
		||||
              ) {
 | 
			
		||||
                  element.previousElementSibling.remove();
 | 
			
		||||
              }
 | 
			
		||||
              element.remove();
 | 
			
		||||
          }
 | 
			
		||||
          element.remove();
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function sortLanguageDropdown() {
 | 
			
		||||
  document.addEventListener("DOMContentLoaded", function () {
 | 
			
		||||
      const dropdownMenu = document.querySelector('.dropdown-menu .dropdown-item.lang_dropdown-item').parentElement;
 | 
			
		||||
      if (dropdownMenu) {
 | 
			
		||||
        const items = Array.from(dropdownMenu.children).filter(child => child.matches('a'));
 | 
			
		||||
        items.sort((a, b) => a.dataset.bsLanguageCode.localeCompare(b.dataset.bsLanguageCode))
 | 
			
		||||
          .forEach(node => dropdownMenu.appendChild(node));
 | 
			
		||||
      }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  //Sort languages by alphabet
 | 
			
		||||
  const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(
 | 
			
		||||
    (child) => child.matches("a"),
 | 
			
		||||
  );
 | 
			
		||||
  list
 | 
			
		||||
    .sort(function (a, b) {
 | 
			
		||||
      return a.textContent.toUpperCase().localeCompare(b.textContent.toUpperCase());
 | 
			
		||||
    })
 | 
			
		||||
    .forEach((node) => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
 | 
			
		||||
});
 | 
			
		||||
sortLanguageDropdown();
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,11 @@
 | 
			
		||||
<div th:fragment="navbar" class="mx-auto">
 | 
			
		||||
  <script th:src="@{'/js/languageSelection.js'}"></script>
 | 
			
		||||
  <script th:src="@{'/js/additionalLanguageCode.js'}"></script>
 | 
			
		||||
  <script th:inline="javascript">
 | 
			
		||||
    // Initializing the scripts
 | 
			
		||||
    initLanguageSettings();
 | 
			
		||||
    removeElements();
 | 
			
		||||
  </script>
 | 
			
		||||
  <script th:inline="javascript">
 | 
			
		||||
    const currentVersion = /*[[${@appVersion}]]*/ '';
 | 
			
		||||
    const noFavourites = /*[[#{noFavourites}]]*/ '';
 | 
			
		||||
@ -36,7 +42,7 @@
 | 
			
		||||
                  <div class="container-fluid">
 | 
			
		||||
                    <div class="row">
 | 
			
		||||
                      <!-- Page tools menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.organize}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPdfs.tags', 'advance')}">
 | 
			
		||||
@ -73,7 +79,7 @@
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <!-- Convert to PDF menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.convertTo}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('img-to-pdf', 'image', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'image')}">
 | 
			
		||||
@ -95,7 +101,7 @@
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <!-- Convert from PDF menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.convertFrom}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-img', 'image', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'image')}">
 | 
			
		||||
@ -126,7 +132,7 @@
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <!-- Security menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.security}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('sign', 'signature', 'home.sign.title', 'home.sign.desc', 'sign.tags', 'sign')}">
 | 
			
		||||
@ -160,7 +166,7 @@
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <!-- View & Edit menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.edit}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('view-pdf', 'menu_book', 'home.viewPdf.title', 'home.viewPdf.desc', 'viewPdf.tags', 'other')}">
 | 
			
		||||
@ -196,14 +202,14 @@
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('get-info-on-pdf', 'info', 'home.getPdfInfo.title', 'home.getPdfInfo.desc', 'getPdfInfo.tags', 'other')}">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                                th:replace="~{fragments/navbarEntry :: navbarEntry ('remove-image-pdf','remove_selection', 'home.removeImagePdf.title', 'home.removeImagePdf.desc', 'removeImagePdf.tags', 'other')}">
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('remove-image-pdf','remove_selection', 'home.removeImagePdf.title', 'home.removeImagePdf.desc', 'removeImagePdf.tags', 'other')}">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                                th:replace="~{fragments/navbarEntry :: navbarEntry ('replace-and-invert-color-pdf','format_color_fill', 'replace-color.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('replace-and-invert-color-pdf','format_color_fill', 'replace-color.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <!-- Advance menu items -->
 | 
			
		||||
                      <div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                      <div class="navbar-item col-lg-2 col-sm-6 py px-xl-1 px-2">
 | 
			
		||||
                        <h6 class="menu-title" th:text="#{navbar.sections.advance}"></h6>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'advance')}">
 | 
			
		||||
@ -230,7 +236,7 @@
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-sections', 'grid_on', 'home.split-by-sections.title', 'home.split-by-sections.desc', 'split-by-sections.tags', 'advance')}">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                                th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-chapters', 'book', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdf-by-chapters', 'book', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                          th:replace="~{fragments/navbarEntry :: navbarEntry ('split-by-size-or-count', 'vertical_split', 'home.autoSizeSplitPDF.title', 'home.autoSizeSplitPDF.desc', 'autoSizeSplitPDF.tags', 'advance')}">
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,8 @@
 | 
			
		||||
  <head>
 | 
			
		||||
  <th:block th:insert="~{fragments/common :: head(title=#{login.title}, header=#{login.header})}"></th:block>
 | 
			
		||||
    <link rel="stylesheet" th:href="@{'/css/login.css'}">
 | 
			
		||||
    <script th:src="@{'/js/languageSelection.js'}"></script>
 | 
			
		||||
    <script th:src="@{'/js/additionalLanguageCode.js'}"></script>
 | 
			
		||||
  </head>
 | 
			
		||||
 | 
			
		||||
  <body>
 | 
			
		||||
@ -29,86 +31,28 @@
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          document.addEventListener('DOMContentLoaded', function() {
 | 
			
		||||
            const defaultLocale = getStoredOrDefaultLocale();
 | 
			
		||||
            checkUserLanguage(defaultLocale);
 | 
			
		||||
 | 
			
		||||
            const defaultLocale = document.documentElement.getAttribute('data-language') || 'en_GB';
 | 
			
		||||
            const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
 | 
			
		||||
 | 
			
		||||
            const currentURL = new URL(window.location.href);
 | 
			
		||||
            const urlParams = currentURL.searchParams;
 | 
			
		||||
            const currentLangParam = urlParams.get('lang') || defaultLocale;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (defaultLocale !== storedLocale && currentLangParam !== storedLocale) {
 | 
			
		||||
              urlParams.set('lang', storedLocale);
 | 
			
		||||
              currentURL.search = urlParams.toString();
 | 
			
		||||
              window.location.href = currentURL.toString();
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const dropdown = document.getElementById('languageDropdown');
 | 
			
		||||
            const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
 | 
			
		||||
 | 
			
		||||
            let activeItem;
 | 
			
		||||
 | 
			
		||||
            for (let i = 0; i < dropdownItems.length; i++) {
 | 
			
		||||
              const item = dropdownItems[i];
 | 
			
		||||
              item.classList.remove('active');
 | 
			
		||||
              if (item.dataset.bsLanguageCode === storedLocale) {
 | 
			
		||||
              if (item.dataset.bsLanguageCode === defaultLocale) {
 | 
			
		||||
                item.classList.add('active');
 | 
			
		||||
                activeItem = item;
 | 
			
		||||
              }
 | 
			
		||||
              item.addEventListener('click', handleDropdownItemClick);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const dropdown = document.getElementById('languageDropdown');
 | 
			
		||||
 | 
			
		||||
            if (activeItem) {
 | 
			
		||||
              dropdown.innerHTML = activeItem.innerHTML;  // This will set the dropdown button's content to the active language's flag and name
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Additional functionality that was in your provided code:
 | 
			
		||||
 | 
			
		||||
            document.querySelectorAll('.nav-item.dropdown').forEach((element) => {
 | 
			
		||||
              const dropdownMenu = element.querySelector(".dropdown-menu");
 | 
			
		||||
              if (dropdownMenu.id !== 'favoritesDropdown' &&  dropdownMenu.children.length <= 2 && dropdownMenu.querySelectorAll("hr.dropdown-divider").length === dropdownMenu.children.length) {
 | 
			
		||||
                if (element.previousElementSibling && element.previousElementSibling.classList.contains('nav-item') && element.previousElementSibling.classList.contains('nav-item-separator')) {
 | 
			
		||||
                  element.previousElementSibling.remove();
 | 
			
		||||
                }
 | 
			
		||||
                element.remove();
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Sort languages by alphabet
 | 
			
		||||
            const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
 | 
			
		||||
            list.sort(function(a, b) {
 | 
			
		||||
              var A = a.textContent.toUpperCase();
 | 
			
		||||
              var B = b.textContent.toUpperCase();
 | 
			
		||||
              return (A < B) ? -1 : (A > B) ? 1 : 0;
 | 
			
		||||
            }).forEach(node => document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').appendChild(node));
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          function handleDropdownItemClick(event) {
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
            const languageCode = event.currentTarget.dataset.bsLanguageCode;
 | 
			
		||||
            const dropdown = document.getElementById('languageDropdown');
 | 
			
		||||
 | 
			
		||||
            if (languageCode) {
 | 
			
		||||
              localStorage.setItem('languageCode', languageCode);
 | 
			
		||||
              const currentLang = document.documentElement.getAttribute('language');
 | 
			
		||||
              if (currentLang !== languageCode) {
 | 
			
		||||
                console.log("currentLang", currentLang)
 | 
			
		||||
                console.log("languageCode", languageCode)
 | 
			
		||||
                const currentUrl = window.location.href;
 | 
			
		||||
                if (currentUrl.indexOf("?lang=") === -1 && currentUrl.indexOf("&lang=") === -1) {
 | 
			
		||||
                  window.location.href = currentUrl + "?lang=" + languageCode;
 | 
			
		||||
                } else if (currentUrl.indexOf("&lang=") !== -1 && currentUrl.indexOf("?lang=") === -1) {
 | 
			
		||||
                  window.location.href = currentUrl.replace(/&lang=\w{2,}/, "&lang=" + languageCode);
 | 
			
		||||
                } else {
 | 
			
		||||
                  window.location.href = currentUrl.replace(/\?lang=\w{2,}/, "?lang=" + languageCode);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              dropdown.innerHTML = event.currentTarget.innerHTML;  // Update the dropdown button's content
 | 
			
		||||
            } else {
 | 
			
		||||
              console.error("Language code is not set for this item.");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        </script>
 | 
			
		||||
        <div class="text-center">
 | 
			
		||||
          <img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144">
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user