mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-10-25 11:17:28 +02: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 () { | function getStoredOrDefaultLocale() { | ||||||
|   setLanguageForDropdown(".lang_dropdown-item"); |   const storedLocale = localStorage.getItem("languageCode"); | ||||||
| 
 |   return storedLocale || getDetailedLanguageCode(); | ||||||
|   // 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 setLanguageForDropdown(dropdownClass) { | function setLanguageForDropdown(dropdownClass) { | ||||||
|   const defaultLocale = document.documentElement.getAttribute("data-language") || "en_GB"; |   const storedLocale = getStoredOrDefaultLocale(); | ||||||
|   const storedLocale = localStorage.getItem("languageCode") || defaultLocale; |  | ||||||
|   const dropdownItems = document.querySelectorAll(dropdownClass); |   const dropdownItems = document.querySelectorAll(dropdownClass); | ||||||
| 
 | 
 | ||||||
|   for (let i = 0; i < dropdownItems.length; i++) { |   dropdownItems.forEach(item => { | ||||||
|     const item = dropdownItems[i]; |       item.classList.toggle("active", item.dataset.bsLanguageCode === storedLocale); | ||||||
|     item.classList.remove("active"); |       item.removeEventListener("click", handleDropdownItemClick); | ||||||
|     if (item.dataset.languageCode === storedLocale) { |       item.addEventListener("click", handleDropdownItemClick); | ||||||
|       item.classList.add("active"); |   }); | ||||||
|     } | } | ||||||
|     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) { | function handleDropdownItemClick(event) { | ||||||
|   event.preventDefault(); |   event.preventDefault(); | ||||||
|   const languageCode = event.currentTarget.dataset.bsLanguageCode; // change this to event.currentTarget
 |   const languageCode = event.currentTarget.dataset.bsLanguageCode; | ||||||
|   if (languageCode) { |   if (languageCode) { | ||||||
|     localStorage.setItem("languageCode", languageCode); |       localStorage.setItem("languageCode", languageCode); | ||||||
| 
 |       updateUrlWithLanguage(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); |  | ||||||
|     } |  | ||||||
|   } else { |   } 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) => { | function initLanguageSettings() { | ||||||
|       const dropdownItems = element.querySelectorAll(".dropdown-item"); |   document.addEventListener("DOMContentLoaded", function () { | ||||||
|       const items = Array.from(dropdownItems).filter(item => !item.querySelector("hr.dropdown-divider")); |       setLanguageForDropdown(".lang_dropdown-item"); | ||||||
| 
 | 
 | ||||||
|       if (items.length <= 2) { |       const defaultLocale = getStoredOrDefaultLocale(); | ||||||
|           if ( |       checkUserLanguage(defaultLocale); | ||||||
|               element.previousElementSibling && | 
 | ||||||
|               element.previousElementSibling.classList.contains("col-lg-2") && |       const dropdownItems = document.querySelectorAll(".lang_dropdown-item"); | ||||||
|               element.previousElementSibling.classList.contains("nav-item-separator") |       dropdownItems.forEach(item => { | ||||||
|           ) { |           item.classList.toggle("active", item.dataset.bsLanguageCode === defaultLocale); | ||||||
|               element.previousElementSibling.remove(); |       }); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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
 | sortLanguageDropdown(); | ||||||
|   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)); |  | ||||||
| }); |  | ||||||
|  | |||||||
| @ -1,5 +1,11 @@ | |||||||
| <div th:fragment="navbar" class="mx-auto"> | <div th:fragment="navbar" class="mx-auto"> | ||||||
|   <script th:src="@{'/js/languageSelection.js'}"></script> |   <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"> |   <script th:inline="javascript"> | ||||||
|     const currentVersion = /*[[${@appVersion}]]*/ ''; |     const currentVersion = /*[[${@appVersion}]]*/ ''; | ||||||
|     const noFavourites = /*[[#{noFavourites}]]*/ ''; |     const noFavourites = /*[[#{noFavourites}]]*/ ''; | ||||||
| @ -36,7 +42,7 @@ | |||||||
|                   <div class="container-fluid"> |                   <div class="container-fluid"> | ||||||
|                     <div class="row"> |                     <div class="row"> | ||||||
|                       <!-- Page tools menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.organize}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPdfs.tags', 'advance')}"> |                           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> | ||||||
|                       </div> |                       </div> | ||||||
|                       <!-- Convert to PDF menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.convertTo}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('img-to-pdf', 'image', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'image')}"> |                           th:replace="~{fragments/navbarEntry :: navbarEntry ('img-to-pdf', 'image', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'image')}"> | ||||||
| @ -95,7 +101,7 @@ | |||||||
|                         </div> |                         </div> | ||||||
|                       </div> |                       </div> | ||||||
|                       <!-- Convert from PDF menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.convertFrom}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-img', 'image', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'image')}"> |                           th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-img', 'image', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'image')}"> | ||||||
| @ -126,7 +132,7 @@ | |||||||
|                         </div> |                         </div> | ||||||
|                       </div> |                       </div> | ||||||
|                       <!-- Security menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.security}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('sign', 'signature', 'home.sign.title', 'home.sign.desc', 'sign.tags', 'sign')}"> |                           th:replace="~{fragments/navbarEntry :: navbarEntry ('sign', 'signature', 'home.sign.title', 'home.sign.desc', 'sign.tags', 'sign')}"> | ||||||
| @ -160,7 +166,7 @@ | |||||||
|                         </div> |                         </div> | ||||||
|                       </div> |                       </div> | ||||||
|                       <!-- View & Edit menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.edit}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('view-pdf', 'menu_book', 'home.viewPdf.title', 'home.viewPdf.desc', 'viewPdf.tags', 'other')}"> |                           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')}"> |                           th:replace="~{fragments/navbarEntry :: navbarEntry ('get-info-on-pdf', 'info', 'home.getPdfInfo.title', 'home.getPdfInfo.desc', 'getPdfInfo.tags', 'other')}"> | ||||||
|                         </div> |                         </div> | ||||||
|                         <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> | ||||||
|                         <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> | ||||||
|                       </div> |                       </div> | ||||||
|                       <!-- Advance menu items --> |                       <!-- 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> |                         <h6 class="menu-title" th:text="#{navbar.sections.advance}"></h6> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'advance')}"> |                           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')}"> |                           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> | ||||||
|                         <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> | ||||||
|                         <div |                         <div | ||||||
|                           th:replace="~{fragments/navbarEntry :: navbarEntry ('split-by-size-or-count', 'vertical_split', 'home.autoSizeSplitPDF.title', 'home.autoSizeSplitPDF.desc', 'autoSizeSplitPDF.tags', 'advance')}"> |                           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> |   <head> | ||||||
|   <th:block th:insert="~{fragments/common :: head(title=#{login.title}, header=#{login.header})}"></th:block> |   <th:block th:insert="~{fragments/common :: head(title=#{login.title}, header=#{login.header})}"></th:block> | ||||||
|     <link rel="stylesheet" th:href="@{'/css/login.css'}"> |     <link rel="stylesheet" th:href="@{'/css/login.css'}"> | ||||||
|  |     <script th:src="@{'/js/languageSelection.js'}"></script> | ||||||
|  |     <script th:src="@{'/js/additionalLanguageCode.js'}"></script> | ||||||
|   </head> |   </head> | ||||||
| 
 | 
 | ||||||
