feat(i18n): integrate StorageService for language persistence in LocalizationServiceImpl
This commit is contained in:
@@ -15,6 +15,7 @@ import org.springframework.context.annotation.Bean;
|
||||
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
@AutoConfiguration
|
||||
@ConditionalOnProperty(name = "game-engine.i18n.enabled", havingValue = "true", matchIfMissing = true)
|
||||
@@ -24,8 +25,8 @@ public class LocalizationAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
LocalizationService localizationManager(@Value("${game-engine.i18n.load-on-start:true}") final boolean loadOnStart, @Value("${game-engine.i18n.resource:i18n/i18n.yaml}") final String resource, final StaticResourceService staticResourceService) {
|
||||
final var localizationManager = new LocalizationServiceImpl();
|
||||
LocalizationService localizationManager(@Value("${game-engine.i18n.load-on-start:true}") final boolean loadOnStart, @Value("${game-engine.i18n.resource:i18n/i18n.yaml}") final String resource, final StaticResourceService staticResourceService, final StorageService storageService) {
|
||||
final var localizationManager = new LocalizationServiceImpl(storageService);
|
||||
|
||||
if (loadOnStart) {
|
||||
final var path = new File(resource).toPath();
|
||||
|
||||
@@ -137,7 +137,7 @@ public class LocalizationEditor extends JFrame {
|
||||
* Create the frame.
|
||||
*/
|
||||
public LocalizationEditor() {
|
||||
this.localizationManagerImpl = new LocalizationServiceImpl();
|
||||
this.localizationManagerImpl = new LocalizationServiceImpl(null);
|
||||
|
||||
this.setTitle("i18n Editor");
|
||||
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
|
||||
@@ -5,10 +5,12 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
import de.extio.game_engine.util.ObjectSerialization;
|
||||
|
||||
public class LocalizationServiceImpl implements LocalizationService {
|
||||
@@ -17,12 +19,21 @@ public class LocalizationServiceImpl implements LocalizationService {
|
||||
|
||||
public final static String NOT_FOUND_PREFIX = "{i18n.";
|
||||
|
||||
private static final List<String> LANGUAGE_STORAGE_PATH = List.of("gameEngine");
|
||||
private static final String LANGUAGE_STORAGE_NAME = "currentLanguage";
|
||||
|
||||
private final StorageService storageService;
|
||||
|
||||
private Localizations localizations = new Localizations();
|
||||
|
||||
private Map<String, String> currentLanguage;
|
||||
|
||||
private String currentLanguageName;
|
||||
|
||||
LocalizationServiceImpl(final StorageService storageService) {
|
||||
this.storageService = storageService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetEntries() {
|
||||
this.localizations.getLanguages().forEach((lang, mapping) -> mapping.clear());
|
||||
@@ -74,10 +85,12 @@ public class LocalizationServiceImpl implements LocalizationService {
|
||||
LOGGER.info("Loaded {} localizations for {} languages", localizations.getDescriptions().size(), localizations.getLanguages().size());
|
||||
}
|
||||
|
||||
this.loadPersistedLanguageName();
|
||||
if (this.currentLanguageName == null) {
|
||||
this.currentLanguageName = "en";
|
||||
}
|
||||
this.setLanguage(this.currentLanguageName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,6 +101,7 @@ public class LocalizationServiceImpl implements LocalizationService {
|
||||
|
||||
this.currentLanguageName = lang;
|
||||
this.currentLanguage = this.localizations.getLanguages().get(lang);
|
||||
this.persistCurrentLanguageName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -169,4 +183,30 @@ public class LocalizationServiceImpl implements LocalizationService {
|
||||
}
|
||||
}
|
||||
|
||||
private void persistCurrentLanguageName() {
|
||||
if (this.storageService == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.storageService.store(LANGUAGE_STORAGE_PATH, LANGUAGE_STORAGE_NAME, this.currentLanguageName);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn("Could not persist current language name", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPersistedLanguageName() {
|
||||
if (this.storageService == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final Optional<String> loaded = this.storageService.loadByPath(String.class, LANGUAGE_STORAGE_PATH, LANGUAGE_STORAGE_NAME);
|
||||
if (loaded.isPresent()) {
|
||||
this.currentLanguageName = loaded.get();
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
LOGGER.warn("Could not load persisted language name", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class G2DThemeManager implements ThemeManager {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(G2DThemeManager.class);
|
||||
|
||||
private static final List<String> THEME_STORAGE_PATH = List.of("gameEngine", "themes");
|
||||
private static final List<String> THEME_STORAGE_PATH = List.of("gameEngine");
|
||||
private static final String THEME_STORAGE_NAME = "lastTheme";
|
||||
|
||||
private G2DRenderer g2dRenderer;
|
||||
|
||||
@@ -10,17 +10,29 @@ import java.io.InputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
|
||||
class LocalizationManagerTest {
|
||||
|
||||
@Mock
|
||||
private StorageService storageService;
|
||||
|
||||
private LocalizationService localizationManager;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.localizationManager = new LocalizationServiceImpl();
|
||||
MockitoAnnotations.openMocks(this);
|
||||
this.localizationManager = new LocalizationServiceImpl(storageService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -278,4 +290,39 @@ class LocalizationManagerTest {
|
||||
assertEquals("Hello", englishGreeting);
|
||||
assertEquals("Hallo", germanGreeting);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPersistCurrentLanguage() {
|
||||
Localizations localizations = this.localizationManager.getLocalizations();
|
||||
Language english = new Language("English", "en");
|
||||
localizations.getLanguagesInfo().put("en", english);
|
||||
localizations.getLanguages().put("en", new LinkedHashMap<>(Map.of("greeting", "Hello")));
|
||||
|
||||
this.localizationManager.setLanguage("en");
|
||||
|
||||
verify(storageService).store(List.of("gameEngine"), "currentLanguage", "en");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadPersistedLanguage() {
|
||||
when(storageService.loadByPath(String.class, List.of("gameEngine"), "currentLanguage"))
|
||||
.thenReturn(Optional.of("de"));
|
||||
|
||||
// Load localizations with "de"
|
||||
Localizations localizationsToSave = new Localizations();
|
||||
Language german = new Language("German", "de");
|
||||
Map<String, String> germanEntries = new LinkedHashMap<>(Map.of("greeting", "Hallo"));
|
||||
localizationsToSave.getLanguagesInfo().put("de", german);
|
||||
localizationsToSave.getLanguages().put("de", germanEntries);
|
||||
localizationsToSave.setPrefix("i18n.");
|
||||
localizationsToSave.setCurId(1);
|
||||
|
||||
byte[] serialized = de.extio.game_engine.util.ObjectSerialization.serialize(
|
||||
localizationsToSave, false, false, false, null, digest -> {});
|
||||
InputStream stream = new ByteArrayInputStream(serialized);
|
||||
|
||||
this.localizationManager.load(stream);
|
||||
|
||||
assertEquals("de", this.localizationManager.getCurrentLanguage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.extio.game_engine.renderer.g2d.G2DRenderer;
|
||||
import de.extio.game_engine.renderer.g2d.G2DRendererControl;
|
||||
import de.extio.game_engine.renderer.model.options.UiOptions;
|
||||
import de.extio.game_engine.resource.StaticResource;
|
||||
import de.extio.game_engine.resource.StaticResourceService;
|
||||
import de.extio.game_engine.storage.StorageService;
|
||||
@@ -42,7 +45,7 @@ public class G2DThemeManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadsLastUsedThemeFromStorageOnConstruction() {
|
||||
void loadsLastUsedThemeFromStorage() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
@@ -50,7 +53,7 @@ public class G2DThemeManagerTest {
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final Theme persistedTheme = theme("Persisted");
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.of(persistedTheme));
|
||||
|
||||
final var manager = new G2DThemeManager(
|
||||
@@ -59,19 +62,21 @@ public class G2DThemeManagerTest {
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
manager.setCurrentTheme((Theme) null);
|
||||
|
||||
assertEquals("Persisted", manager.getCurrentTheme().getName());
|
||||
assertTrue(manager.getAvailableThemeNames().contains("Persisted"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setCurrentThemePersistsLastThemeObject() {
|
||||
final StaticResourceService staticResourceService = org.mockito.Mockito.mock(StaticResourceService.class);
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
final G2DRendererControl g2dRendererControl = org.mockito.Mockito.mock(G2DRendererControl.class);
|
||||
when(g2dRendererControl.getUiOptions()).thenReturn(new UiOptions());
|
||||
final G2DRenderer g2dRenderer = org.mockito.Mockito.mock(G2DRenderer.class);
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
final var manager = new G2DThemeManager(
|
||||
@@ -80,11 +85,13 @@ public class G2DThemeManagerTest {
|
||||
List.of(patternRenderer),
|
||||
Map.of("defaultKey", defaultTheme),
|
||||
"defaultKey");
|
||||
manager.setG2dRendererControl(g2dRendererControl);
|
||||
manager.setG2dRenderer(g2dRenderer);
|
||||
|
||||
final Theme selected = theme("Selected");
|
||||
manager.setCurrentTheme(selected);
|
||||
|
||||
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("lastTheme"), eq(selected));
|
||||
verify(storageService).store(eq(List.of("gameEngine")), eq("lastTheme"), eq(selected));
|
||||
assertTrue(manager.getAvailableThemeNames().contains("Selected"));
|
||||
}
|
||||
|
||||
@@ -94,7 +101,7 @@ public class G2DThemeManagerTest {
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
@@ -106,7 +113,7 @@ public class G2DThemeManagerTest {
|
||||
"defaultKey");
|
||||
|
||||
final Theme loaded = theme("FromStorage");
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("FromStorage")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("FromStorage")))
|
||||
.thenReturn(Optional.of(loaded));
|
||||
|
||||
final Optional<Theme> result = manager.loadThemeFromStorage("FromStorage");
|
||||
@@ -121,7 +128,7 @@ public class G2DThemeManagerTest {
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
@@ -149,7 +156,7 @@ public class G2DThemeManagerTest {
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
@@ -163,7 +170,7 @@ public class G2DThemeManagerTest {
|
||||
final Theme themeToSave = theme("UserTheme");
|
||||
manager.saveThemeToStorage(themeToSave);
|
||||
|
||||
verify(storageService).store(eq(List.of("gameEngine", "themes")), eq("UserTheme"), eq(themeToSave));
|
||||
verify(storageService).store(eq(List.of("gameEngine")), eq("UserTheme"), eq(themeToSave));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -204,7 +211,7 @@ public class G2DThemeManagerTest {
|
||||
final StorageService storageService = org.mockito.Mockito.mock(StorageService.class);
|
||||
final PatternRenderer patternRenderer = org.mockito.Mockito.mock(PatternRenderer.class);
|
||||
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine", "themes")), eq("lastTheme")))
|
||||
when(storageService.loadByPath(eq(Theme.class), eq(List.of("gameEngine")), eq("lastTheme")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
final Theme defaultTheme = theme("Default");
|
||||
|
||||
Reference in New Issue
Block a user