-
Notifications
You must be signed in to change notification settings - Fork 4
Feature #8: Localization services #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
371d53b
Implement LocalizationManager and LocalizedLogger
mialeska a95edd5
Add logger configuration and localization resources
mialeska b188521
Complete LocalizationManagerTests, fixed resource files, extracted IL…
mialeska 57e3a7b
Merge branch 'master' into Feature/8-Localization-Services
mialeska d465d0c
Complete LocalizationManagerTests, fixed resource files, extracted IL…
mialeska File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
src/main/java/aquality/selenium/core/localization/ILocalizationManager.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package aquality.selenium.core.localization; | ||
|
||
/** | ||
* This interface is used for translation messages to different languages. | ||
*/ | ||
public interface ILocalizationManager { | ||
/** | ||
* Gets localized message from resources by its key. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
* @return Localized message. | ||
*/ | ||
String getLocalizedMessage(String messageKey, Object... args); | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/aquality/selenium/core/localization/ILocalizationModule.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package aquality.selenium.core.localization; | ||
|
||
/** | ||
* Describes implementations of localization services to be registered in DI container. | ||
*/ | ||
public interface ILocalizationModule { | ||
/** | ||
* @return class which implements ILocalizationManager | ||
*/ | ||
default Class<? extends ILocalizationManager> getLocalizationManagerImplementation() { | ||
return LocalizationManager.class; | ||
} | ||
|
||
/** | ||
* @return class which implements ILocalizedLogger | ||
*/ | ||
default Class<? extends ILocalizedLogger> getLocalizedLoggerImplementation() { | ||
return LocalizedLogger.class; | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/main/java/aquality/selenium/core/localization/ILocalizedLogger.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package aquality.selenium.core.localization; | ||
|
||
/** | ||
* Log messages in current language. | ||
*/ | ||
public interface ILocalizedLogger { | ||
/** | ||
* Logs localized message for action with INFO level which is applied for element, for example, click, send keys etc. | ||
* @param elementType Type of the element. | ||
* @param elementName Name of the element. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void infoElementAction(String elementType, String elementName, String messageKey, Object... args); | ||
|
||
/** | ||
* Logs localized message with INFO level. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void info(String messageKey, Object... args); | ||
|
||
/** | ||
* Logs localized message with DEBUG level. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void debug(String messageKey, Object... args); | ||
|
||
/** | ||
* Logs localized message with DEBUG level. | ||
* @param messageKey Key in resource file. | ||
* @param throwable Throwable to log. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void debug(String messageKey, Throwable throwable, Object... args); | ||
|
||
/** | ||
* Logs localized message with WARN level. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void warn(String messageKey, Object... args); | ||
|
||
/** | ||
* Logs localized message with ERROR level. | ||
* @param messageKey Key in resource file. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void error(String messageKey, Object... args); | ||
|
||
/** | ||
* Logs localized message with FATAL level. | ||
* @param messageKey Key in resource file. | ||
* @param throwable Throwable to log. | ||
* @param args Arguments, which will be provided to template of localized message. | ||
*/ | ||
void fatal(String messageKey, Throwable throwable, Object... args); | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/aquality/selenium/core/localization/LocalizationManager.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package aquality.selenium.core.localization; | ||
|
||
import aquality.selenium.core.configurations.ILoggerConfiguration; | ||
import aquality.selenium.core.logging.Logger; | ||
import aquality.selenium.core.utilities.ISettingsFile; | ||
import aquality.selenium.core.utilities.JsonSettingsFile; | ||
import com.google.inject.Inject; | ||
|
||
public class LocalizationManager implements ILocalizationManager { | ||
private static final String LANG_RESOURCE_TEMPLATE = "localization/%1$s.json"; | ||
private final ISettingsFile localizationFile; | ||
private final Logger logger; | ||
private final String locResourceName; | ||
|
||
@Inject | ||
public LocalizationManager(ILoggerConfiguration loggerConfiguration, Logger logger) { | ||
this.logger = logger; | ||
String language = loggerConfiguration.getLanguage(); | ||
locResourceName = String.format(LANG_RESOURCE_TEMPLATE, language.toLowerCase()); | ||
localizationFile = new JsonSettingsFile(locResourceName); | ||
} | ||
|
||
@Override | ||
public String getLocalizedMessage(String messageKey, Object... args) { | ||
String jsonKeyPath = "/".concat(messageKey); | ||
if (localizationFile.isValuePresent(jsonKeyPath)) { | ||
return String.format(localizationFile.getValue(jsonKeyPath).toString(), args); | ||
} | ||
|
||
logger.warn(String.format("Cannot find localized message by key '%1$s' in resource file %2$s", | ||
jsonKeyPath, locResourceName)); | ||
return messageKey; | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/aquality/selenium/core/localization/LocalizedLogger.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package aquality.selenium.core.localization; | ||
|
||
import aquality.selenium.core.logging.Logger; | ||
import com.google.inject.Inject; | ||
|
||
public class LocalizedLogger implements ILocalizedLogger { | ||
|
||
private final ILocalizationManager localizationManager; | ||
private final Logger logger; | ||
|
||
@Inject | ||
public LocalizedLogger(ILocalizationManager localizationManager, Logger logger) { | ||
this.localizationManager = localizationManager; | ||
this.logger = logger; | ||
} | ||
|
||
private String localizeMessage(String messageKey, Object... args) { | ||
return localizationManager.getLocalizedMessage(messageKey, args); | ||
} | ||
|
||
@Override | ||
public void infoElementAction(String elementType, String elementName, String messageKey, Object... args) { | ||
String message = String.format("%1$s '%2$s' :: %3$s", elementType, elementName, localizeMessage(messageKey, args)); | ||
logger.info(message); | ||
} | ||
|
||
@Override | ||
public void info(String messageKey, Object... args) { | ||
logger.info(localizeMessage(messageKey, args)); | ||
} | ||
|
||
@Override | ||
public void debug(String messageKey, Object... args) { | ||
logger.debug(localizeMessage(messageKey, args)); | ||
} | ||
|
||
@Override | ||
public void debug(String messageKey, Throwable throwable, Object... args) { | ||
logger.debug(localizeMessage(messageKey, args), throwable); | ||
} | ||
|
||
@Override | ||
public void warn(String messageKey, Object... args) { | ||
logger.warn(localizeMessage(messageKey, args)); | ||
} | ||
|
||
@Override | ||
public void error(String messageKey, Object... args) { | ||
logger.error(localizeMessage(messageKey, args)); | ||
} | ||
|
||
@Override | ||
public void fatal(String messageKey, Throwable throwable, Object... args) { | ||
logger.fatal(localizeMessage(messageKey, args), throwable); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"loc.clicking": "Націскаем", | ||
"loc.el.getattr": "Атрымліваем атрыбут '%1$s'", | ||
"loc.get.text": "Атрымліваем тэкст элемента", | ||
"loc.text.sending.keys": "Націскаем клавішы '%1$s'", | ||
"loc.no.elements.found.in.state": "Не знайшлі элементаў па лакатару '%1$s' у %2$s стане", | ||
"loc.no.elements.found.by.locator": "Не знайшлі элементаў па лакатару '%1$s'", | ||
"loc.elements.were.found.but.not.in.state": "Знайшлі элементы па лакатару '%1$s', але яны не ў жаданым стане %2$s", | ||
"loc.elements.found.but.should.not": "Не павінна быць знойдзена элементаў па лакатару '%1$s' у %2$s стане", | ||
"loc.search.of.elements.failed": "Пошук элемента па лакатару '%1$s' прайшоў няўдала" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"loc.clicking": "Clicking", | ||
"loc.el.getattr": "Getting attribute '%1$s'", | ||
"loc.get.text": "Getting text from element", | ||
"loc.text.sending.keys": "Sending keys '%1$s'", | ||
"loc.no.elements.found.in.state": "No elements with locator '%1$s' were found in %2$s state", | ||
"loc.no.elements.found.by.locator": "No elements were found by locator '%1$s'", | ||
"loc.elements.were.found.but.not.in.state": "Elements were found by locator '%1$s' but not in desired state %2$s", | ||
"loc.elements.found.but.should.not": "No elements should be found by locator '%1$s' in %2$s state", | ||
"loc.search.of.elements.failed": "Search of element by locator '%1$s' failed" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"loc.clicking": "Клик", | ||
"loc.el.getattr": "Получение аттрибута '%1$s'", | ||
"loc.get.text": "Получение текста элемента", | ||
"loc.text.sending.keys": "Нажатие клавиши '%1$s'", | ||
"loc.no.elements.found.in.state": "Не удалось найти элементов по локатору '%1$s' в %2$s состоянии", | ||
"loc.no.elements.found.by.locator": "Не удалось найти элементов по локатору '%1$s'", | ||
"loc.elements.were.found.but.not.in.state": "Удалось найти элементы по локатору '%1$s', но они не в желаемом состоянии %2$s", | ||
"loc.elements.found.but.should.not": "Не должно быть найдено элементов по локатору '%1$s' в %2$s состоянии", | ||
"loc.search.of.elements.failed": "Поиск элемента по локатору '%1$s' прошел неудачно" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
log4j.rootLogger=INFO, stdout, file | ||
log4j.rootLogger=DEBUG, stdout, file | ||
|
||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender | ||
log4j.appender.stdout.encoding=UTF-8 | ||
log4j.appender.stdout.target=System.out | ||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout | ||
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n | ||
log4j.appender.stdout.Threshold=INFO | ||
|
||
log4j.appender.file = org.apache.log4j.RollingFileAppender | ||
log4j.appender.file.File = target/log/log.log | ||
log4j.appender.file.MaxFileSize=10MB | ||
log4j.appender.file.layout=org.apache.log4j.PatternLayout | ||
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n | ||
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p - %m%n | ||
log4j.appender.file.Threshold=DEBUG |
114 changes: 114 additions & 0 deletions
114
src/test/java/tests/localization/LocalizationManagerTests.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package tests.localization; | ||
|
||
import aquality.selenium.core.configurations.ILoggerConfiguration; | ||
import aquality.selenium.core.localization.ILocalizationManager; | ||
import aquality.selenium.core.localization.LocalizationManager; | ||
import aquality.selenium.core.logging.Logger; | ||
import org.testng.Assert; | ||
import org.testng.annotations.DataProvider; | ||
import org.testng.annotations.Test; | ||
import tests.application.CustomAqualityServices; | ||
import tests.application.browser.AqualityServices; | ||
|
||
import java.util.MissingFormatArgumentException; | ||
|
||
import static org.testng.Assert.assertEquals; | ||
|
||
public class LocalizationManagerTests { | ||
private static final String[] SUPPORTED_LANGUAGES = new String[]{"be", "en", "ru"}; | ||
private static final String CLICKING_MESSAGE_KEY = "loc.clicking"; | ||
|
||
@DataProvider | ||
private Object[] keysWithParams() { | ||
return new String[]{ | ||
"loc.el.getattr", | ||
"loc.text.sending.keys", | ||
"loc.no.elements.found.in.state", | ||
"loc.no.elements.found.by.locator", | ||
"loc.elements.were.found.but.not.in.state", | ||
"loc.elements.found.but.should.not", | ||
"loc.search.of.elements.failed"}; | ||
} | ||
|
||
@DataProvider | ||
private Object[] keysWithoutParams() { | ||
return new String[]{ | ||
CLICKING_MESSAGE_KEY, | ||
"loc.get.text"}; | ||
} | ||
|
||
|
||
private LocalizationManager getLocalizationManager() { | ||
return new LocalizationManager( | ||
AqualityServices.getServiceProvider().getInstance(ILoggerConfiguration.class), | ||
Logger.getInstance()); | ||
} | ||
|
||
private LocalizationManager getLocalizationManager(String language) { | ||
return new LocalizationManager(() -> language, Logger.getInstance()); | ||
} | ||
|
||
@Test | ||
public void testShouldReturnUnknownKey() { | ||
String unknownKey = "loc.unknown.fake.key"; | ||
Assert.assertEquals(unknownKey, getLocalizationManager().getLocalizedMessage(unknownKey)); | ||
} | ||
|
||
@Test | ||
public void testShouldBeRegisteredAsSingleton() { | ||
assertEquals(CustomAqualityServices.getServiceProvider().getInstance(ILocalizationManager.class), | ||
CustomAqualityServices.getServiceProvider().getInstance(ILocalizationManager.class)); | ||
} | ||
|
||
@Test | ||
public void testShouldBePossibleToUseForClicking() { | ||
assertEquals(getLocalizationManager().getLocalizedMessage(CLICKING_MESSAGE_KEY), "Clicking", | ||
"Logger should be configured in English by default and return valid value"); | ||
} | ||
|
||
@Test | ||
public void testShouldBePossibleToUseForClickingWithCustomLanguage() { | ||
assertEquals(getLocalizationManager("be").getLocalizedMessage(CLICKING_MESSAGE_KEY), "Націскаем", | ||
"Logger should be configured in custom language when use custom profile, and return valid value"); | ||
} | ||
|
||
@Test(dataProvider = "keysWithParams") | ||
public void testShouldThrowFormatExceptionWhenKeysRequireParams(String keyWithParams) { | ||
for (String language: SUPPORTED_LANGUAGES) { | ||
Assert.assertThrows(MissingFormatArgumentException.class, | ||
() -> getLocalizationManager(language).getLocalizedMessage(keyWithParams)); | ||
} | ||
} | ||
|
||
@Test(dataProvider = "keysWithoutParams") | ||
public void testShouldReturnNonKeyAndNonEmptyValuesForKeysWithoutParams(String keyWithoutParams) { | ||
for (String language: SUPPORTED_LANGUAGES) { | ||
String value = getLocalizationManager(language).getLocalizedMessage(keyWithoutParams); | ||
Assert.assertFalse(value.isEmpty(), | ||
String.format("value of key %1$s in language %2$s should not be empty", keyWithoutParams, language)); | ||
Assert.assertNotEquals(value, keyWithoutParams, | ||
String.format("value of key %1$s in language %2$s should be defined", keyWithoutParams, language)); | ||
} | ||
} | ||
|
||
@Test(dataProvider = "keysWithParams") | ||
public void testShouldReturnNonKeyAndNonEmptyValuesForKeysWithParams(String keyWithParams) { | ||
for (String language: SUPPORTED_LANGUAGES) { | ||
Object[] params = new String[] { "a", "b", "c" }; | ||
String value = getLocalizationManager(language).getLocalizedMessage(keyWithParams, params); | ||
Assert.assertFalse(value.isEmpty(), | ||
String.format("value of key %1$s in language %2$s should not be empty", keyWithParams, language)); | ||
Assert.assertNotEquals(value, keyWithParams, | ||
String.format("value of key %1$s in language %2$s should be defined", keyWithParams, language)); | ||
Assert.assertTrue(value.contains(params[0].toString()), | ||
String.format("value of key %1$s in language %2$s should contain at least first parameter", | ||
keyWithParams, language)); | ||
} | ||
} | ||
|
||
@Test | ||
public void testShouldThrowWhenInvalidLanguageSupplied() { | ||
Assert.assertThrows(IllegalArgumentException.class, () -> | ||
getLocalizationManager("invalid").getLocalizedMessage(CLICKING_MESSAGE_KEY)); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.