|   <body> |   <body> | ||||||
| @ -29,86 +31,28 @@ | |||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           document.addEventListener('DOMContentLoaded', function() { |           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'); |             const dropdownItems = document.querySelectorAll('.lang_dropdown-item'); | ||||||
| 
 |  | ||||||
|             let activeItem; |             let activeItem; | ||||||
|  | 
 | ||||||
|             for (let i = 0; i < dropdownItems.length; i++) { |             for (let i = 0; i < dropdownItems.length; i++) { | ||||||
|               const item = dropdownItems[i]; |               const item = dropdownItems[i]; | ||||||
|               item.classList.remove('active'); |               item.classList.remove('active'); | ||||||
|               if (item.dataset.bsLanguageCode === storedLocale) { |               if (item.dataset.bsLanguageCode === defaultLocale) { | ||||||
|                 item.classList.add('active'); |                 item.classList.add('active'); | ||||||
|                 activeItem = item; |                 activeItem = item; | ||||||
|               } |               } | ||||||
|               item.addEventListener('click', handleDropdownItemClick); |               item.addEventListener('click', handleDropdownItemClick); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             const dropdown = document.getElementById('languageDropdown'); | ||||||
|  | 
 | ||||||
|             if (activeItem) { |             if (activeItem) { | ||||||
|               dropdown.innerHTML = activeItem.innerHTML;  // This will set the dropdown button's content to the active language's flag and name |               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> |         </script> | ||||||
|         <div class="text-center"> |         <div class="text-center"> | ||||||
|           <img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144"> |           <img class="my-4" th:src="@{'/favicon.svg'}" alt="favicon" width="144" height="144"> | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user