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 962eda9faeada26f1522a5480142f7404c66682f..92928d075b77a17e7ccb8f79bd008b010b276f8c 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 f9de81c7c2eb9c1ac06a149538b7ce8498e7339f..878db0d444f76e602a9c5a01d69460892ad718de 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 2a2aafac0e522b191271bbf59c20cffeadf95ae6..62bc181d910e15069afc33400e560536fcf69e0b 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 e12924f4d009b519539abb5995545d2526ee5dcd..9e1b33138e2ec0bd4cc5cab1775b2e06c1daadc9 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 3e83207893d0983c635b783ff05cee2d2e23835e..c2d28a6e33acafa680a95fd5b5d24e0307ec4de6 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 065bae2bef02745655aa60a96d335b789b50b637..f4647f6766bd47d40c78a18f1af972f900fcf8f8 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 1841f6116726e780ae565abdbab3e1c67b874c3c..110a7c73c32c0d67711451dfd743cf29ee5e09e0 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">© 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 0000000000000000000000000000000000000000..f4dbeffc2068f76f3da86fe6bf2243a9e373c156 --- /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');