Skip to content
Snippets Groups Projects
Commit 70c5bbcf authored by Marnuri Nitish -'s avatar Marnuri Nitish -
Browse files

Merge branch '256-language-options-so-that-i-can-switch-to-polish' into 'release/Sprint-4'

Resolve "As a user, I want to be able to select a from a list of language options so that i can switch to English and Polish languages when needed."

See merge request c24108486/team-11-polish-community-group!49
parents 410b3d4e a4e0c78f
Branches
No related tags found
No related merge requests found
Showing
with 788 additions and 109 deletions
......@@ -50,6 +50,8 @@ public class FeedApisController {
List<FeedImpl> posts = feedRepository.getAllPosts();
if (currentUser != null){
// set isEditable flag for each post depedant on whether they are an admin or own the post
for (FeedImpl post : posts) {
log.info("Role ID: " + currentUser.getRoleId());
......@@ -60,6 +62,7 @@ public class FeedApisController {
post.setIsDeletable(isSuperAdmin || isOwner);
log.info("PostIsEditable: " + post.getIsDeletable());
}
}
return posts;
}
......
......@@ -33,7 +33,9 @@ public class WebSecurityConfig {
private final RoleService roleService;
private final String[] whiteListingPath = {
"/api/feed/**"
// "/event",
// "event/*"
// "/api/feed/**" ,
};
public WebSecurityConfig(UserService userService, RoleService roleService) {
......@@ -51,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/**","/api/feed/**").permitAll()
// .requestMatchers().permitAll()
.requestMatchers(whiteListingPath).authenticated()
.anyRequest().permitAll()
)
......
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;
import polish_community_group_11.polish_community.translation.service.TranslationService;
import java.util.List;
@RestController
@RequestMapping("/api/translations")
public class TranslationApisController {
private final TranslationService translationService;
public TranslationApisController(TranslationService translationService) {
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() {
List<Translation> translations = translationService.getAllTranslations();
return ResponseEntity.ok(translations);
}
// for specific lang
@GetMapping("/language/{language}")
public ResponseEntity<List<Translation>> getTranslationsByLanguage(@PathVariable String language) {
List<Translation> translations = translationService.getTranslationsByLanguage(language);
return ResponseEntity.ok(translations);
}
// for specific key and lang
@GetMapping("/{key}/language/{language}")
public ResponseEntity<Translation> getTranslationByKeyAndLanguage(
@PathVariable String key,
@PathVariable String language) {
Translation translation = translationService.getTranslationByKeyAndLanguage(key, language);
if (translation == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(translation);
}
// adding new translation
@PostMapping
public ResponseEntity<String> addTranslation(@RequestBody Translation translation) {
translationService.addTranslation(translation);
return ResponseEntity.ok("Translation added successfully.");
}
// update existing
@PutMapping("/{id}")
public ResponseEntity<String> updateTranslation(@PathVariable int id, @RequestBody Translation translation) {
translationService.updateTranslation(id, translation);
return ResponseEntity.ok("Translation updated successfully.");
}
// deleting a translation
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteTranslation(@PathVariable int id) {
translationService.deleteTranslation(id);
return ResponseEntity.ok("Translation deleted successfully.");
}
// get all unique keys
@GetMapping("/keys")
public ResponseEntity<List<String>> getAllTranslationKeys() {
List<String> keys = translationService.getAllTranslationKeys();
return ResponseEntity.ok(keys);
}
// get all translations for a specific key across all langs
@GetMapping("/keys/{key}")
public ResponseEntity<List<Translation>> getTranslationsByKey(@PathVariable String key) {
List<Translation> translations = translationService.getTranslationsByKey(key);
return ResponseEntity.ok(translations);
}
}
package polish_community_group_11.polish_community.translation.model;
public class Translation {
private int id;
private String key;
private String language;
private String value;
public Translation () {
}
public Translation(int id, String key, String language, String value){
this.id = id;
this.key = key;
this.language = language;
this.value = value;
}
public Translation(String key, String language, String value){
this.key = key;
this.language = language;
this.value = value;
}
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
// some utility methods for debugging
@Override
public String toString() {
return "Translation{" +
"id=" + id +
", key='" + key + '\'' +
", language='" + language + '\'' +
", value='" + value + '\'' +
'}';
}
// cheking if two translations equal each other
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Translation that = (Translation) o;
if (id != that.id) return false;
if (!key.equals(that.key)) return false;
if (!language.equals(that.language)) return false;
return value.equals(that.value);
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + key.hashCode();
result = 31 * result + language.hashCode();
result = 31 * result + value.hashCode();
return result;
}
}
package polish_community_group_11.polish_community.translation.repository;
import polish_community_group_11.polish_community.translation.model.Translation;
import java.util.List;
public interface TranslationRepository {
List<Translation> getAllTranslations();
List<Translation> getTranslationsByLanguage(String language);
Translation getTranslationByKeyAndLanguage(String key, String language);
void addTranslation(Translation translation);
void updateTranslation(int id, Translation translation);
void deleteTranslation(int id);
List<String> getAllTranslationKeys();
List<Translation> getTranslationsByKey(String key);
}
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;
import polish_community_group_11.polish_community.translation.model.Translation;
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;
public TranslationRepositoryImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.translationMapper = (rs, rowNum) -> {
Translation translation = new Translation();
translation.setId(rs.getInt("id"));
translation.setKey(rs.getString("translation_key"));
translation.setLanguage(rs.getString("language"));
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
@Override
public List<Translation> getAllTranslations() {
String sql = "SELECT * FROM translations";
return jdbcTemplate.query(sql, translationMapper);
}
// get translation by key and language
@Override
public Translation getTranslationByKeyAndLanguage(String key, String language) {
String sql = "SELECT * FROM translations WHERE translation_key = ? AND language = ?";
return jdbcTemplate.queryForObject(sql, translationMapper, key, language);
}
// Add a new translation
@Override
public void addTranslation(Translation translation) {
String sql = "INSERT INTO translations (translation_key, language, translation_value) VALUES (?, ?, ?)";
jdbcTemplate.update(sql,
translation.getKey(),
translation.getLanguage(),
translation.getValue()
);
}
// update existing translation
@Override
public void updateTranslation(int id, Translation translation) {
String sql = "UPDATE translations SET translation_key = ?, language = ?, translation_value = ? WHERE id = ?";
jdbcTemplate.update(sql,
translation.getKey(),
translation.getLanguage(),
translation.getValue(),
id
);
}
// delete a translation
@Override
public void deleteTranslation(int id) {
String sql = "DELETE FROM translations WHERE id = ?";
jdbcTemplate.update(sql, id);
}
// getting all unique keys for word list management
@Override
public List<String> getAllTranslationKeys() {
String sql = "SELECT DISTINCT translation_key FROM translations";
return jdbcTemplate.query(sql, (rs, rowNum) -> rs.getString("translation_key"));
}
// get translations for something across all languages
@Override
public List<Translation> getTranslationsByKey(String key) {
String sql = "SELECT * FROM translations WHERE translation_key = ?";
return jdbcTemplate.query(sql, translationMapper, key);
}
}
package polish_community_group_11.polish_community.translation.service;
import polish_community_group_11.polish_community.translation.model.Translation;
import java.util.List;
public interface TranslationService {
List<Translation> getAllTranslations();
List<Translation> getTranslationsByLanguage(String language);
Translation getTranslationByKeyAndLanguage(String key, String language);
void addTranslation(Translation translation);
void updateTranslation(int id, Translation translation);
void deleteTranslation(int id);
List<String> getAllTranslationKeys();
List<Translation> getTranslationsByKey(String key);
}
package polish_community_group_11.polish_community.translation.service;
import org.springframework.stereotype.Service;
import polish_community_group_11.polish_community.translation.model.Translation;
import polish_community_group_11.polish_community.translation.repository.TranslationRepository;
import java.util.List;
@Service
public class TranslationServiceImpl implements TranslationService {
private final TranslationRepository translationRepository;
public TranslationServiceImpl(TranslationRepository translationRepository) {
this.translationRepository = translationRepository;
}
@Override
public List<Translation> getAllTranslations() {
return translationRepository.getAllTranslations();
}
@Override
public List<Translation> getTranslationsByLanguage(String language) {
return translationRepository.getTranslationsByLanguage(language);
}
@Override
public Translation getTranslationByKeyAndLanguage(String key, String language) {
return translationRepository.getTranslationByKeyAndLanguage(key, language);
}
@Override
public void addTranslation(Translation translation) {
translationRepository.addTranslation(translation);
}
@Override
public void updateTranslation(int id, Translation translation) {
translationRepository.updateTranslation(id, translation);
}
@Override
public void deleteTranslation(int id) {
translationRepository.deleteTranslation(id);
}
@Override
public List<String> getAllTranslationKeys() {
return translationRepository.getAllTranslationKeys();
}
@Override
public List<Translation> getTranslationsByKey(String key) {
return translationRepository.getTranslationsByKey(key);
}
}
......@@ -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
......
......@@ -13,6 +13,7 @@ DROP TABLE IF EXISTS user_profile;
DROP TABLE IF EXISTS user_roles;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS roles;
DROP TABLE IF EXISTS translations;
create table if not exists categories (
category_id INT AUTO_INCREMENT PRIMARY KEY,
......@@ -131,6 +132,15 @@ CREATE TABLE IF NOT EXISTS comment
FOREIGN KEY (user_id) REFERENCES users (id)
) ENGINE = InnoDB;
create table if not exists translations (
id int auto_increment primary key,
translation_key varchar(255) not null,
language varchar(10) not null,
value text not null
) engine = InnoDB;
ALTER TABLE translations MODIFY value TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- create schema for event
create table if not exists event(
......@@ -161,3 +171,4 @@ CREATE TABLE IF NOT EXISTS user_profile (
CREATE TRIGGER UMustHaveProfile AFTER INSERT ON users FOR EACH ROW INSERT INTO user_profile (user_id) VALUES (NEW.id);
let translations = [];
let currentLanguage = "en";
/**
* Fetch translations for the given language.
* @param {string} language - Language code to fetch translations for.
*/
async function fetchTranslations(language) {
try {
const response = await fetch(`/api/translations/language/${language}`);
if (!response.ok) {
throw new Error(`Failed to fetch translations: ${response.statusText}`);
}
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);
}
}
function updateUIWithTranslations() {
const elementsToTranslate = document.querySelectorAll("[data-translate-key]");
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
......@@ -10,60 +10,60 @@
</head>
<section layout:fragment="content">
<h1>Welcome to our Community</h1>
<p>Connect, Share, and Grow Together</p>
<h1 data-translate-key="home.header">Welcome to our Community</h1>
<p data-translate-key="home.smallheader">Connect, Share, and Grow Together</p>
<section class="tiles">
<div class="tile" id="feedTile">
<a th:href="@{/feed}" class="tileLink">
<div class="topTile">
<img src="/assets/navbarImages/feed.png" class="tile-logo"><span class="tile-title">Feed</span>
<img src="/assets/navbarImages/feed.png" class="tile-logo"><span class="tile-title" data-translate-key="navbar.feed">Feed</span>
</div>
<p class="tile-description">Stay updated with the latest posts</p>
<p class="tile-description" data-translate-key="home.latest_posts">Stay updated with the latest posts</p>
</a>
</div>
<div class="tile" id="newsTile">
<a th:href="@{/news}" class="tileLink">
<div class="topTile">
<img src="/assets/navbarImages/news.png" class="tile-logo"><span class="tile-title">News</span>
<img src="/assets/navbarImages/news.png" class="tile-logo"><span class="tile-title" data-translate-key="navbar.news">News</span>
</div>
<p class="tile-description">Discover the latest community news</p>
<p class="tile-description" data-translate-key="home.news">Discover the latest community news</p>
</a>
</div>
<div class="tile" id="eventsTile">
<a th:href="@{/event}" class="tileLink">
<div class="topTile">
<img src="/assets/navbarImages/events.png" class="tile-logo"><span class="tile-title">Events</span>
<img src="/assets/navbarImages/events.png" class="tile-logo"><span class="tile-title" data-translate-key="navbar.events">Events</span>
</div>
<p class="tile-description">Join our upcoming community events</p>
<p class="tile-description" data-translate-key="home.events">Join our upcoming community events</p>
</a>
</div>
<div class="tile" id="infoTile">
<a th:href="@{/categories}" class="tileLink">
<div class="topTile">
<img src="/assets/navbarImages/info.png" class="tile-logo"><span class="tile-title">Info Database</span>
<img src="/assets/navbarImages/info.png" class="tile-logo"><span class="tile-title" data-translate-key="navbar.db_info">Info Database</span>
</div>
<p class="tile-description">Access our community information database</p>
<p class="tile-description" data-translate-key="home.db_info">Access our community information database</p>
</a>
</div>
<div class="tile" id="aboutTile">
<a th:href="@{/aboutUs}" class="tileLink">
<div class="topTile">
<img src="/assets/navbarImages/about.png" class="tile-logo"><span class="tile-title">About Us</span>
<img src="/assets/navbarImages/about.png" class="tile-logo"><span class="tile-title" data-translate-key="navbar.about_us">About Us</span>
</div>
<p class="tile-description">Learn about our mission and values</p>
<p class="tile-description" data-translate-key="home.about_us">Learn about our mission and values</p>
</a>
</div>
</section>
<h1>Join Our Thriving Community Today!</h1>
<p>Connect with like-minded individuals, share your ideas, and be part of something amazing</p>
<button>Get Started</button>
<h1 data-translate-key="home.join_community">Join Our Thriving Community Today!</h1>
<p data-translate-key="home.tagline">Connect with like-minded individuals, share your ideas, and be part of something amazing</p>
<button data-translate-key="home.get_started">Get Started</button>
</section>
......
......@@ -8,7 +8,8 @@
<title>Ludek Polonia Wajiska</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="/css/comments/comments.css">
<link rel="stylesheet" href="/css/layout/layout.css">
......@@ -26,25 +27,32 @@
<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">Home</span>
</a>
<a th:href="@{/feed}" class="navLink">
<img src="/assets/navbarImages/feed.png" class="navIcons"><span class="navText">Feed</span>
<img src="/assets/navbarImages/feed.png" class="navIcons"><span class="navText"
data-translate-key="navbar.feed">Feed</span>
</a>
<a th:href="@{/news}" class="navLink">
<img src="/assets/navbarImages/news.png" class="navIcons"><span class="navText">News</span>
<img src="/assets/navbarImages/news.png" class="navIcons"><span class="navText"
data-translate-key="navbar.news">News</span>
</a>
<a th:href="@{/event}" class="navLink">
<img src="/assets/navbarImages/events.png" class="navIcons"><span class="navText">Events</span>
<img src="/assets/navbarImages/events.png" class="navIcons"><span class="navText"
data-translate-key="navbar.events">Events</span>
</a>
<a th:href="@{/categories}" class="navLink">
<img src="/assets/navbarImages/info.png" class="navIcons"><span class="navText">Info Database</span>
<img src="/assets/navbarImages/info.png" class="navIcons"><span class="navText"
data-translate-key="navbar.db_info">Info Database</span>
</a>
<a th:href="@{/aboutUs}" class="navLink">
<img src="/assets/navbarImages/about.png" class="navIcons"><span class="navText">About Us</span>
<img src="/assets/navbarImages/about.png" class="navIcons"><span class="navText"
data-translate-key="navbar.about_us">About Us</span>
</a>
<a th:href="@{/contactus}" class="navLink">
<img src="/assets/navbarImages/contact.png" class="navIcons"><span class="navText">Contact Us</span>
<img src="/assets/navbarImages/contact.png" class="navIcons"><span class="navText"
data-translate-key="navbar.contact_us">Contact Us</span>
</a>
</div>
......@@ -54,14 +62,15 @@
<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>
<!-- Profile -->
<a th:href="@{/profile}" class="navLink">
<img src="/assets/navbarImages/profile.png" class="navIcons"><span class="navText">Profile</span>
<img src="/assets/navbarImages/profile.png" class="navIcons"><span class="navText"
data-translate-key="navbar.profile">Profile</span>
</a>
</div>
</nav>
......@@ -69,43 +78,42 @@
</header>
<div class="mainBody">
<main layout:fragment="content" class="content"></main>
</div>
<footer class="footer">
<div class="footer-section about">
<h3 class="footerTitle">Polish Community Website</h3>
<p class="footerText">Connecting people, sharing ideas, and building a better future together.</p>
<h3 class="footerTitle">Ludek Polonia Wajiska</h3>
<p class="footerText" data-translate-key="footer.tagline">Connecting people, sharing ideas, and building a
better future together.</p>
</div>
<div class="footer-section links">
<h3 class="footerTitle">Quick Links</h3>
<h3 class="footerTitle" data-translate-key="footer.quick_links">Quick Links</h3>
<ul class="footerLinks">
<li><a th:href="@{/aboutus}" class="footerLink">About Us</a></li>
<li><a th:href="@{/contact}" class="footerLink">Contact</a></li>
<li><a th:href="@{/}" class="footerLink">Privacy Policy</a></li>
<li><a th:href="@{/}" class="footerLink">Terms of Service</a></li>
<li><a th:href="@{/aboutus}" class="footerLink" data-translate-key="navbar.about_us">About Us</a></li>
<li><a th:href="@{/contact}" class="footerLink" data-translate-key="navbar.contact">Contact</a></li>
<li><a th:href="@{/}" class="footerLink" data-translate-key="footer.privacy_policy">Privacy Policy</a></li>
<li><a th:href="@{/}" class="footerLink" data-translate-key="footer.terms_of_service">Terms of Service</a>
</li>
</ul>
</div>
<div class="footer-section connect">
<h3 class="footerTitle">Connect with us</h3>
<h3 class="footerTitle" data-translate-key="footer.connect_with_us">Connect with us</h3>
<div class="social-icons">
<a href="https://www.facebook.com/LudekPCG" class="social-icon"><img src="/assets/navbarImages/facebook.png" alt="Facebook"></a>
<a href="https://www.facebook.com/LudekPCG" class="social-icon"><img src="/assets/navbarImages/facebook.png"
alt="Facebook"></a>
<a href="#" class="social-icon"><img src="/assets/navbarImages/twitter.png" alt="Twitter"></a>
<a href="#" class="social-icon"><img src="/assets/navbarImages/instagram.png" alt="Instagram"></a>
</div>
</div>
<div class="footer-section copyright">
<p class="footerCompanyName">&copy; LUDEK PCG ltd. All rights reserved.</p>
<p class="footerCompanyName">&copy; LUDEK PCG ltd. <span data-translate-key="footer.all_rights_reserved" >All rights reserved.</span></p>
</div>
</footer>
<script src="/js/layout/layout.js" defer></script>
<script th:replace="~{comments/commentFragment::commentScript}"></script>
</body>
</html>
\ No newline at end of file
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'),
('home.header', 'en', 'Welcome to our Community'),
('home.smallheader', 'en', 'Connect, Share, and Grow Together'),
('home.latest_posts', 'en', 'Stay updated with the latest posts'),
('home.news', 'en', 'Discover the latest community news'),
('home.events', 'en', 'Join our upcoming community events'),
('home.db_info', 'en', 'Access our community information database'),
('home.about_us', 'en', 'Learn about our mission and values'),
('home.join_community', 'en', 'Join Our Thriving Community Today!'),
('home.tagline', 'en', 'Connect with like-minded individuals, share your ideas, and be part of something amazing'),
('home.get_started', 'en', 'Get Started'),
('footer.tagline', 'en', 'Connecting people, sharing ideas, and building a better future together.'),
('footer.quick_links', 'en', 'Quick Links'),
('footer.connect_with_us', 'en', 'Connect with us'),
('footer.privacy_policy', 'en', 'Privacy Policy'),
('footer.terms_of_service', 'en', 'Terms of Service'),
('footer.all_rights_reserved', 'en', 'All rights reserved.'),
-- 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'),
('home.header', 'pl', 'Witamy w naszej społeczności'),
('home.smallheader', 'pl', 'Łącz się, dziel i rozwijaj razem'),
('home.latest_posts', 'pl', 'Bądź na bieżąco z najnowszymi postami'),
('home.news', 'pl', 'Odkryj najnowsze wiadomości społecznościowe'),
('home.events', 'pl', 'Dołącz do nadchodzących wydarzeń społecznościowych'),
('home.db_info', 'pl', 'Uzyskaj dostęp do naszej bazy informacji społecznościowych'),
('home.about_us', 'pl', 'Dowiedz się o naszej misji i wartościach'),
('home.join_community', 'pl', 'Dołącz do naszej rozwijającej się społeczności już dziś!'),
('home.tagline', 'pl', 'Łącz się z podobnie myślącymi ludźmi, dziel się pomysłami i bądź częścią czegoś niesamowitego'),
('home.get_started', 'pl', 'Zacznij teraz'),
('footer.tagline', 'pl', 'Łącząc ludzi, dzieląc się pomysłami i budując lepszą przyszłość razem.'),
('footer.quick_links', 'pl', 'Szybkie linki'),
('footer.connect_with_us', 'pl', 'Połącz się z nami'),
('footer.privacy_policy', 'pl', 'Polityka prywatności'),
('footer.terms_of_service', 'pl', 'Warunki korzystania z usługi'),
('footer.all_rights_reserved', 'pl', 'Wszelkie prawa zastrzeżone.');
package polish_community_group_11.polish_community.translation.controller;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import polish_community_group_11.polish_community.translation.model.Translation;
import polish_community_group_11.polish_community.translation.service.TranslationService;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(TranslationApisController.class)
class TranslationControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private TranslationService translationService;
private List<Translation> mockTranslations;
@BeforeEach
void setUp() {
mockTranslations = Arrays.asList(
new Translation(1, "greeting", "en", "Hello"),
new Translation(2, "greeting", "pl", "Cześć")
);
}
@Test
void getAllTranslations_shouldReturnAllTranslations() throws Exception {
when(translationService.getAllTranslations()).thenReturn(mockTranslations);
mockMvc.perform(get("/api/translations")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].key", is("greeting")))
.andExpect(jsonPath("$[0].value", is("Hello")));
}
@Test
void getTranslationsByLanguage_shouldReturnTranslationsForSpecificLanguage() throws Exception {
List<Translation> englishTranslations = List.of(
new Translation(1, "greeting", "en", "Hello")
);
when(translationService.getTranslationsByLanguage("en")).thenReturn(englishTranslations);
mockMvc.perform(get("/api/translations/language/en")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(1)))
.andExpect(jsonPath("$[0].value", is("Hello")));
}
@Test
void addTranslation_shouldAddNewTranslation() throws Exception {
Translation newTranslation = new Translation(0, "farewell", "en", "Goodbye");
Mockito.doNothing().when(translationService).addTranslation(Mockito.any(Translation.class));
mockMvc.perform(post("/api/translations")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"key\":\"farewell\",\"language\":\"en\",\"value\":\"Goodbye\"}"))
.andExpect(status().isOk())
.andExpect(content().string("Translation added successfully."));
}
}
package polish_community_group_11.polish_community.translation.service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import polish_community_group_11.polish_community.translation.model.Translation;
import polish_community_group_11.polish_community.translation.repository.TranslationRepository;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class TranslationServiceImplTest {
@Mock
private TranslationRepository translationRepository;
@InjectMocks
private TranslationServiceImpl translationService;
private Translation mockTranslation;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
mockTranslation = new Translation(1, "greeting", "en", "Hello");
}
@Test
void getAllTranslations_shouldReturnAllTranslations() {
when(translationRepository.getAllTranslations()).thenReturn(List.of(mockTranslation));
List<Translation> result = translationService.getAllTranslations();
assertNotNull(result);
assertEquals(1, result.size());
assertEquals("Hello", result.get(0).getValue());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment