From a07e15e685adbb46e2bd1607773277f7b0523674 Mon Sep 17 00:00:00 2001
From: Githuba Richard <githubarj@cardiff.ac.uk>
Date: Wed, 11 Dec 2024 11:48:08 +0000
Subject: [PATCH] proof of the translation api working

---
 .../security/WebSecurityConfig.java           |  4 +-
 .../controller/TranslationApisController.java | 13 ++++++
 .../repository/TranslationRepositoryImpl.java | 34 ++++++++++----
 src/main/resources/application.properties     |  2 +-
 src/main/resources/schema.sql                 |  4 +-
 src/main/resources/static/js/layout/layout.js | 45 +++++++++++++------
 .../resources/templates/layout/layout.html    |  8 ++--
 src/main/resources/translations.sql           | 20 +++++++++
 8 files changed, 101 insertions(+), 29 deletions(-)
 create mode 100644 src/main/resources/translations.sql

diff --git a/src/main/java/polish_community_group_11/polish_community/security/WebSecurityConfig.java b/src/main/java/polish_community_group_11/polish_community/security/WebSecurityConfig.java
index 962eda9..92928d0 100644
--- a/src/main/java/polish_community_group_11/polish_community/security/WebSecurityConfig.java
+++ b/src/main/java/polish_community_group_11/polish_community/security/WebSecurityConfig.java
@@ -35,7 +35,7 @@ public class WebSecurityConfig {
     private final String[] whiteListingPath = {
 //            "/event",
 //            "event/*"
-            "/api/feed/**"
+//            "/api/feed/**" ,
     };
 
     public WebSecurityConfig(UserService userService, RoleService roleService) {
@@ -53,6 +53,8 @@ public class WebSecurityConfig {
                 // require authentication for events only
                 //update in future when more protected resources are available
                 .authorizeHttpRequests((requests) -> requests
+                        .requestMatchers("/api/translations/**").permitAll()
+                        .requestMatchers("/api/feed/**").permitAll()
                         .requestMatchers(whiteListingPath).authenticated()
                         .anyRequest().permitAll()
                 )
diff --git a/src/main/java/polish_community_group_11/polish_community/translation/controller/TranslationApisController.java b/src/main/java/polish_community_group_11/polish_community/translation/controller/TranslationApisController.java
index f9de81c..878db0d 100644
--- a/src/main/java/polish_community_group_11/polish_community/translation/controller/TranslationApisController.java
+++ b/src/main/java/polish_community_group_11/polish_community/translation/controller/TranslationApisController.java
@@ -1,5 +1,6 @@
 package polish_community_group_11.polish_community.translation.controller;
 
+import jakarta.annotation.PostConstruct;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import polish_community_group_11.polish_community.translation.model.Translation;
@@ -17,6 +18,18 @@ public class TranslationApisController {
         this.translationService = translationService;
     }
 
+    @GetMapping("/test")
+    public ResponseEntity<String> test() {
+        return ResponseEntity.ok("Translation API is working");
+    }
+
+    @PostConstruct
+    public void init() {
+        System.out.println("TranslationApisController initialized with mappings:");
+        System.out.println("/api/translations");
+        System.out.println("/api/translations/language/{language}");
+    }
+
     // get all translations
     @GetMapping
     public ResponseEntity<List<Translation>> getAllTranslations() {
diff --git a/src/main/java/polish_community_group_11/polish_community/translation/repository/TranslationRepositoryImpl.java b/src/main/java/polish_community_group_11/polish_community/translation/repository/TranslationRepositoryImpl.java
index 2a2aafa..62bc181 100644
--- a/src/main/java/polish_community_group_11/polish_community/translation/repository/TranslationRepositoryImpl.java
+++ b/src/main/java/polish_community_group_11/polish_community/translation/repository/TranslationRepositoryImpl.java
@@ -1,5 +1,7 @@
 package polish_community_group_11.polish_community.translation.repository;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Repository;
@@ -9,6 +11,8 @@ import java.util.List;
 
 @Repository
 public class TranslationRepositoryImpl implements TranslationRepository {
+    private static final Logger logger = LoggerFactory.getLogger(TranslationRepositoryImpl.class);
+
     private final JdbcTemplate jdbcTemplate;
     private final RowMapper<Translation> translationMapper;
 
@@ -19,9 +23,30 @@ public class TranslationRepositoryImpl implements TranslationRepository {
             translation.setId(rs.getInt("id"));
             translation.setKey(rs.getString("translation_key"));
             translation.setLanguage(rs.getString("language"));
-            translation.setValue(rs.getString("translation_value"));
+            translation.setValue(rs.getString("value"));
             return translation;
         };
+        // Test database connection on startup
+        try {
+            jdbcTemplate.queryForObject("SELECT 1", Integer.class);
+            logger.info("Database connection successful");
+        } catch (Exception e) {
+            logger.error("Database connection failed", e);
+        }
+    }
+
+    @Override
+    public List<Translation> getTranslationsByLanguage(String language) {
+        try {
+            logger.info("Attempting to fetch translations for language: {}", language);
+            String sql = "SELECT * FROM translations WHERE language = ?";
+            List<Translation> results = jdbcTemplate.query(sql, translationMapper, language);
+            logger.info("Found {} translations for language {}", results.size(), language);
+            return results;
+        } catch (Exception e) {
+            logger.error("Error fetching translations for language {}: {}", language, e.getMessage());
+            throw e;
+        }
     }
 
     // getting all translaions
@@ -31,13 +56,6 @@ public class TranslationRepositoryImpl implements TranslationRepository {
         return jdbcTemplate.query(sql, translationMapper);
     }
 
-    // getting translations for a single language
-    @Override
-    public List<Translation> getTranslationsByLanguage(String language) {
-        String sql = "SELECT * FROM translations WHERE language = ?";
-        return jdbcTemplate.query(sql, translationMapper, language);
-    }
-
     // get translation by key and language
     @Override
     public Translation getTranslationByKeyAndLanguage(String key, String language) {
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index e12924f..9e1b331 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -18,7 +18,7 @@ server.error.whitelabel.enabled=false
 server.error.path=/error
 spring.jpa.hibernate.ddl-auto=none
 spring.sql.init.schema-locations=classpath:/schema.sql
-spring.sql.init.data-locations=classpath:/data.sql, classpath:/data_information_domains.sql
+spring.sql.init.data-locations=classpath:/data.sql, classpath:/data_information_domains.sql, classpath:/translations.sql
 #spring.jpa.hibernate.ddl-auto=none
 spring.jpa.defer-datasource-initialization=true
 
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 3e83207..c2d28a6 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -152,4 +152,6 @@ create table if not exists translations (
     translation_key varchar(255) not null,
     language varchar(10) not null,
     value text not null
-) engine = InnoDB;
\ No newline at end of file
+) engine = InnoDB;
+
+ALTER TABLE translations MODIFY value TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
diff --git a/src/main/resources/static/js/layout/layout.js b/src/main/resources/static/js/layout/layout.js
index 065bae2..f4647f6 100644
--- a/src/main/resources/static/js/layout/layout.js
+++ b/src/main/resources/static/js/layout/layout.js
@@ -1,5 +1,5 @@
-let translations = {};
-let currentLanguage = "english";
+let translations = [];
+let currentLanguage = "en";
 
 /**
  * Fetch translations for the given language.
@@ -11,27 +11,44 @@ async function fetchTranslations(language) {
         if (!response.ok) {
             throw new Error(`Failed to fetch translations: ${response.statusText}`);
         }
-        translations = await response.json();
+        translations = await response.json(); // This is now an array of translation objects
         currentLanguage = language;
         console.log("Translations updated:", translations);
+        updateUIWithTranslations();
         document.dispatchEvent(new Event("translations-updated"));
     } catch (error) {
         console.error("Error fetching translations:", error);
     }
 }
 
-// fetch translations on page load
-document.addEventListener("DOMContentLoaded", () => {
-    fetchTranslations(currentLanguage);
-});
+function updateUIWithTranslations() {
+    const elementsToTranslate = document.querySelectorAll("[data-translate-key]");
 
-// handle language selection
-const languageSelector = document.querySelector(".languageSelector select");
-if (languageSelector) {
-    languageSelector.addEventListener("change", async (event) => {
-        const selectedLanguage = event.target.value;
-        if (selectedLanguage !== currentLanguage) {
-            await fetchTranslations(selectedLanguage);
+    elementsToTranslate.forEach(element => {
+        const translationKey = element.getAttribute("data-translate-key");
+        // Find the translation object with matching key
+        const translation = translations.find(t => t.key === translationKey);
+        if (translation) {
+            element.textContent = translation.value;
+        } else {
+            console.warn(`No translation found for key: ${translationKey}`);
         }
     });
 }
+
+// fetch translations on page load
+document.addEventListener("DOMContentLoaded", () => {
+    fetchTranslations(currentLanguage);
+    console.log("I have run");
+
+    // handle language selection
+    const languageSelector = document.querySelector(".languageSelector select");
+    if (languageSelector) {
+        languageSelector.addEventListener("change", async (event) => {
+            const selectedLanguage = event.target.value;
+            if (selectedLanguage !== currentLanguage) {
+                await fetchTranslations(selectedLanguage);
+            }
+        });
+    }
+});
\ No newline at end of file
diff --git a/src/main/resources/templates/layout/layout.html b/src/main/resources/templates/layout/layout.html
index 1841f61..110a7c7 100644
--- a/src/main/resources/templates/layout/layout.html
+++ b/src/main/resources/templates/layout/layout.html
@@ -26,7 +26,7 @@
 
                 <div class="navMiddle">
                     <a th:href="@{/}" class="navLink">
-                        <img src="/assets/navbarImages/home.png" class="navIcons"><span class="navText">Home</span>
+                        <img src="/assets/navbarImages/home.png" class="navIcons" ><span class="navText" data-translate-key="navbar.home"></span>
                     </a>
                     <a th:href="@{/feed}" class="navLink">
                         <img src="/assets/navbarImages/feed.png" class="navIcons"><span class="navText">Feed</span>
@@ -54,8 +54,8 @@
                     <div class="languageSelector">
                         <img src="/assets/navbarImages/globe.png" class="navIcons">
                         <select name="language">
-                            <option value="english">English</option>
-                            <option value="polish">Polish</option>
+                            <option value="en">English</option>
+                            <option value="pl">Polish</option>
                         </select>
                     </div>
 
@@ -103,7 +103,7 @@
             <p class="footerCompanyName">&copy; LUDEK PCG ltd. All rights reserved.</p>
         </div>
     </footer>
-    <script src="/js/layout/layout.js"></script>
+    <script src="/js/layout/layout.js" defer></script>
     <script th:replace="~{comments/commentFragment::commentScript}"></script>
 </body>
 </html>
\ No newline at end of file
diff --git a/src/main/resources/translations.sql b/src/main/resources/translations.sql
new file mode 100644
index 0000000..f4dbeff
--- /dev/null
+++ b/src/main/resources/translations.sql
@@ -0,0 +1,20 @@
+INSERT INTO translations (translation_key, language, value) VALUES
+    -- English translations
+    ('navbar.home', 'en', 'Home'),
+    ('navbar.news', 'en', 'News'),
+    ('navbar.events', 'en', 'Events'),
+    ('navbar.db_info', 'en', 'Info Database'),
+    ('navbar.contact_us', 'en', 'Contact Us'),
+    ('navbar.feed', 'en', 'Feed'),
+    ('navbar.about_us', 'en', 'About Us'),
+    ('navbar.profile', 'en', 'Profile'),
+
+    -- Polish translations
+    ('navbar.home', 'pl', 'Strona główna'),
+    ('navbar.news', 'pl', 'Aktualności'),
+    ('navbar.events', 'pl', 'Wydarzenia'),
+    ('navbar.db_info', 'pl', 'Informacje o bazie danych'),
+    ('navbar.contact_us', 'pl', 'Skontaktuj się z nami'),
+    ('navbar.feed', 'pl', 'Kanał'),
+    ('navbar.about_us', 'pl', 'O nas'),
+    ('navbar.profile', 'pl', 'Profil');
-- 
GitLab