diff --git a/boms/minimal/pom.xml b/boms/minimal/pom.xml index d012299a..16dfb4dc 100644 --- a/boms/minimal/pom.xml +++ b/boms/minimal/pom.xml @@ -65,6 +65,11 @@ devon4j-beanmapping-orika ${project.version} + + com.devonfw.java.modules + devon4j-i18n + ${project.version} + com.devonfw.java.modules devon4j-security diff --git a/modules/i18n/pom.xml b/modules/i18n/pom.xml new file mode 100644 index 00000000..1daee873 --- /dev/null +++ b/modules/i18n/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.devonfw.java.dev + devon4j-modules + dev-SNAPSHOT + + com.devonfw.java.modules + devon4j-i18n + ${devon4j.version} + ${project.artifactId} + jar + Module for i18n. + + + + net.sf.m-m-m + mmm-util-cli + 7.0.0 + + + net.sf.m-m-m + mmm-util-nls + + + com.google.code.gson + gson + + + commons-lang + commons-lang + 2.6 + + + org.json + json + + + com.devonfw.java.modules + devon4j-test + test + + + \ No newline at end of file diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/exception/UnknownLocaleException.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/exception/UnknownLocaleException.java new file mode 100644 index 00000000..66d0b8ed --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/exception/UnknownLocaleException.java @@ -0,0 +1,35 @@ +package com.devonfw.module.i18n.common.api.exception; + +/** + * Signals Exception when locale is not found + * + */ +public class UnknownLocaleException extends RuntimeException { + + /** + * Default serial version UID + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new {@link UnknownLocaleException} with the given message + * + * @param msg error message + */ + public UnknownLocaleException(String msg) { + + super(msg); + } + + /** + * Creates a new {@link UnknownLocaleException} with the given message and the given cause + * + * @param msg error message + * @param ex cause of the created exception + */ + public UnknownLocaleException(String msg, Throwable ex) { + + super(msg, ex); + } + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/nls/NlsBundleI18nRoot.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/nls/NlsBundleI18nRoot.java new file mode 100644 index 00000000..202cae0f --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/api/nls/NlsBundleI18nRoot.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright 2015-2018 Capgemini SE. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package com.devonfw.module.i18n.common.api.nls; + +import javax.inject.Named; + +import net.sf.mmm.util.nls.api.NlsBundle; +import net.sf.mmm.util.nls.api.NlsBundleMessage; +import net.sf.mmm.util.nls.api.NlsMessage; + +/** + * This is the {@link NlsBundle} for this application. + * + * @author kugawand + * @since dev + * + */ + +public interface NlsBundleI18nRoot extends NlsBundle { + /** + * @param name + * @return + */ + @SuppressWarnings("javadoc") + @NlsBundleMessage("{name}. This Module is related to internationalization ") + public NlsMessage getLocale(@Named("name") String name); + + /** + * @param name + * @return + */ + @SuppressWarnings("javadoc") + @NlsBundleMessage("Hello {name}") + NlsMessage messageSayHi(@Named("name") String name); + + @NlsBundleMessage("Sorry. The login \"{login}\" is already in use. Please choose a different login.") + NlsMessage errorLoginInUse(@Named("login") String login); +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/BundleMapSerializer.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/BundleMapSerializer.java new file mode 100644 index 00000000..ee0de52c --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/BundleMapSerializer.java @@ -0,0 +1,95 @@ +package com.devonfw.module.i18n.common.util; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * {@link JsonSerializer} for {@link Map}. + */ +public class BundleMapSerializer implements JsonSerializer> { + + private static final Logger LOG = LoggerFactory.getLogger(BundleMapSerializer.class); + + /** + * {@inheritDoc} + */ + @Override + public JsonElement serialize(final Map bundleMap, final Type typeOfSrc, + final JsonSerializationContext context) { + + final JsonObject resultJson = new JsonObject(); + + for (final String key : bundleMap.keySet()) { + try { + createFromBundleKey(resultJson, key, bundleMap.get(key)); + } catch (final IOException e) { + LOG.error("Bundle Map Serialization Exception: ", e); + } + } + + return resultJson; + } + + /** + * @param resultJson JSON that will be returned for a filter + * @param key from the resource Bundle + * @param value from the resource Bundle + * @return JsonObject JSON that will be returned for a key + * @throws IOException thrown by createFromBundleKey + */ + private static JsonObject createFromBundleKey(final JsonObject resultJson, final String key, final String value) + throws IOException { + + if (!key.contains(I18nConstants.DOT)) { + resultJson.addProperty(key, value); + + return resultJson; + } + + final String currentKey = firstKey(key); + + if (currentKey != null) { + final String subRightKey = key.substring(currentKey.length() + 1, key.length()); + final JsonObject childJson = getJsonIfExists(resultJson, currentKey); + resultJson.add(currentKey, createFromBundleKey(childJson, subRightKey, value)); + } + + return resultJson; + } + + private static String firstKey(final String fullKey) { + + final String[] splittedKey = fullKey.split("\\."); + + return (splittedKey.length != 0) ? splittedKey[0] : fullKey; + } + + private static JsonObject getJsonIfExists(final JsonObject parent, final String key) { + + if (parent == null) { + LOG.warn("Parent json parameter is null!"); + return null; + } + + if (parent.get(key) != null && !(parent.get(key) instanceof JsonObject)) { + throw new IllegalArgumentException("Invalid key \'" + key + "\' for parent: " + parent + + "\nKey can not be JSON object and property or array at a time"); + } + + if (parent.getAsJsonObject(key) != null) { + return parent.getAsJsonObject(key); + } else { + return new JsonObject(); + } + } + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nConstants.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nConstants.java new file mode 100644 index 00000000..bfa2eabf --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nConstants.java @@ -0,0 +1,86 @@ +package com.devonfw.module.i18n.common.util; + +/** + * Constants for i18n module + * + */ +public class I18nConstants { + + /** + * Constant for the character DOT + */ + public static final String DOT = "."; + + /** + * Constant for the character 0 + */ + public static final int ZERO = 0; + + /** + * Constant for the Error message in case of Invalid Locale + */ + public static final String INVALID_LOCALE = "Invalid Locale . Please provide valid Locale"; + + /** + * Constants for Resource path for NLS bundle + * + * The files needed to be store in following package, and file name will be starting with NlsBundleI18n + * + * sample - com\devonfw\module\i18n\common\api\nls\NlsBundleI18n_en.properties + */ + public static final String NLS_BUNDLE_INTF_NAME = "com/devonfw/module/i18n/common/api/nls/NlsBundleI18n"; + + /** + * Empty String + */ + public static final String EMPTY_STRING = ""; + + /** + * + */ + // public static final String LOCALE_FILES_LOCATION = "src/main/resources/locale/"; + + /** + * Constants for resource for other locale integration using gson option + * + * The files needed to be store in following package, and file name will be starting with messages + * + * Sample file - locale\messages_en_US.properties + */ + public static final String RESOURCE_BASENAME = "locale/messages"; + + /** + * Closing bracket + */ + public static final String CLOSING_BRACE = "}"; + + /** + * Opening bracket + */ + public static final String OPENING_BRACE = "{"; + + /** + * Underscore + */ + public static final String UNDER_SCORE = "_"; + + /** + * Property file extension + */ + public static final String PROPERTIES = "properties"; + + /** + * English locale + * + */ + public static final String en = "en"; + + /** + * Constants for Resource path for NLS bundle - qualified name. + * + * The files needed to be store in following package, and file name will be starting with NlsBundleI18n + * + * sample - com\devonfw\module\i18n\common\api\nls\NlsBundleI18n_en.properties + */ + public static final String NLS_BUNDLE_INTF_QUAL_NAME = "com.devonfw.module.i18n.common.api.nls.NlsBundleI18n"; +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nUtils.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nUtils.java new file mode 100644 index 00000000..39d3688e --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/common/util/I18nUtils.java @@ -0,0 +1,198 @@ +package com.devonfw.module.i18n.common.util; + +import java.io.File; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +import net.sf.mmm.util.nls.base.ResourceBundleControlUtf8WithNlsBundleSupport; + +import org.json.JSONException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; + +/** + * Utility class for i18n module. + * + */ +public class I18nUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(I18nUtils.class); + + /** + * @param resource is the bundle of message resources + * @return map containing key value pairs of message resources + */ + public static Map convertResourceBundleToMap(ResourceBundle resource) { + + Map map = new HashMap<>(); + + Enumeration keys = resource.getKeys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + map.put(key, resource.getString(key)); + } + return map; + } + + /** + * @param objJSON JSON String which is the representation of key value pairs in message resources property file + * @param filter passed from the service + * @param strJSONKey JSON Key + * @param count used to traverse the JSON + * @return JSON String that is matched against the filter + * @throws JSONException thrown by getWithDotNotation + */ + public static String getWithDotNotation(JsonObject objJSON, String filter, String strJSONKey, int count) + throws JSONException { + + String closingBraces = I18nConstants.EMPTY_STRING; + String strJSON = I18nConstants.EMPTY_STRING; + if (filter.contains(I18nConstants.DOT)) { + int indexOfDot = filter.indexOf(I18nConstants.DOT); + String subKey = filter.substring(0, indexOfDot); + JsonObject jsonObject = (JsonObject) objJSON.get(subKey); + count++; + strJSONKey = strJSONKey + "{\"" + subKey + "\":"; + if (jsonObject == null) { + throw new JSONException(subKey + " is null"); + } + try { + return getWithDotNotation(jsonObject, filter.substring(indexOfDot + 1), strJSONKey, count); + } catch (JSONException e) { + throw new JSONException(subKey + I18nConstants.DOT + e.getMessage()); + } + } else { + for (int i = 0; i <= count; i++) { + closingBraces = closingBraces + I18nConstants.CLOSING_BRACE; + } + + if (objJSON.get(filter) == null) + strJSON = I18nConstants.OPENING_BRACE + I18nConstants.CLOSING_BRACE; + else + strJSON = strJSONKey + "{\"" + filter + "\":" + objJSON.get(filter).toString() + closingBraces; + } + return strJSON; + } + + /** + * @param objJSON is the JSON representation of the resource file + * @param filter is the filter supplied from service + * @return JSON object filtered by the filter + * @throws Exception thrown by getJsonObj + */ + + public static String getJsonObj(JsonObject objJSON, String filter) throws Exception { + + String strJSON = null; + String strJSONKey = I18nConstants.EMPTY_STRING; + int count = I18nConstants.ZERO; + if (filter == null) { + throw new JSONException("Null key."); + } + if (objJSON != null) { + strJSON = getWithDotNotation(objJSON, filter, strJSONKey, count); + } + return strJSON; + } + + /** + * @param resourceMap contains the resources in the form of key value pairs + * @param filter received from service + * @return resources as JSON String + * @throws Exception thrown by getResourcesAsJSON + */ + public static String getResourcesAsJSON(HashMap resourceMap, String filter) throws Exception { + + JsonParser jsonParser = new JsonParser(); + + final java.lang.reflect.Type mapType = new TypeToken>() { + }.getType(); + + String strJSON = new GsonBuilder().registerTypeAdapter(mapType, new BundleMapSerializer()).create() + .toJson(resourceMap, mapType); + + if (filter != null && !filter.isEmpty()) { + JsonObject obj = (JsonObject) jsonParser.parse(strJSON); + strJSON = I18nUtils.getJsonObj(obj, filter); + } + return strJSON; + } + + /** + * @param locale received from service + * @return resources generated by MMM as Map + * @throws Exception thrown by getResourcesGeneratedFromMMMAsMap + */ + + public static Map getResourcesGeneratedFromMMMAsMap(Locale locale) throws Exception { + + HashMap resourceMap = new HashMap<>(); + ResourceBundle resBundle = null; + File objResourcesFile = null; + try { + String language = locale.getLanguage(); + + String resourcePath = I18nConstants.NLS_BUNDLE_INTF_NAME + I18nConstants.UNDER_SCORE + language + + I18nConstants.DOT + I18nConstants.PROPERTIES; + URL url = I18nUtils.class.getClassLoader().getResource(resourcePath); + if (url != null) { + objResourcesFile = new File(url.getPath()); + } + + if (objResourcesFile != null && objResourcesFile.exists() && !language.equals(I18nConstants.en)) { + resBundle = ResourceBundle.getBundle( + I18nConstants.NLS_BUNDLE_INTF_QUAL_NAME + I18nConstants.UNDER_SCORE + new Locale(locale.getLanguage()), + locale, ResourceBundleControlUtf8WithNlsBundleSupport.INSTANCE); + } else { + resBundle = ResourceBundle.getBundle(I18nConstants.NLS_BUNDLE_INTF_QUAL_NAME, + ResourceBundleControlUtf8WithNlsBundleSupport.INSTANCE); + } + resourceMap = (HashMap) I18nUtils.convertResourceBundleToMap(resBundle); + } catch (Throwable t) { + LOGGER.error("Exception in getResourcesGeneratedFromMMMAsMap ", t); + throw t; + } + return resourceMap; + } + + /** + * @param locale received from service + * @param objLocale Locale object created out of locale received from service + * @return resources generated by Default Implementation as Map + * @throws Exception thrown by getResourcesGeneratedFromMMMAsMap + */ + public static Map getResourcesGeneratedFromDefaultImplAsMap(String locale, Locale objLocale) + throws Exception { + + HashMap resourceMap = new HashMap<>(); + ResourceBundle resBundle = null; + try { + resBundle = ResourceBundle.getBundle(I18nConstants.RESOURCE_BASENAME + I18nConstants.UNDER_SCORE + locale, + objLocale); + resourceMap = (HashMap) I18nUtils.convertResourceBundleToMap(resBundle); + } catch (Throwable t) { + LOGGER.error("Exception in getResourcesGeneratedFromDefaultImplAsMap ", t); + throw t; + } + return resourceMap; + } + + /** + * @param locale String that contains language and country code separated by hyphen + * @return Locale Object + */ + public static Locale getLocale(String locale) { + + String[] arrLocale = locale.split(I18nConstants.UNDER_SCORE); + return new Locale(arrLocale[0], arrLocale[1]); + } +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/I18n.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/I18n.java new file mode 100644 index 00000000..68d0b07b --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/I18n.java @@ -0,0 +1,20 @@ +package com.devonfw.module.i18n.locale.api; + +/** + * Interface for getting JSON using locale and filter. + * + */ + +public interface I18n { + + /** + * Gets the JSON string for specified locale and filter + * + * @param locale locale + * @param filter + * @return Json String + * @throws Exception + */ + String getResourceObject(String locale, String filter) throws Exception; + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/LocaleResourceFactory.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/LocaleResourceFactory.java new file mode 100644 index 00000000..f4315f5a --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/api/LocaleResourceFactory.java @@ -0,0 +1,20 @@ +package com.devonfw.module.i18n.locale.api; + +import com.devonfw.module.i18n.locale.impl.LocaleNlsResourceImpl; +import com.devonfw.module.i18n.locale.impl.LocaleResourceImpl; + +/** + * Factory for generating JSON according to implementation see {@link LocaleResourceImpl} , + * {@link LocaleNlsResourceImpl} + * + */ +public interface LocaleResourceFactory { + /** + * @param locale + * @param filter + * @return + * @throws Exception + */ + String getResourceAsJson(String locale, String filter) throws Exception; + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/I18nImpl.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/I18nImpl.java new file mode 100644 index 00000000..caad1d48 --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/I18nImpl.java @@ -0,0 +1,36 @@ +package com.devonfw.module.i18n.locale.impl; + +import com.devonfw.module.i18n.locale.api.I18n; +import com.devonfw.module.i18n.locale.api.LocaleResourceFactory; + +/** + * Basic implementation of the {@link I18n} interface. + * + */ + +public class I18nImpl implements I18n { + + private LocaleResourceFactory localeResource; + + /** + * The constructor. + * + * @param localeResource + */ + public I18nImpl(LocaleResourceFactory localeResource) { + + super(); + this.localeResource = localeResource; + } + + @Override + public String getResourceObject(String locale, String filter) throws Exception { + + String jsonString = null; + + jsonString = this.localeResource.getResourceAsJson(locale, filter); + + return jsonString; + } + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleNlsResourceImpl.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleNlsResourceImpl.java new file mode 100644 index 00000000..62deed41 --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleNlsResourceImpl.java @@ -0,0 +1,48 @@ +package com.devonfw.module.i18n.locale.impl; + +import java.util.HashMap; +import java.util.Locale; + +import org.apache.commons.lang.LocaleUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.devonfw.module.i18n.common.api.exception.UnknownLocaleException; +import com.devonfw.module.i18n.common.util.I18nConstants; +import com.devonfw.module.i18n.common.util.I18nUtils; +import com.devonfw.module.i18n.locale.api.LocaleResourceFactory; + +/** + * NLS(Native Language Support) based Implementation for {@link LocaleResourceFactory} + * + */ +public class LocaleNlsResourceImpl implements LocaleResourceFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(I18nImpl.class); + + @Override + public String getResourceAsJson(String locale, String filter) throws Exception { + + String strJSON = null; + HashMap resourceMap = new HashMap<>(); + Locale objLocale = null; + + try { + objLocale = I18nUtils.getLocale(locale); + if (locale == null || locale.isEmpty() || !LocaleUtils.availableLocaleSet().contains(objLocale)) { + throw new UnknownLocaleException(I18nConstants.INVALID_LOCALE); + } else { + resourceMap = (HashMap) I18nUtils.getResourcesGeneratedFromMMMAsMap(objLocale); + strJSON = I18nUtils.getResourcesAsJSON(resourceMap, filter); + } + } catch (UnknownLocaleException de) { + LOGGER.error("Exception in getResourcesAsJSONStringUsingMMM ", de); + throw de; + } catch (Exception e) { + LOGGER.error("Exception in getResourcesAsJSONStringUsingMMM ", e); + throw e; + } + return strJSON; + } + +} diff --git a/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleResourceImpl.java b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleResourceImpl.java new file mode 100644 index 00000000..73410473 --- /dev/null +++ b/modules/i18n/src/main/java/com/devonfw/module/i18n/locale/impl/LocaleResourceImpl.java @@ -0,0 +1,49 @@ +package com.devonfw.module.i18n.locale.impl; + +import java.util.HashMap; +import java.util.Locale; + +import org.apache.commons.lang.LocaleUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.devonfw.module.i18n.common.api.exception.UnknownLocaleException; +import com.devonfw.module.i18n.common.util.I18nConstants; +import com.devonfw.module.i18n.common.util.I18nUtils; +import com.devonfw.module.i18n.locale.api.LocaleResourceFactory; + +/** + * Basic Implementation for {@link LocaleResourceFactory} based on {@link com.google.gson.Gson} + * + */ +public class LocaleResourceImpl implements LocaleResourceFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(LocaleResourceImpl.class); + + @Override + public String getResourceAsJson(String locale, String filter) throws Exception { + + String strJSON = null; + Locale objLocale = null; + HashMap resourceMap = new HashMap<>(); + + try { + objLocale = I18nUtils.getLocale(locale); + + if (locale == null || locale.isEmpty() || !LocaleUtils.availableLocaleSet().contains(objLocale)) { + throw new UnknownLocaleException(I18nConstants.INVALID_LOCALE); + } + + resourceMap = (HashMap) I18nUtils.getResourcesGeneratedFromDefaultImplAsMap(locale, objLocale); + strJSON = I18nUtils.getResourcesAsJSON(resourceMap, filter); + } catch (UnknownLocaleException de) { + LOGGER.error("Exception in getResourcesAsJSONStringUsingDefaultImpl ", de); + throw de; + } catch (Exception e) { + LOGGER.error("Exception in getResourcesAsJSONStringUsingDefaultImpl ", e); + throw e; + } + return strJSON; + } + +} diff --git a/modules/i18n/src/test/java/com/devonfw/module/i18n/logic/impl/I18nImplTest.java b/modules/i18n/src/test/java/com/devonfw/module/i18n/logic/impl/I18nImplTest.java new file mode 100644 index 00000000..57c92370 --- /dev/null +++ b/modules/i18n/src/test/java/com/devonfw/module/i18n/logic/impl/I18nImplTest.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright 2015-2018 Capgemini SE. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ +package com.devonfw.module.i18n.logic.impl; + +import org.junit.jupiter.api.Test; + +import com.devonfw.module.i18n.locale.api.I18n; +import com.devonfw.module.i18n.locale.impl.I18nImpl; +import com.devonfw.module.i18n.locale.impl.LocaleNlsResourceImpl; +import com.devonfw.module.i18n.locale.impl.LocaleResourceImpl; +//import com.devonfw.module.i18n.common.I18nTestApp; +import com.devonfw.module.test.common.base.ComponentTest; + +/** + * Test cases for i18n (Internationalization) + * + */ +public class I18nImplTest extends ComponentTest { + + /** + * @throws Exception thrown by testlanguageFiles + */ + @SuppressWarnings("unused") + @Test + public void testlanguageFiles() throws Exception { + + I18n i18nDefaultImpl = new I18nImpl(new LocaleResourceImpl()); + I18n i18nNlsImpl = new I18nImpl(new LocaleNlsResourceImpl()); + // given + assertThat(i18nDefaultImpl).isNotNull(); + assertThat(i18nNlsImpl).isNotNull(); + + // With default implementation + + String strWholeFile = i18nDefaultImpl.getResourceObject("en_US", ""); + assertThat(strWholeFile).isNotNull(); + + String strKeyValue = i18nDefaultImpl.getResourceObject("en_US", "i18n.msg.helloworld"); // when + assertThat(strKeyValue).isNotNull(); // then + assertThat(strKeyValue).isEqualTo("{\"i18n\":{\"msg\":{\"helloworld\":\"Hello World\"}}}"); + + String strUnknownkey = i18nDefaultImpl.getResourceObject("en_US", "unknownkey"); // when + assertThat(strUnknownkey).isNotNull(); // then assertThat(strUnknownkey).isEqualTo("{}"); + + String strWholeFile_DE = i18nDefaultImpl.getResourceObject("de_DE", ""); + assertThat(strWholeFile_DE).isNotNull(); + // With MMM implementation + + String strMmmWholeFile = i18nNlsImpl.getResourceObject("en_US", ""); + assertThat(strMmmWholeFile).isNotNull(); + + String strMmmKeyValue = i18nNlsImpl.getResourceObject("en_US", "getLocale"); // when + assertThat(strMmmKeyValue).isNotNull(); + // then + assertThat(strMmmKeyValue) + .isEqualTo("{\"getLocale\":\"TODO(en):{name}. This Module is related to internationalization\"}"); + + String strMmmUnknownkey = i18nNlsImpl.getResourceObject("en_US", "unknownkey"); // when + assertThat(strMmmUnknownkey).isNotNull(); // then assertThat(strMmmUnknownkey).isEqualTo("{}"); + + } +}; diff --git a/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_de.properties b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_de.properties new file mode 100644 index 00000000..d9affc53 --- /dev/null +++ b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_de.properties @@ -0,0 +1,4 @@ +# Generated 2016-07-22 17:52:35 +0530 +getLocale.test = German. This Module is related to internationalization +messageSayHi = German:Hello {name} +errorLoginInUse = German:Sorry. The login "{login}" is already in use. Please choose a different login. diff --git a/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_en.properties b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_en.properties new file mode 100644 index 00000000..56b32ecd --- /dev/null +++ b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_en.properties @@ -0,0 +1,5 @@ +# Generated 2016-07-21 16:01:29 +0530 +getLocale = TODO(en):{name}. This Module is related to internationalization +messageSayHi = TODO(en):Hello {name} +# Updated 2017-03-01 14:51:59 +0530 +errorLoginInUse = TODO(en):Sorry. The login "{login}" is already in use. Please choose a different login. diff --git a/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr.properties b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr.properties new file mode 100644 index 00000000..7ff54c40 --- /dev/null +++ b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr.properties @@ -0,0 +1,4 @@ +# Generated 2020-02-07 23:05:09 +0530 +messageSayHi = TODO(fr):Hello {name} +errorLoginInUse = TODO(fr):Sorry. The login "{login}" is already in use. Please choose a different login. +getLocale = TODO(fr):{name}. This Module is related to internationalization diff --git a/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr2.properties b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr2.properties new file mode 100644 index 00000000..c0194899 --- /dev/null +++ b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_fr2.properties @@ -0,0 +1,4 @@ +# Generated 2016-11-07 17:11:10 +0530 +getLocale = TODO(fr):{name}. This Module is related to internationalization +messageSayHi = TODO(fr):Hello {name} +errorLoginInUse = TODO(fr):Sorry. The login "{login}" is already in use. Please choose a different login. diff --git a/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_in.properties b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_in.properties new file mode 100644 index 00000000..aa27f4cb --- /dev/null +++ b/modules/i18n/src/test/resources/com/devonfw/module/i18n/common/api/nls/NlsBundleI18n_in.properties @@ -0,0 +1,4 @@ +# Generated 2020-02-07 20:43:44 +0530 +messageSayHi = TODO(in):Hello {name} +errorLoginInUse = TODO(in):Sorry. The login "{login}" is already in use. Please choose a different login. +getLocale = TODO(in):{name}. This Module is related to internationalization diff --git a/modules/i18n/src/test/resources/locale/messages_de_DE.properties b/modules/i18n/src/test/resources/locale/messages_de_DE.properties new file mode 100644 index 00000000..7c2bea59 --- /dev/null +++ b/modules/i18n/src/test/resources/locale/messages_de_DE.properties @@ -0,0 +1,4 @@ +# Generated 2016-07-22 17:52:35 +0530 +getLocale.test = German. This Module is related to internationalization +messageSayHi = German:Hello {name} + diff --git a/modules/i18n/src/test/resources/locale/messages_en_US.properties b/modules/i18n/src/test/resources/locale/messages_en_US.properties new file mode 100644 index 00000000..175a2895 --- /dev/null +++ b/modules/i18n/src/test/resources/locale/messages_en_US.properties @@ -0,0 +1,10 @@ +# --------------------------------------------------------------------------- +# Base values +# --------------------------------------------------------------------------- + +i18n.msg.helloworld=Hello World +i18n.msg.english=ENGLISH + +internationalization.msg.helloworld=Hello World +internationalization.msg.english=ENGLISH + diff --git a/modules/pom.xml b/modules/pom.xml index df61adec..cc051799 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -37,6 +37,7 @@ batch-tool web basic + i18n kafka diff --git a/templates/server/src/main/resources/archetype-resources/api/src/main/java/__packageInPathFormat__/general/service/api/rest/I18nRestService.java b/templates/server/src/main/resources/archetype-resources/api/src/main/java/__packageInPathFormat__/general/service/api/rest/I18nRestService.java new file mode 100644 index 00000000..5d209253 --- /dev/null +++ b/templates/server/src/main/resources/archetype-resources/api/src/main/java/__packageInPathFormat__/general/service/api/rest/I18nRestService.java @@ -0,0 +1,26 @@ +package ${package}.general.service.api.rest; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import com.devonfw.module.rest.common.api.RestService; + +/** + * The Internationlization REST service provides access to i18n module. + */ +@Path("/i18n/v1") +public interface I18nRestService extends RestService { + /** + * @param locale for locale + * @param filter + * @return JSON string + * @throws Exception + */ + @GET + @Path("/locales/{locale}/") + public String getResourcesForLocale(@PathParam("locale") String locale, @QueryParam("filter") String filter) + throws Exception; + +} diff --git a/templates/server/src/main/resources/archetype-resources/core/pom.xml b/templates/server/src/main/resources/archetype-resources/core/pom.xml index 55c4c00e..b455443b 100644 --- a/templates/server/src/main/resources/archetype-resources/core/pom.xml +++ b/templates/server/src/main/resources/archetype-resources/core/pom.xml @@ -35,6 +35,11 @@ com.devonfw.java.modules devon4j-web + + + com.devonfw.java.modules + devon4j-i18n + diff --git a/templates/server/src/main/resources/archetype-resources/core/src/main/java/__packageInPathFormat__/general/service/impl/rest/I18nRestServiceImpl.java b/templates/server/src/main/resources/archetype-resources/core/src/main/java/__packageInPathFormat__/general/service/impl/rest/I18nRestServiceImpl.java new file mode 100644 index 00000000..83469366 --- /dev/null +++ b/templates/server/src/main/resources/archetype-resources/core/src/main/java/__packageInPathFormat__/general/service/impl/rest/I18nRestServiceImpl.java @@ -0,0 +1,27 @@ +package ${package}.general.service.impl.rest; + +import javax.annotation.security.PermitAll; +import javax.inject.Named; +import javax.transaction.Transactional; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import ${package}.general.service.api.rest.I18nRestService; +import com.devonfw.module.i18n.locale.impl.I18nImpl; +import com.devonfw.module.i18n.locale.impl.LocaleNlsResourceImpl; + +/** + * Implementation of {@link I18nRestService}. + */ +@Named +@Transactional +public class I18nRestServiceImpl implements I18nRestService { + @Override + @PermitAll + public String getResourcesForLocale(@PathParam("locale") String locale, @QueryParam("filter") String filter) + throws Exception { + + return new I18nImpl(new LocaleNlsResourceImpl()).getResourceObject(locale, filter); + } + +}