diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 3705306..650cecd 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -4,13 +4,9 @@ on: push: branches: - main - - stage - - dev - snapshot/* - release/* - # pull_request: - # types: [opened, synchronize, reopened] - workflow_dispatch: +# workflow_dispatch: jobs: build: name: Build and analyze @@ -58,4 +54,4 @@ jobs: -Dsonar.exclusions=${{ vars.SONAR_EXCLUSIONS }} \ -Dsonar.java.binaries=${{ vars.SONAR_JAVA_BINARIES }} \ -Dsonar.coverage.exclusions=${{ vars.SONAR_COVERAGE_EXCLUSIONS }} \ - -Dsonar.java.source=${{ vars.SONAR_JAVA_SOURCE }} + -Dsonar.java.source=17 diff --git a/README.md b/README.md index 511af56..a3a15e9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This package provides a [MessageSource](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/MessageSource.html) for using translations from XLIFF files. The package support XLIFF versions 1.2, 2.0 and 2.1. [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=alaugks_spring-xliff-translation&metric=alert_status)](https://sonarcloud.io/summary/overall?id=alaugks_spring-xliff-translation) -[![Maven Central](https://img.shields.io/maven-central/v/io.github.alaugks/spring-messagesource-xliff.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/io.github.alaugks/spring-messagesource-xliff/1.3.0) +[![Maven Central](https://img.shields.io/maven-central/v/io.github.alaugks/spring-messagesource-xliff.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/io.github.alaugks/spring-messagesource-xliff/2.0.0) ## Dependency @@ -12,59 +12,59 @@ This package provides a [MessageSource](https://docs.spring.io/spring-framework/ io.github.alaugks spring-messagesource-xliff - 1.3.0 + 2.0.0 ``` ### Gradle ```text -implementation group: 'io.github.alaugks', name: 'spring-messagesource-xliff', version: '1.3.0' +implementation group: 'io.github.alaugks', name: 'spring-messagesource-xliff', version: '2.0.0' ``` -### Snapshots - -| Version | Description | -|:---------------|:------------------------------------------------------------------------------------------| -| 2.0.0-SNAPSHOT | [SNAPSHOT](https://github.com/alaugks/spring-messagesource-xliff/tree/snapshot/2.0.0) | | - ## MessageSource Configuration The class XliffTranslationMessageSource implements the [MessageSource](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/MessageSource.html) interface. -### XliffTranslationMessageSource +`builder(Locale defaultLocale, String locationPattern)` or
+`builder(Locale defaultLocale, List locationPatterns)` (***required***) +* Argument `Locale locale`: Defines the default locale. +* Argument `String locationPattern` | `List locationPatterns`: + * Defines the pattern used to select the XLIFF files. + * The package uses the [PathMatchingResourcePatternResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html) to select the XLIFF files. So you can use the supported patterns. + * Files with the extension `xliff` and `xlf` are filtered from the result list. -`setBasenamePattern(String basename)` or `setBasenamesPattern(Iterable basenames)` (***required***) +`defaultDomain(String defaultDomain)` -* Defines the pattern used to select the XLIFF files. -* The package uses the [PathMatchingResourcePatternResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html) to select the XLIFF files. So you can use the supported patterns. -* Files with the extension `xliff` and `xlf` are filtered from the result list. +* Defines the default domain. Default is `messages`. For more information, see [XlIFF Translations Files](#xliff-translation-files). -`setDefaultLocale(Locale locale)` (***required***) -* Defines the default language. -`setDefaultDomain(String defaultDomain)` -* Defines the default domain. Default is `messages`. For more information, see [XlIFF Translations Files](#xliff). +### Example + +* Default locale is `en`. +* The Xliff files are stored in `src/main/resources/translations`. ```java -import de.alaugks.spring.XliffTranslationMessageSource; +import io.github.alaugks.spring.messagesource.xliff.XliffResourceMessageSource; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; - import java.util.Locale; @Configuration public class MessageConfig { - + + @Bean public MessageSource messageSource() { - XliffTranslationMessageSource messageSource = new XliffTranslationMessageSource(); - messageSource.setDefaultLocale(Locale.forLanguageTag("en")); - messageSource.setBasenamePattern("translations/*"); - return messageSource; + return XliffResourceMessageSource + .builder( + Locale.forLanguageTag("en"), + "translations/*" + ) + .build(); } - + } ``` @@ -77,10 +77,12 @@ public class MessageConfig { * **XLIFF 1.2**: * If the attribute `resname` does not exist, the attribute `id` is used to determine the identifier. * Documentation identifier: [XLIFF 1.2](http://docs.oasis-open.org/xliff/v1.2/xliff-profile-html/xliff-profile-html-1.2.html#General_Identifiers) - * XLIFF 2.*: + * **XLIFF 2.***: * The attribute `id` is optional by standard in XLIFF 2.*. However, this package requires the `id` on a translation unit. * Documentation identifier: [XLIFF 2.0](https://docs.oasis-open.org/xliff/xliff-core/v2.0/csprd01/xliff-core-v2.0-csprd01.html#segment) and [XLIFF 2.1](https://docs.oasis-open.org/xliff/xliff-core/v2.1/os/xliff-core-v2.1-os.html#segment) -* For performance reasons, there is no validation of XLIFF files with an XMLSchema. If there is any corrupt XML in an XLIFF file, the SAX parser will throw a [Fatal Error]. +* All attributes in the `` tag are ignored. +* For performance reasons, there is no validation of XLIFF files with an XMLSchema. +* SAX parser errors are handled by an [ErrorHandler](src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandler.java). ### Structure of the Translation Filename @@ -133,14 +135,6 @@ Mixing XLIFF versions is possible. Here is an example using XLIFF 1.2 and XLIFF Postcode Postcode - - Your email {0} has been registered. - Your email {0} has been registered. - - - This is a default message. - This is a default message. - @@ -163,14 +157,6 @@ Mixing XLIFF versions is possible. Here is an example using XLIFF 1.2 and XLIFF Postcode Postleitzahl - - Your email {0} has been registered. - Ihre E-Mail {0} wurde registriert. - - - This is a default message. - Das ist ein Standardtext. - @@ -282,20 +268,6 @@ The behaviour of resolving the target value based on the code is equivalent to t Postleitzahl Postcode - - email-notice*
messages.email-notice - Your email {0} has been registered. - Your email {0} has been registered.** - Ihre E-Mail {0} wurde registriert. - Your email {0} has been registered. - - - default-message*
messages.default-message - This is a default message. - This is a default message.** - Das ist ein Standardtext. - This is a default message. - payment.headline Payment diff --git a/pom.xml b/pom.xml index fdf1045..f0fe232 100644 --- a/pom.xml +++ b/pom.xml @@ -1,15 +1,21 @@ - + 4.0.0 - io.github.alaugks + + io.github.alaugks + spring-messagesource-parent + 1.0.0 + + spring-messagesource-xliff - 1.3.0 + 2.0.0 jar ${project.groupId}:${project.artifactId} - Provides a MessageSource for translations from XLIFF files for Spring and Spring Boot. + Provides a Spring MessageSource for XLIFF files https://github.com/alaugks/spring-messagesource-xliff @@ -22,7 +28,7 @@ André Laugks - package@pb82.de + maven-central@pb82.de @@ -32,259 +38,12 @@ https://github.com/alaugks/spring-messagesource-xliff - - org.springframework.boot - spring-boot-starter-parent - 3.2.7 - - - - 11 - 5.9.3 - - - org.springframework - spring-core - - - org.springframework - spring-context - - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-core - - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test - - - org.junit.jupiter - junit-jupiter-engine - ${junit.version} - test - - - org.mockito - mockito-subclass - 5.4.0 - test - - - org.mockito - mockito-inline - 5.2.0 - test + io.github.alaugks + spring-messagesource-catalog + 0.2.0 - - - - - - - - local - - - central - file:~/.m2/ - - - - - - - - - - release - - 3.0.1 - 3.1.0 - 1.6.13 - - - - - ossrh - https://s01.oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - - - maven-release-plugin - ${version.maven-release-plugin} - - @{project.version} - - - - maven-gpg-plugin - ${version.maven-gpg-plugin} - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - ${version.nexus-staging-maven-plugin} - true - - ossrh - https://s01.oss.sonatype.org - true - - - - - - - maven-gpg-plugin - - - org.sonatype.plugins - nexus-staging-maven-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - attach-sources - - jar-no-fork - - - - - - - - - - - - - - - test-coverage - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.2.5 - - - --illegal-access=permit - - true - 2 - true - ${surefireArgLine} - - - - org.jacoco - jacoco-maven-plugin - 0.8.11 - - - default-prepare-agent - - prepare-agent - - - ${project.build.directory}/coverage-reports/jacoco.exec - surefireArgLine - - - - default-report - test - - report - - - ${project.build.directory}/coverage-reports/jacoco.exec - ${project.reporting.outputDirectory}/jacoco - - - - default-check - - check - - - - - BUNDLE - - - COMPLEXITY - COVEREDRATIO - 0.70 - - - - - - - - - - - - - diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGenerator.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGenerator.java deleted file mode 100644 index fdb4df9..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGenerator.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogUtilities; -import java.lang.reflect.Method; -import java.util.Locale; -import org.springframework.cache.interceptor.KeyGenerator; - -/** - * @deprecated - */ -@Deprecated(since = "2.0.0") -@SuppressWarnings({"java:S1133"}) -public final class XliffCacheableKeyGenerator implements KeyGenerator { - - public static final String GENERATOR_NAME = "messagesource.xliff.KEY_GENERATOR"; - - public static String createCode(Locale locale, String code) { - return CatalogUtilities.localeToKey(locale) + "|" + code; - } - - public Object generate(Object target, Method method, Object... params) { - return createCode( - (Locale) params[2], - params[0].toString() - ); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalog.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalog.java new file mode 100644 index 0000000..b2621fb --- /dev/null +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalog.java @@ -0,0 +1,182 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import io.github.alaugks.spring.messagesource.catalog.catalog.CatalogAbstract; +import io.github.alaugks.spring.messagesource.catalog.records.TransUnit; +import io.github.alaugks.spring.messagesource.catalog.records.TranslationFile; +import io.github.alaugks.spring.messagesource.xliff.exception.SaxErrorHandler; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceRuntimeException; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException.FatalError; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceVersionSupportException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +public final class XliffCatalog extends CatalogAbstract { + + private final List transUnits; + + private final List identifiers; + + private final List translationFiles; + + List supportedVersions = List.of( + new XliffVersion12(), + new XliffVersion2x() + ); + + public XliffCatalog( + List translationFiles, + List identifiers + ) { + this.translationFiles = translationFiles; + this.transUnits = new ArrayList<>(); + this.identifiers = identifiers == null ? List.of() : identifiers; + } + + @Override + public List getTransUnits() { + return this.transUnits; + } + + @Override + public void build() { + try { + this.parseXliffDocuments(this.translationFiles); + } + catch (ParserConfigurationException | IOException e) { + throw new FatalError(e); + } + } + + private void parseXliffDocuments(List xliffFiles) + throws ParserConfigurationException, IOException { + + for (TranslationFile xliffFile : xliffFiles) { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder documentBuilder = factory.newDocumentBuilder(); + documentBuilder.setErrorHandler(new SaxErrorHandler()); + Document document; + try { + document = documentBuilder.parse(xliffFile.inputStream()); + } + catch (SAXException e) { + throw new XliffMessageSourceRuntimeException(e); + } + + Element root = document.getDocumentElement(); + XliffDocument xliffDocument = new XliffDocument(root); + + if (!xliffDocument.isXliffDocument()) { + continue; + } + + var version = xliffDocument.getXliffVersion(); + + XliffVersionInterface xliffVersionObject = this.supportedVersions + .stream() + .filter(o -> o.support(xliffDocument.getXliffVersion())) + .findFirst() + .orElse(null); + + if (xliffVersionObject != null) { + xliffDocument.getTransUnits( + xliffVersionObject.getTransUnitName(), + this.resolveIdentifiers(this.identifiers, xliffVersionObject).list() + ).forEach((code, value) -> this.transUnits.add( + new TransUnit( + xliffFile.locale(), + code, + value, + xliffFile.domain() + ) + ) + ); + } + else { + throw new XliffMessageSourceVersionSupportException( + String.format("XLIFF version \"%s\" not supported.", version) + ); + } + } + } + + public XliffIdentifierInterface resolveIdentifiers( + List identifiers, + XliffVersionInterface xliffVersionObject + ) { + return identifiers + .stream() + .filter(u -> u.getClass() == xliffVersionObject.getDefaultIdentifier().getClass()) + .findFirst() + .orElse(xliffVersionObject.getDefaultIdentifier()); + } + + public static final class XliffVersion12 implements XliffVersionInterface { + + @Override + public boolean support(String version) { + return version.equals("1.2"); + } + + @Override + public String getTransUnitName() { + return "trans-unit"; + } + + @Override + public XliffIdentifierInterface getDefaultIdentifier() { + return new Xliff12Identifier(List.of()); + } + } + + public static final class XliffVersion2x implements XliffVersionInterface { + + @Override + public boolean support(String version) { + return List.of("2.0", "2.1").contains(version); + } + + @Override + public String getTransUnitName() { + return "segment"; + } + + @Override + public XliffIdentifierInterface getDefaultIdentifier() { + return new Xliff2xIdentifier(List.of()); + } + } + + public interface XliffVersionInterface { + + boolean support(String version); + + String getTransUnitName(); + + XliffIdentifierInterface getDefaultIdentifier(); + } + + record Xliff12Identifier(List list) implements XliffIdentifierInterface { + + } + + record Xliff2xIdentifier(List list) implements XliffIdentifierInterface { + + } + + public interface XliffIdentifierInterface { + + List list(); + } +} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffDocument.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffDocument.java new file mode 100644 index 0000000..a655b86 --- /dev/null +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffDocument.java @@ -0,0 +1,81 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public final class XliffDocument { + + private final Element root; + + private List transUnitIdentifiers; + + private NodeList nodeList; + + public XliffDocument(Element root) { + this.root = root; + } + + public XliffDocument(Document document) { + this.root = document.getDocumentElement(); + } + + public Map getTransUnits(String transUnitName, List transUnitIdentifiers) { + this.nodeList = this.root.getElementsByTagName(transUnitName); + this.transUnitIdentifiers = transUnitIdentifiers; + return this.getNodes(); + } + + public boolean isXliffDocument() { + // Simple test: Filter if root element + return root.getNodeName().equals("xliff"); + } + + public String getXliffVersion() { + return this.getAttributeValue( + root.getAttributes().getNamedItem("version") + ); + } + + private Map getNodes() { + Map transUnits = new HashMap<>(); + + for (int item = 0; item < nodeList.getLength(); item++) { + var node = (Element) nodeList.item(item); + Arrays.stream(this.transUnitIdentifiers.toArray()) + .map(value -> this.getAttributeValue( + node.getAttributes().getNamedItem(value.toString()) + )) + .filter(Objects::nonNull) + .findFirst().ifPresent(code -> transUnits.put( + code, + this.getCharacterDataFromElement( + node.getElementsByTagName("target").item(0).getFirstChild() + ) + )); + } + + return transUnits; + } + + private String getCharacterDataFromElement(Node child) { + if (child.getNextSibling() != null) { + return child.getNextSibling().getTextContent().trim(); + } + return child.getNodeValue().trim(); + } + + private String getAttributeValue(Node node) { + if (node != null) { + return node.getNodeValue(); + } + return null; + } +} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSource.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSource.java new file mode 100644 index 0000000..169c5a2 --- /dev/null +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSource.java @@ -0,0 +1,83 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import io.github.alaugks.spring.messagesource.catalog.CatalogMessageSourceBuilder; +import io.github.alaugks.spring.messagesource.catalog.catalog.Catalog; +import io.github.alaugks.spring.messagesource.catalog.catalog.CatalogInterface; +import io.github.alaugks.spring.messagesource.catalog.ressources.ResourcesLoader; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff12Identifier; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff2xIdentifier; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.XliffIdentifierInterface; + +public class XliffResourceMessageSource { + + private XliffResourceMessageSource() { + throw new IllegalStateException(XliffResourceMessageSource.class.toString()); + } + + public static Builder builder(Locale defaultLocale, String locationPattern) { + return new Builder(defaultLocale, List.of(locationPattern)); + } + + public static Builder builder(Locale defaultLocale, List locationPatterns) { + return new Builder(defaultLocale, locationPatterns); + } + + public static final class Builder { + + private final Locale defaultLocale; + + private final Set locationPatterns; + + private String defaultDomain = Catalog.DEFAULT_DOMAIN; + + private List fileExtensions = List.of("xlf", "xliff"); + + private List identifier = List.of( + new Xliff12Identifier(List.of("resname", "id")), + new Xliff2xIdentifier(List.of("id")) + ); + + public Builder(Locale defaultLocale, List locationPatterns) { + this.defaultLocale = defaultLocale; + this.locationPatterns = new HashSet<>(locationPatterns); + } + + public Builder defaultDomain(String defaultDomain) { + this.defaultDomain = defaultDomain; + return this; + } + + public Builder fileExtensions(List fileExtensions) { + this.fileExtensions = fileExtensions; + return this; + } + + public Builder identifier(List identifier) { + this.identifier = identifier; + return this; + } + + public CatalogMessageSourceBuilder build() { + ResourcesLoader resourcesLoader = new ResourcesLoader( + this.defaultLocale, + this.locationPatterns, + this.fileExtensions + ); + + CatalogInterface xliffCatalog = new XliffCatalog( + resourcesLoader.getTranslationFiles(), + this.identifier + ); + + return CatalogMessageSourceBuilder + .builder(xliffCatalog, this.defaultLocale) + .defaultDomain(this.defaultDomain) + .build(); + } + } +} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffTranslationMessageSource.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffTranslationMessageSource.java deleted file mode 100644 index 032520c..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/XliffTranslationMessageSource.java +++ /dev/null @@ -1,161 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogCache; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogWrapper; -import io.github.alaugks.spring.messagesource.xliff.catalog.xliff.XliffCatalogBuilder; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceRuntimeException; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoader; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; -import java.text.MessageFormat; -import java.util.List; -import java.util.Locale; -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.springframework.context.MessageSource; -import org.springframework.context.MessageSourceResolvable; -import org.springframework.context.NoSuchMessageException; -import org.springframework.context.support.DefaultMessageSourceResolvable; -import org.springframework.lang.Nullable; - -@SuppressWarnings("java:S1133") -public class XliffTranslationMessageSource implements MessageSource { - - private final CatalogWrapper catalogWrapper; - private final ResourcesLoaderInterface resourcesLoader = new ResourcesLoader(); - private final XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource() { - this(new ConcurrentMapCacheManager(CatalogCache.CACHE_NAME)); - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource(CacheManager cacheManager) { - this.catalogWrapper = new CatalogWrapper( - cacheManager, - this.resourcesLoader, - this.xliffCatalogBuilder, - new Catalog() - ); - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource setDefaultLocale(Locale locale) { - this.resourcesLoader.setDefaultLocale(locale); - return this; - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource setBasenamePattern(String basename) { - this.resourcesLoader.setBasenamePattern(basename); - return this; - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource setBasenamesPattern(Iterable basenames) { - this.resourcesLoader.setBasenamesPattern(basenames); - return this; - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource setDefaultDomain(String defaultDomain) { - this.catalogWrapper.setDefaultDomain(defaultDomain); - return this; - } - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public XliffTranslationMessageSource setTranslationUnitIdentifiersOrdering(List translationUnitIdentifiers) { - this.xliffCatalogBuilder.setTranslationUnitIdentifiersOrdering(translationUnitIdentifiers); - return this; - } - - @Nullable - public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) { - return this.format( - this.internalMessageWithDefaultMessage(code, defaultMessage, locale), - args, - locale - ); - } - - public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { - CatalogWrapper.Translation translation = this.internalMessage(code, locale); - if (translation.exists()) { - return this.format(translation.toString(), args, locale); - } - - throw new NoSuchMessageException(code, locale); - } - - public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { - String[] codes = resolvable.getCodes(); - if (codes != null) { - for (String code : codes) { - CatalogWrapper.Translation translation = internalMessage(code, locale); - if (translation.exists()) { - return this.format(translation.toString(), resolvable.getArguments(), locale); - } - } - } - if (resolvable instanceof DefaultMessageSourceResolvable) { - String defaultMessage = resolvable.getDefaultMessage(); - if (defaultMessage != null) { - return this.format(defaultMessage, resolvable.getArguments(), locale); - } - } - - throw new NoSuchMessageException(codes != null && codes.length > 0 ? codes[codes.length - 1] : "", locale); - } - - private CatalogWrapper.Translation internalMessage(String code, Locale locale) throws NoSuchMessageException { - return this.findInCatalog(locale, code); - } - - private String internalMessageWithDefaultMessage(String code, @Nullable String defaultMessage, Locale locale) { - CatalogWrapper.Translation translation = this.findInCatalog(locale, code); - if (translation.exists()) { - return translation.toString(); - } - return defaultMessage; - } - - private CatalogWrapper.Translation findInCatalog(Locale locale, String code) { - return this.catalogWrapper.get(locale, code); - } - - public void initCache() { - if (this.resourcesLoader.getDefaultLocale() == null || this.resourcesLoader.getDefaultLocale().toString().isEmpty()) { - throw new XliffMessageSourceRuntimeException("Default language is not set or empty."); - } - //this.catalogWrapper.initCache(); - } - - private String format(@Nullable String message, @Nullable Object[] args, Locale locale) { - if (message != null && args != null && args.length > 0) { - return new MessageFormat(message, locale).format(args); - } - return message; - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/Catalog.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/Catalog.java deleted file mode 100644 index b7910b8..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/Catalog.java +++ /dev/null @@ -1,63 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import java.util.HashMap; -import java.util.Locale; - -public final class Catalog implements CatalogInterface { - - private final HashMap> catalogMap; - - public Catalog() { - this.catalogMap = new HashMap<>(); - } - - @Override - public HashMap> getAll() { - return this.catalogMap; - } - - @Override - public String get(Locale locale, String code) { - if (this.localeExists(locale)) { - HashMap languageCatalog = this.getLocaleMap(locale); - if (languageCatalog.containsKey(code)) { - return languageCatalog.get(code); - } - } - return null; - } - - public boolean has(Locale locale, String code) { - return this.get(locale, code) != null; - } - - @Override - public void put(Locale locale, String domain, String code, String targetValue) { - if (!locale.toString().isEmpty()) { - String concatenatedCode = CatalogUtilities.concatCode(domain, code); - if (this.localeExists(locale)) { - HashMap transUnit = this.getLocaleMap(locale); - if (!transUnit.containsKey(concatenatedCode)) { - this.getLocaleMap(locale).put(concatenatedCode, targetValue); - } - return; - } - // Init catalog for locale - HashMap transUnit = new HashMap<>(); - transUnit.put(concatenatedCode, targetValue); - this.catalogMap.put(CatalogUtilities.localeToKey(locale), transUnit); - } - } - - public boolean localeExists(Locale locale) { - if (!locale.toString().isEmpty()) { - return this.catalogMap.containsKey(CatalogUtilities.localeToKey(locale)); - } - return false; - } - - - private HashMap getLocaleMap(Locale locale) { - return this.catalogMap.get(CatalogUtilities.localeToKey(locale)); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogBuilderInterface.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogBuilderInterface.java deleted file mode 100644 index ebb642c..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogBuilderInterface.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; - -public interface CatalogBuilderInterface { - CatalogInterface createCatalog(ResourcesLoaderInterface resourceLoader, CatalogInterface catalog); -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCache.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCache.java deleted file mode 100644 index 73c3398..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCache.java +++ /dev/null @@ -1,102 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import io.github.alaugks.spring.messagesource.xliff.XliffCacheableKeyGenerator; -import io.github.alaugks.spring.messagesource.xliff.XliffTranslationMessageSource; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceCacheNotExistsException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Locale; -import java.util.Objects; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; - -@SuppressWarnings({"java:S5738", "java:S1874", "java:S1133"}) -public final class CatalogCache implements CatalogInterface { - - /** - * @deprecated - */ - @Deprecated(since = "2.0.0") - public static final String CACHE_NAME = "messagesource.xliff.catalog.CACHE"; - - private static final Logger logger = LogManager.getLogger(XliffTranslationMessageSource.class.toString()); - private Cache cache; - - CatalogCache(CacheManager cacheManager) { - this.loadCache(cacheManager); - } - - private void loadCache(CacheManager cacheManager) { - if (cacheManager != null) { - Collection caches = cacheManager.getCacheNames(); - if (caches.contains(CACHE_NAME)) { - this.cache = cacheManager.getCache(CACHE_NAME); - return; - } - throw new XliffMessageSourceCacheNotExistsException( - String.format("Cache with name [%s] not available.", CACHE_NAME) - ); - } - throw new XliffMessageSourceCacheNotExistsException( - "org.springframework.cache.CacheManager not available." - ); - } - - @Override - public HashMap> getAll() { - return new HashMap<>(); - } - - @Override - public boolean has(Locale locale, String code) { - return this.get(locale, code) != null; - } - - @Override - public String get(Locale locale, String code) { - if (!locale.toString().isEmpty()) { - return this.getValue( - this.cache.get( - XliffCacheableKeyGenerator.createCode(locale, code) - ) - ); - } - return null; - } - - @Override - public void put(Locale locale, String domain, String code, String targetValue) { - this.put(locale, CatalogUtilities.concatCode(domain, code), targetValue); - } - - void put(Locale locale, String code, String targetValue) { - if (!locale.toString().isEmpty()) { - this.cache.put( - XliffCacheableKeyGenerator.createCode(locale, code), - targetValue - ); - } - } - - private String getValue(Cache.ValueWrapper valueWrapper) { - if (valueWrapper != null) { - return Objects.requireNonNull(valueWrapper.get()).toString(); - } - return null; - } - - void initCache(CatalogInterface catalog) { - if (catalog != null) { - logger.debug("Init xliff catalog cache"); - catalog.getAll().forEach((langCode, domain) -> domain.forEach((code, targetValue) -> - this.put( - Locale.forLanguageTag(langCode.replace("_", "-")), - code, - targetValue - ) - )); - } - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogInterface.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogInterface.java deleted file mode 100644 index dd70a72..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogInterface.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import java.util.HashMap; -import java.util.Locale; - -public interface CatalogInterface { - // HashMap<"language+region", HashMap<"code", "targetValue">> - HashMap> getAll(); - - String get(Locale locale, String code); - - void put(Locale locale, String domain, String code, String targetValue); - - boolean has(Locale locale, String code); -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilities.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilities.java deleted file mode 100644 index 3ddde41..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilities.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import java.util.Locale; - -public class CatalogUtilities { - - private CatalogUtilities() { - throw new IllegalStateException("CatalogUtilities class"); - } - - public static String localeToKey(Locale locale) { - return buildLocale(locale).toString().trim().toLowerCase().replace("_", "-"); - } - - public static String concatCode(String domain, String code) { - return domain + "." + code; - } - - public static Locale buildLocale(Locale locale) { - Locale.Builder localeBuilder = new Locale.Builder(); - localeBuilder.setLanguage(locale.getLanguage()); - if (!locale.getCountry().isEmpty()) { - localeBuilder.setRegion(locale.getCountry()); - } - return localeBuilder.build(); - } - - public static Locale buildLocale(String language, String region) { - Locale.Builder localeBuilder = new Locale.Builder(); - if (language != null && !language.isEmpty()) { - localeBuilder.setLanguage(language); - // Set region only is present - if (region != null && !region.isEmpty()) { - localeBuilder.setRegion(region); - } - } - return localeBuilder.build(); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapper.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapper.java deleted file mode 100644 index 6c98824..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapper.java +++ /dev/null @@ -1,177 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import io.github.alaugks.spring.messagesource.xliff.XliffTranslationMessageSource; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.cache.CacheManager; - -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Objects; - -public class CatalogWrapper { - private static final Logger logger = LogManager.getLogger(XliffTranslationMessageSource.class.toString()); - private final CatalogCache catalogCache; - private final CatalogInterface catalog; - private final CatalogBuilderInterface catalogBuilder; - private final ResourcesLoaderInterface resourcesLoader; - private String defaultDomain = "messages"; - - public CatalogWrapper(CacheManager cacheManager, - ResourcesLoaderInterface resourcesLoader, - CatalogBuilderInterface catalogBuilder, - CatalogInterface catalog - ) { - this.catalog = catalog; - this.resourcesLoader = resourcesLoader; - this.catalogBuilder = catalogBuilder; - this.catalogCache = new CatalogCache(cacheManager); - } - - private static Locale buildLocaleWithLanguageRegion(Locale locale) { - return CatalogUtilities.buildLocale(locale); - } - - private static Locale buildLocaleWithLanguage(Locale locale) { - Locale.Builder localeBuilder = new Locale.Builder(); - localeBuilder.setLanguage(locale.getLanguage()); - return localeBuilder.build(); - } - - public Translation get(Locale locale, String code) { - // Check cache - String targetValue = this.getTranslationItemFromCatalog( - this.catalogCache, - locale, - code - ); - - // Exists in cache? - if (targetValue != null) { - return new Translation(code, targetValue); - } - - // Check catalog - CatalogInterface loadedCatalog = this.loadCatalog(); - targetValue = this.getTranslationItemFromCatalog( - loadedCatalog, - locale, - code - ); - - // If exists then init cache, because it was not in the cache. Cache empty? - if (targetValue != null) { - logger.debug("Re-init xliff catalog cache"); - this.initCache(loadedCatalog); - } - - // If not exists then is the targetValue is the code. - // - // Non-existing code is added to the cache to fetch the non-existing code from - // the cache so as not to continue looking in the messagesource files. - String targetValueCode = null; - if (targetValue == null) { - targetValueCode = code; - this.put(locale, code, targetValueCode); - } - - return new Translation(code, (targetValue != null ? targetValue : targetValueCode)); - } - - void put(Locale locale, String code, String targetValue) { - this.catalogCache.put( - locale, - code, - targetValue - ); - } - - void put(Locale locale, String domain, String code, String targetValue) { - this.catalogCache.put( - locale, - CatalogUtilities.concatCode(domain, code), - targetValue - ); - } - - public void setDefaultDomain(String defaultDomain) { - this.defaultDomain = defaultDomain; - } - - public void initCache(CatalogInterface catalog) { - // Without cache do not get load catalog - this.catalogCache.initCache(catalog); - } - - public void initCache() { - // Without cache do not get load catalog - this.catalogCache.initCache(this.loadCatalog()); - } - - private CatalogInterface loadCatalog() { - return this.catalogBuilder.createCatalog(this.resourcesLoader, this.catalog); - } - - private String findTranslationItemInCatalog(CatalogInterface catalog, Locale locale, String code) { - String targetValue; - LinkedHashMap locales = new LinkedHashMap<>(); - // Follow the order - locales.put(0, locale); // First - locales.put(1, this.resourcesLoader.getDefaultLocale()); // Second - for (int i = 0; i < locales.size(); i++) { - if(locales.containsKey(i) && locales.get(i) != null) { - // Try with locale+region - targetValue = catalog.get( - buildLocaleWithLanguageRegion(locales.get(i)), - code - ); - - // Try with locale - if (targetValue == null) { - targetValue = catalog.get( - buildLocaleWithLanguage(locales.get(i)), - code - ); - } - - if (targetValue != null) { - return targetValue; - } - } - } - return null; - } - - private String getTranslationItemFromCatalog(CatalogInterface catalog, Locale locale, String code) { - // Find "code" - String targetValue = this.findTranslationItemInCatalog(catalog, locale, code); - if (targetValue == null) { - // Find "domain.code" - targetValue = this.findTranslationItemInCatalog( - catalog, - locale, - CatalogUtilities.concatCode(this.defaultDomain, code) - ); - } - return targetValue; - } - - public static class Translation { - String code; - String targetValue; - - public Translation(String code, String targetValue) { - this.code = code; - this.targetValue = targetValue; - } - - public boolean exists() { - return !Objects.equals(this.code, this.targetValue); - } - - public String toString() { - return targetValue; - } - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12.java deleted file mode 100644 index b27bb1b..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -final class Xliff12 extends XliffAbstract implements XliffInterface { - private List translationUnitIdentifiers = new ArrayList<>(Arrays.asList("resname", "id")); - - @Override - public boolean support(String version) { - return version.equals("1.2"); - } - - @Override - public void setTranslationUnitIdentifiersOrdering(List translationUnitIdentifiers) { - this.translationUnitIdentifiers = translationUnitIdentifiers; - } - - @Override - public void read(CatalogInterface catalog, Document document, String domain, Locale locale) { - NodeList translationUnits = XliffParserUtility.getTranslationUnits(document, "trans-unit"); - this.readItems(catalog, domain, locale, translationUnits, this.translationUnitIdentifiers); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff2.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff2.java deleted file mode 100644 index e5e912d..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff2.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -final class Xliff2 extends XliffAbstract implements XliffInterface { - private List translationUnitIdentifiers = new ArrayList<>(List.of("id")); - - @Override - public boolean support(String version) { - return List.of("2.0", "2.1").contains(version); - } - - @Override - public void setTranslationUnitIdentifiersOrdering(List translationUnitIdentifiers) { - this.translationUnitIdentifiers = translationUnitIdentifiers; - } - - @Override - public void read(CatalogInterface catalog, Document document, String domain, Locale locale) { - NodeList translationUnits = XliffParserUtility.getTranslationUnits(document, "segment"); - this.readItems(catalog, domain, locale, translationUnits, this.translationUnitIdentifiers); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffAbstract.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffAbstract.java deleted file mode 100644 index 47d737f..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffAbstract.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.util.List; -import java.util.Locale; - -// https://docs.oasis-open.org/xliff/v1.2/xliff-profile-html/xliff-profile-html-1.2.html#General_Identifiers -// https://docs.oasis-open.org/xliff/xliff-core/v2.0/csprd01/xliff-core-v2.0-csprd01.html#segment -// https://docs.oasis-open.org/xliff/xliff-core/v2.1/os/xliff-core-v2.1-os.html#segment -abstract class XliffAbstract { - protected void readItems( - CatalogInterface catalog, - String domain, - Locale locale, - NodeList translationNodes, - List translationUnitIdentifiers - ) { - for (int item = 0; item < translationNodes.getLength(); item++) { - Node translationNode = translationNodes.item(item); - - /* Translation Node */ - Element translationNodeElement = (Element) translationNode; - /* */ - String targetValue = XliffParserUtility.getTargetValue(translationNodeElement); - /* code */ - String code = XliffParserUtility.getCode(translationNodeElement, translationUnitIdentifiers); - - /* Add catalog */ - catalog.put(locale, domain, code, targetValue); - } - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilder.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilder.java deleted file mode 100644 index 492b7af..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilder.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogBuilderInterface; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceRuntimeException; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceVersionSupportException; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoader; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class XliffCatalogBuilder implements CatalogBuilderInterface { - - private CatalogInterface catalog; - private List translationUnitIdentifiers; - - @Override - public CatalogInterface createCatalog(ResourcesLoaderInterface resourceLoader, CatalogInterface catalog) { - try { - this.catalog = catalog; - this.readFile(resourceLoader.getResourcesInputStream()); - return this.catalog; - } catch (ParserConfigurationException | IOException e) { - throw new XliffMessageSourceRuntimeException(e); - } - } - - public void setTranslationUnitIdentifiersOrdering(List translationUnitIdentifiers) { - this.translationUnitIdentifiers = translationUnitIdentifiers; - } - - private void readFile(ArrayList translationFiles) throws ParserConfigurationException, IOException { - - XliffReader xliffReader = new XliffReader(); - - for (ResourcesLoader.Dto translationFile : translationFiles) { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document; - try { - document = builder.parse(translationFile.getInputStream()); - } catch (SAXException e) { - throw new XliffMessageSourceRuntimeException(e); - } - - Element root = document.getDocumentElement(); - - // Simple test: Filter if root element not - if (!root.getNodeName().equals("xliff")) { - continue; - } - - String version = XliffParserUtility.getAttributeValue( - root.getAttributes().getNamedItem("version") - ); - - XliffInterface xliffInterface = xliffReader.getReader(version); - if (xliffInterface != null) { - if (this.translationUnitIdentifiers != null) { - xliffInterface.setTranslationUnitIdentifiersOrdering(this.translationUnitIdentifiers); - } - xliffInterface.read(this.catalog, document, translationFile.getDomain(), translationFile.getLocale()); - } else { - throw new XliffMessageSourceVersionSupportException(String.format("XLIFF version \"%s\" not supported.", version)); - } - } - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffInterface.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffInterface.java deleted file mode 100644 index f714c7e..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffInterface.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.w3c.dom.Document; - -import java.util.List; -import java.util.Locale; - -public interface XliffInterface { - boolean support(String version); - - void setTranslationUnitIdentifiersOrdering(List translationUnitIdentifiers); - - void read(CatalogInterface catalog, Document document, String domain, Locale locale); -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtility.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtility.java deleted file mode 100644 index c6b8d55..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtility.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import org.w3c.dom.CharacterData; -import org.w3c.dom.*; - -import java.util.List; - -final class XliffParserUtility { - - private XliffParserUtility() { - throw new IllegalStateException("XliffParserUtility class"); - } - - static Node getFirstChild(NodeList nodeList) { - return nodeList.item(0).getFirstChild(); - } - - public static String getAttributeValue(Node node) { - if (node != null) { - return node.getNodeValue(); - } - return null; - } - - private static String getCharacterDataFromElement(Node child) { - if (child instanceof CharacterData) { - if (child.getNextSibling() != null) { - return child.getNextSibling().getTextContent().trim(); - } - return ((CharacterData) child).getData().trim(); - } - return null; - } - - public static String getAttributeValue(Node translationNode, String attributeName) { - return getAttributeValue( - translationNode.getAttributes().getNamedItem(attributeName) - ); - } - - public static String getElementValue(Element translationNodeElement, String elementName) { - return getCharacterDataFromElement( - getFirstChild( - translationNodeElement.getElementsByTagName(elementName) - ) - ); - } - - public static String getTargetValue(Element translationNodeElement) { - return getElementValue(translationNodeElement, "target"); - } - - public static NodeList getTranslationUnits(Document document, String nodeName) { - return document.getElementsByTagName(nodeName); - } - - public static String getCode( - Element translationUnit, - List translationUnitIdentifiers - ) { - if (translationUnitIdentifiers != null) { - for (String name : translationUnitIdentifiers) { - String value = getAttributeValue(translationUnit, name); - if (value != null) { - return value; - } - } - } - - return null; - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReader.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReader.java deleted file mode 100644 index 7c7741d..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReader.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import java.util.Set; - -final class XliffReader { - Set supportedVersions; - - public XliffReader() { - this.supportedVersions = Set.of( - new Xliff12(), - new Xliff2() - ); - } - - public XliffInterface getReader(String version) { - for (XliffInterface xliffClass : this.supportedVersions) { - if (xliffClass.support(version)) { - return xliffClass; - } - } - return null; - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandler.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandler.java new file mode 100644 index 0000000..19e2509 --- /dev/null +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandler.java @@ -0,0 +1,25 @@ +package io.github.alaugks.spring.messagesource.xliff.exception; + +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException.Error; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException.FatalError; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException.Warning; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXParseException; + +public class SaxErrorHandler implements ErrorHandler { + + @Override + public void warning(SAXParseException exception) { + throw new Warning(exception); + } + + @Override + public void error(SAXParseException exception) { + throw new Error(exception); + } + + @Override + public void fatalError(SAXParseException exception) { + throw new FatalError(exception); + } +} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceCacheNotExistsException.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceCacheNotExistsException.java deleted file mode 100644 index ea205bb..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceCacheNotExistsException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.exception; - -public class XliffMessageSourceCacheNotExistsException extends RuntimeException { - public XliffMessageSourceCacheNotExistsException(String message) { - super(message); - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceRuntimeException.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceRuntimeException.java index 3f4ea5b..e449fd9 100644 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceRuntimeException.java +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceRuntimeException.java @@ -1,11 +1,8 @@ package io.github.alaugks.spring.messagesource.xliff.exception; public class XliffMessageSourceRuntimeException extends RuntimeException { - public XliffMessageSourceRuntimeException(Throwable cause) { - super(cause); - } - public XliffMessageSourceRuntimeException(String message) { - super(message); - } + public XliffMessageSourceRuntimeException(Throwable cause) { + super(cause); + } } diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceSAXParseException.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceSAXParseException.java new file mode 100644 index 0000000..2e153b1 --- /dev/null +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceSAXParseException.java @@ -0,0 +1,29 @@ +package io.github.alaugks.spring.messagesource.xliff.exception; + +public class XliffMessageSourceSAXParseException extends RuntimeException { + + public XliffMessageSourceSAXParseException(Throwable cause) { + super(cause); + } + + public static class Warning extends XliffMessageSourceSAXParseException { + + public Warning(Throwable cause) { + super(cause); + } + } + + public static class Error extends XliffMessageSourceSAXParseException { + + public Error(Throwable cause) { + super(cause); + } + } + + public static class FatalError extends XliffMessageSourceSAXParseException { + + public FatalError(Throwable cause) { + super(cause); + } + } +} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceVersionSupportException.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceVersionSupportException.java index d9d01b8..26a0f1a 100644 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceVersionSupportException.java +++ b/src/main/java/io/github/alaugks/spring/messagesource/xliff/exception/XliffMessageSourceVersionSupportException.java @@ -1,7 +1,8 @@ package io.github.alaugks.spring.messagesource.xliff.exception; public class XliffMessageSourceVersionSupportException extends RuntimeException { - public XliffMessageSourceVersionSupportException(String message) { - super(message); - } + + public XliffMessageSourceVersionSupportException(String message) { + super(message); + } } diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParser.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParser.java deleted file mode 100644 index b77d00b..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParser.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.ressources; - -import io.github.alaugks.spring.messagesource.xliff.XliffTranslationMessageSource; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogUtilities; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.IllformedLocaleException; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -final class ResourcesFileNameParser { - private static final Logger logger = LogManager.getLogger(XliffTranslationMessageSource.class.toString()); - private final String filename; - - public ResourcesFileNameParser(String filename) { - this.filename = filename; - } - - public Dto parse() { - String regexp = "^(?[a-z0-9]+)(?:([_-](?[a-z]+))(?:[_-](?[a-z]+))?)?"; - Pattern pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(this.filename); - - if (matcher.find()) { - String domain = this.getGroup(matcher, "domain"); - String language = this.getGroup(matcher, "language"); - String region = this.getGroup(matcher, "region"); - return new Dto( - domain, - language, - region - ); - } - return null; - } - - public static class Dto { - private final String domain; - private final String language; - private final String region; - - public Dto(String domain, String lang, String country) { - this.domain = domain; - this.language = lang; - this.region = country; - } - - public String getDomain() { - return domain; - } - - public String getLanguage() { - return language; - } - - public String getRegion() { - return region; - } - - public boolean hasLocale() { - return getLocale() != null && !getLocale().toString().isEmpty(); - } - - public Locale getLocale() { - try { - return CatalogUtilities.buildLocale(this.language, this.region); - } catch (IllformedLocaleException e) { - logger.debug(e.getMessage()); - return null; - } - } - } - - private String getGroup(Matcher matcher, String groupName) { - try { - return matcher.group(groupName); - } catch (IllegalArgumentException | IllegalStateException e) { - return null; - } - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoader.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoader.java deleted file mode 100644 index 3969341..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoader.java +++ /dev/null @@ -1,127 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.ressources; - -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceRuntimeException; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.*; - -public final class ResourcesLoader implements ResourcesLoaderInterface { - - private final Set basenameSet = new LinkedHashSet<>(); - private Locale defaultLocale; - private final List fileExtensions = List.of("xlf", "xliff"); - - @Override - public ResourcesLoader setBasenamePattern(String basename) { - this.setBasenamesPattern(List.of(basename)); - return this; - } - - @Override - public ResourcesLoader setBasenamesPattern(Iterable basenames) { - this.basenameSet.clear(); - this.addBasenames(basenames); - return this; - } - - @Override - public ResourcesLoader setDefaultLocale(Locale locale) { - this.defaultLocale = locale; - return this; - } - - @Override - public Locale getDefaultLocale() { - return defaultLocale; - } - - @Override - public ArrayList getResourcesInputStream() throws IOException { - if (this.defaultLocale == null || this.defaultLocale.toString().isEmpty()) { - throw new XliffMessageSourceRuntimeException("Default language is not set or empty."); - } - - ArrayList translationFiles = new ArrayList<>(); - PathMatchingResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver(); - for (String basename : getBasenameSet()) { - Resource[] resources = resourceLoader.getResources(basename); - for (Resource resource : resources) { - if (this.isFileExtensionSupported(resource)) { - Dto dto = this.parseFileName(resource); - if(dto != null) { - translationFiles.add(dto); - } - } - } - } - - return translationFiles; - } - - private Dto parseFileName(Resource resource) throws IOException { - ResourcesFileNameParser.Dto dto = new ResourcesFileNameParser(resource.getFilename()).parse(); - if (dto != null) { - return new Dto( - dto.getDomain(), - dto.hasLocale() - ? dto.getLocale() - : this.defaultLocale, - resource.getInputStream() - ); - } - return null; - } - - private boolean isFileExtensionSupported(Resource resource) { - String fileExtension = this.getFileExtension(resource.getFilename()); - return fileExtension != null && this.fileExtensions.contains(fileExtension.toLowerCase()); - } - - public static class Dto { - private final String domain; - private final Locale locale; - private final InputStream inputStream; - - public Dto(String domain, Locale locale, InputStream inputStream) { - this.domain = domain; - this.locale = locale; - this.inputStream = inputStream; - } - - public String getDomain() { - return domain; - } - - public Locale getLocale() { - return locale; - } - - public InputStream getInputStream() { - return inputStream; - } - } - - private String getFileExtension(String filename) { - return Optional.ofNullable(filename) - .filter(f -> f.contains(".")) - .map(f -> f.substring(filename.lastIndexOf(".") + 1)).orElse(null); - } - - private void addBasenames(Iterable basenames) { - if (!ObjectUtils.isEmpty(basenames)) { - for (String basename : basenames) { - Assert.hasText(basename, "Basename must not be empty"); - this.basenameSet.add(basename.trim()); - } - } - } - - private Set getBasenameSet() { - return this.basenameSet; - } -} diff --git a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderInterface.java b/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderInterface.java deleted file mode 100644 index fd6a32b..0000000 --- a/src/main/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderInterface.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.ressources; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Locale; - -public interface ResourcesLoaderInterface { - ArrayList getResourcesInputStream() throws IOException; - - ResourcesLoader setDefaultLocale(Locale locale); - - Locale getDefaultLocale(); - - ResourcesLoader setBasenamePattern(String basename); - - ResourcesLoader setBasenamesPattern(Iterable basenames); -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/TestUtilities.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/TestUtilities.java deleted file mode 100644 index b81ff68..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/TestUtilities.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogCache; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogWrapper; -import io.github.alaugks.spring.messagesource.xliff.catalog.xliff.XliffCatalogBuilder; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoader; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.Locale; - -public class TestUtilities { - public static CatalogInterface getTestCatalog() { - ResourcesLoader translationResourcesLoader = new ResourcesLoader(); - translationResourcesLoader.setBasenamePattern("translations/*"); - translationResourcesLoader.setDefaultLocale(Locale.forLanguageTag("en")); - return new XliffCatalogBuilder().createCatalog(translationResourcesLoader, new Catalog()); - } - - public static CatalogWrapper getCacheWrapperWithCachedTestCatalog() { - CatalogWrapper catalogWrapper = new CatalogWrapper( - getMockedCacheManager(), - getResourcesLoader(), new XliffCatalogBuilder(), TestUtilities.getTestCatalog() - ); - catalogWrapper.initCache(); - return catalogWrapper; - } - - public static CacheManager getMockedCacheManager() { - return getMockedCacheManager(CatalogCache.CACHE_NAME); - } - - public static CacheManager getMockedCacheManager(String cacheName) { - ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(); - cacheManager.setCacheNames(List.of(cacheName)); - return cacheManager; - } - - public static ResourcesLoaderInterface getResourcesLoader() { - ResourcesLoader resourcesLoader = new ResourcesLoader(); - resourcesLoader.setBasenamePattern( - "translations/*" - ); - resourcesLoader.setDefaultLocale(Locale.forLanguageTag("en")); - return resourcesLoader; - } - - public static Document getDocument(InputStream inputStream) throws ParserConfigurationException, SAXException, IOException { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - return builder.parse(inputStream); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGeneratorTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGeneratorTest.java deleted file mode 100644 index 7cf024e..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCacheableKeyGeneratorTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.lang.reflect.Method; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class XliffCacheableKeyGeneratorTest { - - private Object target; - private Method method; - - @BeforeEach - void beforeEach() { - this.target = new Object(); - this.method = getClass().getMethods()[0]; - } - - @Test - void test_createKey_code_en() { - XliffCacheableKeyGenerator generator = new XliffCacheableKeyGenerator(); - - Locale locale = Locale.forLanguageTag("en"); - String code = "my-code"; - Object[] params = {code, "args", locale}; - - assertEquals("en|my-code", XliffCacheableKeyGenerator.createCode(locale, code)); - assertEquals("en|my-code", generator.generate(this.target, this.method, params)); - } - - @Test - void test_createKey_code_enUk() { - XliffCacheableKeyGenerator generator = new XliffCacheableKeyGenerator(); - - Locale locale = Locale.forLanguageTag("en-GB"); - String code = "my-code"; - Object[] params = {code, "args", locale}; - - assertEquals("en-gb|my-code", XliffCacheableKeyGenerator.createCode(locale, code)); - assertEquals("en-gb|my-code", generator.generate(this.target, this.method, params)); - } - - @Test - void test_Constants() { - assertEquals("messagesource.xliff.KEY_GENERATOR", XliffCacheableKeyGenerator.GENERATOR_NAME); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalogTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalogTest.java new file mode 100644 index 0000000..37c2e35 --- /dev/null +++ b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffCatalogTest.java @@ -0,0 +1,139 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Stream; + +import io.github.alaugks.spring.messagesource.catalog.records.TransUnit; +import io.github.alaugks.spring.messagesource.catalog.ressources.ResourcesLoader; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff12Identifier; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff2xIdentifier; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceSAXParseException.FatalError; +import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceVersionSupportException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class XliffCatalogTest { + + @Test + void test_getTransUnits() { + + var ressourceLoader = new ResourcesLoader( + Locale.forLanguageTag("en"), + new HashSet<>(List.of("translations/messages.xliff", "translations/messages_de.xliff")), + List.of("xlf", "xliff") + ); + + var catalog = new XliffCatalog( + ressourceLoader.getTranslationFiles(), + List.of( + new Xliff12Identifier(List.of("resname", "id")), + new Xliff2xIdentifier(List.of("id")) + ) + ); + catalog.build(); + var transUnits = catalog.getTransUnits(); + + assertEquals("Postcode", this.findInTransUnits(transUnits, "en", "postcode")); + assertEquals("Postleitzahl", this.findInTransUnits(transUnits, "de", "postcode")); + } + + @Test + void test_parseError() { + var xliffCatalogBuilder = this.getXliffCatalogBuilder( + new HashSet<>(List.of("fixtures/parse_error.xliff")), + Locale.forLanguageTag("en") + ); + + assertThrows( + XliffMessageSourceSAXParseException.class, xliffCatalogBuilder::build + ); + + assertThrows( + FatalError.class, xliffCatalogBuilder::build + ); + } + + @Test + void test_noXliffDocument() { + + var ressourceLoader = new ResourcesLoader( + Locale.forLanguageTag("en"), + new HashSet<>(List.of("fixtures/no-xliff.xml")), + List.of("xml") + ); + + var transUnits = new XliffCatalog( + ressourceLoader.getTranslationFiles(), + null + ).getTransUnits(); + + assertEquals(List.of(), transUnits); + } + + @Test + void test_versionNotSupported() { + var xliffCatalogBuilder = this.getXliffCatalogBuilder( + new HashSet<>(List.of("fixtures/xliff10.xliff")), + Locale.forLanguageTag("en") + ); + + XliffMessageSourceVersionSupportException exception = assertThrows( + XliffMessageSourceVersionSupportException.class, xliffCatalogBuilder::build + ); + assertEquals("XLIFF version \"1.0\" not supported.", exception.getMessage()); + } + + + @ParameterizedTest + @MethodSource("dataProvider_loadVersions") + void test_versionSupported(String ressourcePath, String domain, String expected) { + var catalog = this.getXliffCatalogBuilder( + new HashSet<>(List.of(ressourcePath)), + Locale.forLanguageTag("en") + ); + catalog.build(); + + assertEquals( + expected, + this.findInTransUnits(catalog.getTransUnits(), "en", "code-1") + ); + } + + private static Stream dataProvider_loadVersions() { + return Stream.of( + Arguments.of("fixtures/xliff12.xliff", "xliff12", "Postcode (Xliff Version 1.2)"), + Arguments.of("fixtures/xliff20.xliff", "xliff20", "Postcode (Xliff Version 2.0)"), + Arguments.of("fixtures/xliff21.xliff", "xliff21", "Postcode (Xliff Version 2.1)") + ); + } + + private XliffCatalog getXliffCatalogBuilder(Set files, Locale locale) { + + var ressourceLoader = new ResourcesLoader(locale, files, List.of("xlf", "xliff")); + + return new XliffCatalog( + ressourceLoader.getTranslationFiles(), + List.of( + new Xliff12Identifier(List.of("resname", "id")), + new Xliff2xIdentifier(List.of("id")) + ) + ); + } + + private String findInTransUnits(List transUnits, String locale, String code) { + return transUnits + .stream() + .filter(t -> t.locale().toString().equals(locale) && t.code().equals(code)) + .findFirst() + .get().value(); + } +} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffDocumentTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffDocumentTest.java new file mode 100644 index 0000000..96e4f30 --- /dev/null +++ b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffDocumentTest.java @@ -0,0 +1,63 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class XliffDocumentTest { + + @Test + void test_getXliffVersion() throws ParserConfigurationException, IOException, SAXException { + var xliffDocument = new XliffDocument(this.getDocument("fixtures/xliff21.xliff")); + + assertTrue(xliffDocument.isXliffDocument()); + assertEquals("2.1", xliffDocument.getXliffVersion()); + } + + @Test + void test_fail() throws ParserConfigurationException, IOException, SAXException { + var xliffDocument = new XliffDocument(this.getDocument("fixtures/xliff-fail.xliff")); + + assertFalse(xliffDocument.isXliffDocument()); + assertNull(xliffDocument.getXliffVersion()); + } + + @Test + void test_getElementValue_getCharacterDataFromElement_TextNode() + throws ParserConfigurationException, IOException, SAXException { + + var xliffDocument = new XliffDocument(this.getDocument("fixtures/xliff-value-test.xliff")); + Map transUnits = new HashMap<>(xliffDocument.getTransUnits("segment", List.of("id"))); + + assertEquals("value", transUnits.get("element")); + assertEquals("value", transUnits.get("element-newline")); + assertEquals("value", transUnits.get("element-with-cdata")); + assertEquals("value", transUnits.get("element-with-cdata-newline")); + } + + private Document getDocument(InputStream inputStream) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + return builder.parse(inputStream); + } + + private Document getDocument(String path) throws ParserConfigurationException, SAXException, IOException { + return this.getDocument(getClass().getClassLoader().getResourceAsStream(path)); + } +} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverAbstract.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverAbstract.java deleted file mode 100644 index ac05410..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverAbstract.java +++ /dev/null @@ -1,153 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import org.junit.jupiter.api.Test; -import org.springframework.context.NoSuchMessageException; -import org.springframework.context.support.DefaultMessageSourceResolvable; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -abstract class XliffMatchingResourcePatternResolverAbstract { - - protected static XliffTranslationMessageSource messageSource; - - @Test - void test_message_withDefaultMessage_messageExists() { - String message = messageSource.getMessage( - "hello_language", - null, - "My default message", - Locale.forLanguageTag("en") - ); - - assertEquals("Hello EN (messages)", message); - } - - @Test - void test_getMessage_withDefaultMessage_messageNotExists() { - String message = messageSource.getMessage( - "not_exists", - null, - "My default message", - Locale.forLanguageTag("en") - ); - - assertEquals("My default message", message); - } - - @Test - void test_getMessage_withDefaultMessage_messageExists_messageWithArgs() { - Object[] args = {"Road Runner", "Wile E. Coyote"}; - String message = messageSource.getMessage( - "roadrunner", - args, - "My default message", - Locale.forLanguageTag("en") - ); - - assertEquals("Road Runner and Wile E. Coyote", message); - } - - @Test - void test_getMessage_withDefaultMessage_messageNotExists_defaultMessageWithArgs() { - Object[] args = {"Road Runner", "Wile E. Coyote"}; - String message = messageSource.getMessage( - "not_exists", - args, - "{0} and {1} as default", - Locale.forLanguageTag("en") - ); - - assertEquals("Road Runner and Wile E. Coyote as default", message); - } - - @Test - void test_getMessage_messageExists() { - String message = messageSource.getMessage( - "hello_language", - null, - Locale.forLanguageTag("en") - ); - - assertEquals("Hello EN (messages)", message); - } - - @Test - void test_getMessage_messageNotExists() { - Locale locale = Locale.forLanguageTag("en"); - - NoSuchMessageException exception = assertThrows(NoSuchMessageException.class, () -> { - messageSource.getMessage( - "not_exists", - null, - locale - ); - }); - - assertEquals("No message found under code 'not_exists' for locale 'en'.", exception.getMessage()); - } - - @Test - void test_getMessage_messageExists_messageWithArgs() { - Object[] args = {"Road Runner", "Wile E. Coyote"}; - String message = messageSource.getMessage( - "roadrunner", - args, - Locale.forLanguageTag("en") - ); - - assertEquals("Road Runner and Wile E. Coyote", message); - } - - @Test - void test_getMessage_resolvable_messageExists_messageWithArgs() { - String[] codes = {"roadrunner"}; - Object[] args = {"Road Runner", "Wile E. Coyote"}; - DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable( - codes, - args - ); - String message = messageSource.getMessage( - resolvable, - Locale.forLanguageTag("en") - ); - - assertEquals("Road Runner and Wile E. Coyote", message); - } - - @Test - void test_getMessage_resolvable_messageNotExists() { - Locale locale = Locale.forLanguageTag("en"); - String[] codes = {"not_exists"}; - DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable( - codes - ); - - NoSuchMessageException exception = assertThrows(NoSuchMessageException.class, () -> { - messageSource.getMessage( - resolvable, - locale - ); - }); - assertEquals("No message found under code 'not_exists' for locale 'en'.", exception.getMessage()); - } - - @Test - void test_getMessage_resolvable_messageNotExists_withDefaultMessage() { - String[] codes = {"not_exists"}; - String defaultMessage = "This is a default message."; - DefaultMessageSourceResolvable resolvable = new DefaultMessageSourceResolvable( - codes, - null, - defaultMessage - ); - String message = messageSource.getMessage( - resolvable, - Locale.forLanguageTag("en") - ); - - assertEquals(defaultMessage, message); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverCasesTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverCasesTest.java deleted file mode 100644 index 784a790..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverCasesTest.java +++ /dev/null @@ -1,172 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceRuntimeException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class XliffMatchingResourcePatternResolverCasesTest { - - @Test - void test_withRegion_setDefaultLocale_notSet() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - - XliffMessageSourceRuntimeException exception = assertThrows( - XliffMessageSourceRuntimeException.class, resolver::initCache - ); - assertEquals("Default language is not set or empty.", exception.getMessage()); - } - - @Test - void test_withRegion_setDefaultLocale_empty() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("")); - - XliffMessageSourceRuntimeException exception = assertThrows( - XliffMessageSourceRuntimeException.class, resolver::initCache - ); - assertEquals("Default language is not set or empty.", exception.getMessage()); - } - - @Test - void test_withRegion_enUS() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.initCache(); - String message = resolver.getMessage( - "hello_language", - null, - Locale.forLanguageTag("en-US") - ); - assertEquals("Hello EN_US (messages)", message); - } - - @Test - void test_withRegion_fallback() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.initCache(); - String message = resolver.getMessage( - "hello_language", - null, - Locale.forLanguageTag("en-GB") - ); - - assertEquals("Hello EN (messages)", message); - } - - @Test - void test_setDefaultDomain() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.setDefaultDomain("otherdomain"); - resolver.initCache(); - String message = resolver.getMessage( - "hello_language", - null, - Locale.forLanguageTag("en-US") - ); - assertEquals("Other Hello EN (otherdomain)", message); - } - - @Test - void test_setBasenamePattern() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamesPattern(List.of("translations/*")); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.setDefaultDomain("otherdomain"); - resolver.initCache(); - String message = resolver.getMessage( - "hello_language", - null, - Locale.forLanguageTag("en-US") - ); - assertEquals("Other Hello EN (otherdomain)", message); - } - - @Test - void test_messagesFormat_choice() { - var messageSource = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - messageSource.setBasenamesPattern(List.of("translations/*")); - messageSource.setDefaultLocale(Locale.forLanguageTag("en")); - messageSource.initCache(); - - assertEquals("There are 10,000 files.", messageSource.getMessage( - "format_choice", - new Object[]{10000L}, - Locale.forLanguageTag("en") - )); - assertEquals("There is one file.", messageSource.getMessage( - "format_choice", - new Object[]{1}, - Locale.forLanguageTag("en") - )); - - assertEquals("Es gibt 10.000 Dateien.", messageSource.getMessage( - "format_choice", - new Object[]{10000L}, - Locale.forLanguageTag("de") - )); - assertEquals("Es gibt eine Datei.", messageSource.getMessage( - "format_choice", - new Object[]{1}, - Locale.forLanguageTag("de") - )); - } - - @ParameterizedTest(name = "{index} => translationUnitIdentifiers={0}, code={1}, expected={2}, targetValue={3}") - @MethodSource("dataProvider_setTranslationUnitIdentifiersOrdering") - void test_setTranslationUnitIdentifiersOrdering(ArrayList translationUnitIdentifiers, String code, String expected) { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamesPattern(List.of("translations/*")); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.setTranslationUnitIdentifiersOrdering(translationUnitIdentifiers); - resolver.initCache(); - - String message = resolver.getMessage( - code, - null, - Locale.forLanguageTag("en") - ); - assertEquals(expected, message); - } - - private static Stream dataProvider_setTranslationUnitIdentifiersOrdering() { - return Stream.of( - Arguments.of( - new ArrayList<>(List.of("resname")), - "code-resname-a", - "Target" - ), - Arguments.of( - new ArrayList<>(List.of("id")), - "code-id-a", - "Target" - ), - Arguments.of( - new ArrayList<>(Arrays.asList("resname", "id")), - "code-resname-a", - "Target" - ), - Arguments.of( - new ArrayList<>(Arrays.asList("id", "resname")), - "code-id-a", - "Target" - ) - ); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverFallbackTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverFallbackTest.java deleted file mode 100644 index 3dcf75f..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverFallbackTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import org.junit.jupiter.api.Test; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class XliffMatchingResourcePatternResolverFallbackTest { - - @Test - void test_fallbackDefaultLanguage() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.initCache(); - String message = resolver.getMessage( - "hello_language", - null, - Locale.forLanguageTag("jp") - ); - assertEquals("Hello EN (messages)", message); - } - - @Test - void test_getMessage_withDefaultMessage_messageNotExists_defaultMessageWithArgs() { - var resolver = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - resolver.setBasenamePattern("translations/*"); - resolver.setDefaultLocale(Locale.forLanguageTag("en")); - resolver.initCache(); - - Object[] args = {"Road Runner", "Wile E. Coyote"}; - String message = resolver.getMessage( - "not_exists", - args, - "{0} and {1} as default", - Locale.forLanguageTag("jp") - ); - - assertEquals("Road Runner and Wile E. Coyote as default", message); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInitCacheTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInitCacheTest.java deleted file mode 100644 index 9d36880..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInitCacheTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import java.util.Locale; -import org.junit.jupiter.api.BeforeAll; - -@SuppressWarnings({"java:S2187"}) -class XliffMatchingResourcePatternResolverInitCacheTest extends XliffMatchingResourcePatternResolverAbstract { - - @BeforeAll - static void beforeAll() { - messageSource = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - messageSource.setBasenamePattern("translations/*"); - messageSource.setDefaultLocale(Locale.forLanguageTag("en")); - messageSource.initCache(); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInternalCacheTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInternalCacheTest.java deleted file mode 100644 index 0b5574e..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverInternalCacheTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import java.util.Locale; -import org.junit.jupiter.api.BeforeAll; - -@SuppressWarnings({"java:S2187"}) -class XliffMatchingResourcePatternResolverInternalCacheTest extends XliffMatchingResourcePatternResolverAbstract { - - @BeforeAll - static void beforeAll() { - messageSource = new XliffTranslationMessageSource(); - messageSource.setBasenamePattern("translations/*"); - messageSource.setDefaultLocale(Locale.forLanguageTag("en")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverTest.java deleted file mode 100644 index 3feecfb..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffMatchingResourcePatternResolverTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff; - -import java.util.Locale; -import org.junit.jupiter.api.BeforeAll; - -@SuppressWarnings({"java:S2187"}) -class XliffMatchingResourcePatternResolverTest extends XliffMatchingResourcePatternResolverAbstract { - - @BeforeAll - static void beforeAll() { - messageSource = new XliffTranslationMessageSource(TestUtilities.getMockedCacheManager()); - messageSource.setBasenamePattern("translations/*"); - messageSource.setDefaultLocale(Locale.forLanguageTag("en")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSourceTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSourceTest.java new file mode 100644 index 0000000..50e5d6f --- /dev/null +++ b/src/test/java/io/github/alaugks/spring/messagesource/xliff/XliffResourceMessageSourceTest.java @@ -0,0 +1,196 @@ +package io.github.alaugks.spring.messagesource.xliff; + +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; + +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff12Identifier; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.Xliff2xIdentifier; +import io.github.alaugks.spring.messagesource.xliff.XliffCatalog.XliffIdentifierInterface; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import org.springframework.context.NoSuchMessageException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class XliffResourceMessageSourceTest { + + @Test + void test_getMessage_code_args_locale() { + var messageSource = XliffResourceMessageSource + .builder(Locale.forLanguageTag("en"), "translations/*") + .build(); + + assertEquals("Postcode", messageSource.getMessage( + "postcode", + null, + Locale.forLanguageTag("en") + )); + + assertEquals("Zip code", messageSource.getMessage( + "postcode", + null, + Locale.forLanguageTag("en-US") + )); + + assertEquals("Postleitzahl", messageSource.getMessage( + "postcode", + null, + Locale.forLanguageTag("de") + )); + } + + @Test + void test_builder_withLocationPatterns() { + var messageSource = XliffResourceMessageSource + .builder( + Locale.forLanguageTag("en"), + List.of( + "translations_en/*", + "translations_de/*" + ) + ) + .build(); + + assertEquals( + "Postcode", + messageSource.getMessage("messages.postcode", null, Locale.forLanguageTag("en")) + ); + assertEquals( + "Expiry date", + messageSource.getMessage("payment.expiry_date", null, Locale.forLanguageTag("en")) + ); + assertEquals( + "Postleitzahl", + messageSource.getMessage("messages.postcode", null, Locale.forLanguageTag("de")) + ); + assertEquals( + "Ablaufdatum", + messageSource.getMessage("payment.expiry_date", null, Locale.forLanguageTag("de")) + ); + } + + @Test + void test_defaultDomain() { + var messageSource = XliffResourceMessageSource + .builder(Locale.forLanguageTag("en"), "translations/*") + .defaultDomain("payment") + .build(); + + assertEquals("Expiry date", messageSource.getMessage( + "expiry_date", + null, + Locale.forLanguageTag("en-US") + )); + } + + @Test + void test_fileExtensions() { + var messageSource = XliffResourceMessageSource + .builder(Locale.forLanguageTag("en"), "translations/*") + .fileExtensions(List.of("xlf")) + .build(); + + var locale = Locale.forLanguageTag("en"); + assertThrows(NoSuchMessageException.class, () -> messageSource.getMessage( + "postcode", + null, + locale + )); + } + + @ParameterizedTest() + @MethodSource("dataProvider_setTranslationUnitIdentifiersOrdering") + void test_identifier( + List translationUnitIdentifiers, + String code, + String expected + ) { + var messageSource = XliffResourceMessageSource + .builder( + Locale.forLanguageTag("en"), + List.of( + "fixtures/identifierxliff12.xliff", + "fixtures/identifierxliff2x.xliff" + ) + ) + .identifier(translationUnitIdentifiers) + .build(); + + String message = messageSource.getMessage( + code, + null, + Locale.forLanguageTag("en") + ); + assertEquals(expected, message); + } + + private static Stream dataProvider_setTranslationUnitIdentifiersOrdering() { + return Stream.of( + Arguments.of( + List.of( + new Xliff12Identifier(List.of("resname")) + ), + "identifierxliff12.code-resname-a", + "Target A" + ), + Arguments.of( + List.of( + new Xliff12Identifier(List.of("id")) + ), + "identifierxliff12.code-id-a", + "Target A" + ), + + Arguments.of( + List.of( + new Xliff12Identifier(List.of("resname", "id")) + ), + "identifierxliff12.code-id-b", + "Target B" + ), + Arguments.of( + List.of( + new Xliff12Identifier(List.of("id", "resname")) + ), + "identifierxliff12.code-resname-c", + "Target C" + ), + + Arguments.of( + List.of( + new Xliff2xIdentifier(List.of("resname")) + ), + "identifierxliff2x.code-resname-a", + "Target A" + ), + Arguments.of( + List.of( + new Xliff2xIdentifier(List.of("id")) + ), + "identifierxliff2x.code-id-a", + "Target A" + ), + + Arguments.of( + List.of( + new Xliff2xIdentifier(List.of("resname", "id")) + ), + "identifierxliff2x.code-id-b", + "Target B" + ), + Arguments.of( + List.of( + new Xliff2xIdentifier(List.of("id", "resname")) + ), + "identifierxliff2x.code-resname-c", + "Target C" + ) + ); + } + +} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCacheTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCacheTest.java deleted file mode 100644 index c9fcd22..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogCacheTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import io.github.alaugks.spring.messagesource.xliff.TestUtilities; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceCacheNotExistsException; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.cache.CacheManager; - -import java.util.HashMap; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.*; - -class CatalogCacheTest { - private CatalogCache catalogCache; - private Locale locale; - - @BeforeEach - void beforeEach() { - this.catalogCache = new CatalogCache(TestUtilities.getMockedCacheManager()); - this.locale = Locale.forLanguageTag("en"); - } - - @Test - void test_initCache() { - Catalog catalog = new Catalog(); - catalog.put(this.locale, "domain", "code", "targetValue"); - this.catalogCache.initCache(catalog); - assertTrue(catalog.has(locale, "domain.code")); - } - - @Test - void test_getAll() { - assertInstanceOf(HashMap.class, this.catalogCache.getAll()); - } - - @Test - void test_put_get_withDomain() { - this.catalogCache.put(this.locale, "domain", "code", "targetValue"); - assertEquals("targetValue", this.catalogCache.get(this.locale, "domain.code")); - } - - @Test - void test_put_has_withDomain() { - Locale locale = Locale.forLanguageTag("en"); - this.catalogCache.put(this.locale, "domain", "code", "targetValue"); - assertTrue(this.catalogCache.has(locale, "domain.code")); - assertFalse(this.catalogCache.has(locale, "domain.bar")); - } - - @Test - void test_put_get() { - Locale locale = Locale.forLanguageTag("en"); - this.catalogCache.put(this.locale, "code", "targetValue"); - assertEquals("targetValue", this.catalogCache.get(this.locale, "code")); - } - - @Test - void test_put_has() { - Locale locale = Locale.forLanguageTag("en"); - this.catalogCache.put(this.locale, "code", "targetValue"); - assertTrue(this.catalogCache.has(locale, "code")); - assertFalse(this.catalogCache.has(locale, "bar")); - } - - @Test - void test_get_onNull() { - this.catalogCache.put(this.locale, "domain", "code", "targetValue"); - assertNull(this.catalogCache.get(this.locale, "domain.foo")); - } - - @Test - void test_get_onNull_localeEmpty() { - this.catalogCache.put(this.locale, "domain", "code", "targetValue"); - assertNull(this.catalogCache.get(Locale.forLanguageTag(""), "domain.foo")); - } - - @Test - void test_exception_cacheNameNotExists() { - CacheManager cacheManager = TestUtilities.getMockedCacheManager("CACHE_NAME_NOT_EXISTS"); - - XliffMessageSourceCacheNotExistsException exception = assertThrows( - XliffMessageSourceCacheNotExistsException.class, () -> { - new CatalogCache(cacheManager); - } - ); - assertEquals( - "Cache with name [messagesource.xliff.catalog.CACHE] not available.", - exception.getMessage() - ); - } - - @Test - void test_exception() { - XliffMessageSourceCacheNotExistsException exception = assertThrows( - XliffMessageSourceCacheNotExistsException.class, () -> { - new CatalogCache(null); - } - ); - assertEquals("org.springframework.cache.CacheManager not available.", exception.getMessage()); - } - - @Test - void test_Constants() { - assertEquals("messagesource.xliff.catalog.CACHE", CatalogCache.CACHE_NAME); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogTest.java deleted file mode 100644 index 56e593c..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.*; - -class CatalogTest { - - static Catalog catalog = new Catalog(); - - @BeforeEach - void BeforeEach() { - // Domain foo - catalog.put(Locale.forLanguageTag("en"), "foo", "key_1", "value_en_1"); - catalog.put(Locale.forLanguageTag("en"), "foo", "key_2", "value_en_2"); - catalog.put(Locale.forLanguageTag("en"), "foo", "key_1", "value_en_3"); // Check overwrite - // Domain bar - catalog.put(Locale.forLanguageTag("en"), "bar", "key_1", "value_en_1"); - catalog.put(Locale.forLanguageTag("en"), "bar", "key_2", "value_en_2"); - catalog.put(Locale.forLanguageTag("en"), "bar", "key_1", "value_en_3"); // Check overwrite - // Domain foo - catalog.put(Locale.forLanguageTag("en-US"), "foo", "key_1", "value_en_us_1"); - catalog.put(Locale.forLanguageTag("en_US"), "foo", "key_2", "value_en_us_2"); - } - - @Test - void test_en() { - // Domain foo - Locale locale = Locale.forLanguageTag("en"); - assertEquals("value_en_1", catalog.get(locale, "foo.key_1")); - // Domain bar - assertEquals("value_en_1", catalog.get(locale, "bar.key_1")); - // Domain foo - assertEquals("value_en_2", catalog.get(locale, "foo.key_2")); - // Domain bar - assertEquals("value_en_2", catalog.get(locale, "bar.key_2")); - - // Domain bar - assertNull(catalog.get(locale, "bar.key_3")); - // Domain foo - assertNull(catalog.get(locale, "foo.key_3")); - } - - @Test - void test_localeExists() { - assertTrue(catalog.localeExists(Locale.forLanguageTag("en"))); - assertTrue(catalog.localeExists(Locale.forLanguageTag("en-US"))); - assertFalse(catalog.localeExists(Locale.forLanguageTag("en_US"))); - assertFalse(catalog.localeExists(Locale.forLanguageTag("jp"))); - } - - @Test - void test_enUk_withDash() { - Locale locale = Locale.forLanguageTag("en-US"); - // Domain foo - assertEquals("value_en_us_1", catalog.get(locale, "foo.key_1")); - } - - @Test - void test_enUk_withUnderscore() { - Locale locale = Locale.forLanguageTag("en_US"); - // Domain foo - assertNull(catalog.get(locale, "foo.key_2")); - } - - @Test - void test_hasTranslation_true() { - Locale locale = Locale.forLanguageTag("en"); - assertTrue(catalog.has(locale, "foo.key_1")); - } - - @Test - void test_hasTranslation_false() { - Locale locale = Locale.forLanguageTag("en"); - assertFalse(catalog.has(locale, "key_3")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilitiesTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilitiesTest.java deleted file mode 100644 index 82173c2..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogUtilitiesTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import org.junit.jupiter.api.Test; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class CatalogUtilitiesTest { - - @Test - void test_concat_Code() { - assertEquals("domain.code", CatalogUtilities.concatCode("domain", "code")); - } - - @Test - void test_normalizeLocale() { - assertEquals("en", CatalogUtilities.localeToKey(Locale.forLanguageTag("en"))); - assertEquals("en", CatalogUtilities.localeToKey(Locale.forLanguageTag("EN"))); - assertEquals("en-gb", CatalogUtilities.localeToKey(Locale.forLanguageTag("en-gb"))); - assertEquals("en-gb", CatalogUtilities.localeToKey(Locale.forLanguageTag("en-GB"))); - assertEquals("en-gb", CatalogUtilities.localeToKey(Locale.forLanguageTag("EN-GB"))); - - Locale localeVariant1 = new Locale.Builder().setLanguage("de").setRegion("DE").setVariant("Cologne").build(); - assertEquals("de-de", CatalogUtilities.localeToKey(localeVariant1)); - - Locale localeVariant2 = Locale.forLanguageTag("de-Germany"); - assertEquals("de", CatalogUtilities.localeToKey(localeVariant2)); - - Locale localeVariant3 = Locale.forLanguageTag("hy-Latn-IT-arevela"); - assertEquals("hy-it", CatalogUtilities.localeToKey(localeVariant3)); - } - - @Test - void test_buildLocale_Locale() { - assertEquals("en", CatalogUtilities.buildLocale(Locale.forLanguageTag("en")).toString()); - assertEquals("en", CatalogUtilities.buildLocale(Locale.forLanguageTag("EN")).toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale(Locale.forLanguageTag("en-gb")).toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale(Locale.forLanguageTag("en-GB")).toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale(Locale.forLanguageTag("EN-GB")).toString()); - - Locale localeVariant1 = new Locale.Builder().setLanguage("de").setRegion("DE").setVariant("Cologne").build(); - assertEquals("de_DE", CatalogUtilities.buildLocale(localeVariant1).toString()); - - Locale localeVariant2 = Locale.forLanguageTag("de-Germany"); - assertEquals("de", CatalogUtilities.buildLocale(localeVariant2).toString()); - - Locale localeVariant3 = Locale.forLanguageTag("hy-Latn-IT-arevela"); - assertEquals("hy_IT", CatalogUtilities.buildLocale(localeVariant3).toString()); - - Locale localeVariant4 = Locale.forLanguageTag("sr-Cyrl"); - assertEquals("sr", CatalogUtilities.buildLocale(localeVariant4).toString()); - } - - @Test - void test_buildLocale_languageRegion() { - assertEquals("en", CatalogUtilities.buildLocale("en", null).toString()); - assertEquals("", CatalogUtilities.buildLocale(null, "GB").toString()); - assertEquals("en", CatalogUtilities.buildLocale(Locale.forLanguageTag("EN")).toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale("en", "gb").toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale("en", "GB").toString()); - assertEquals("en_GB", CatalogUtilities.buildLocale("EN", "GB").toString()); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapperTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapperTest.java deleted file mode 100644 index 8f7f4e0..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/CatalogWrapperTest.java +++ /dev/null @@ -1,179 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog; - -import io.github.alaugks.spring.messagesource.xliff.TestUtilities; -import io.github.alaugks.spring.messagesource.xliff.catalog.xliff.XliffCatalogBuilder; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoaderInterface; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InOrder; -import org.mockito.Mockito; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -class CatalogWrapperTest { - - private Locale locale; - private CatalogWrapper catalogWrapper; - - @BeforeEach - void beforeEach() { - this.locale = Locale.forLanguageTag("en"); - this.catalogWrapper = TestUtilities.getCacheWrapperWithCachedTestCatalog(); - } - - @Test - void test_get() { - assertEquals("Hello EN (messages)", this.catalogWrapper.get(this.locale, "hello_language").toString()); - // again - assertEquals("Hello EN (messages)", this.catalogWrapper.get(this.locale, "messages.hello_language").toString()); - // again - assertEquals("Hello EN (messages)", this.catalogWrapper.get(this.locale, "hello_language").toString()); - // again - assertEquals("Hello EN (messages)", this.catalogWrapper.get(this.locale, "messages.hello_language").toString()); - } - - @Test - void test_get_notExists() { - for (int i = 0; i < 3; i++) { - assertEquals("not-exists-id", this.catalogWrapper.get(this.locale, "not-exists-id").toString()); - } - } - - @Test - void test_put() { - this.catalogWrapper.setDefaultDomain("foo"); - - this.catalogWrapper.put(this.locale, "foo", "code", "foo_value"); - assertEquals("foo_value", this.catalogWrapper.get(this.locale, "code").toString()); - - this.catalogWrapper.put(this.locale, "bar", "code", "bar_value"); - assertEquals("bar_value", this.catalogWrapper.get(this.locale, "bar.code").toString()); - } - - @Test - void test_getTargetValue_fromCache() { - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - CatalogInterface catalog = TestUtilities.getTestCatalog(); - ResourcesLoaderInterface resourcesLoader = TestUtilities.getResourcesLoader(); - - XliffCatalogBuilder mockedXliffCatalogBuilder = Mockito.spy(xliffCatalogBuilder); - - CatalogWrapper catalogWrapper = new CatalogWrapper( - TestUtilities.getMockedCacheManager(), - resourcesLoader, - mockedXliffCatalogBuilder, - catalog - ); - - CatalogWrapper mockedCatalogWrapper = Mockito.spy(catalogWrapper); - mockedCatalogWrapper.initCache(); - mockedCatalogWrapper.get(this.locale, "messages.hello_language"); // From Cache - mockedCatalogWrapper.get(this.locale, "roadrunner"); // From Cache - - // initCache() called createCatalog(resourcesLoader, catalog) - // But createCatalog(resourcesLoader, catalog) will not be called the second time. - InOrder orderVerifier = Mockito.inOrder(mockedCatalogWrapper, mockedXliffCatalogBuilder); - orderVerifier.verify(mockedCatalogWrapper).initCache(); - orderVerifier.verify(mockedXliffCatalogBuilder).createCatalog(resourcesLoader, catalog); - - verify(mockedCatalogWrapper, times(1)).initCache(); - verify(mockedXliffCatalogBuilder, times(1)).createCatalog(resourcesLoader, catalog); - } - - @Test - void test_getTargetValue_fromCatalog_fromCache() { - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - CatalogInterface catalog = TestUtilities.getTestCatalog(); - ResourcesLoaderInterface resourcesLoader = TestUtilities.getResourcesLoader(); - XliffCatalogBuilder mockedXliffCatalogBuilder = Mockito.spy(xliffCatalogBuilder); - - CatalogWrapper catalogWrapper = new CatalogWrapper( - TestUtilities.getMockedCacheManager(), - resourcesLoader, - mockedXliffCatalogBuilder, - catalog - ); - - catalogWrapper.get(this.locale, "messages.hello_language"); // From Files + Init Cache - catalogWrapper.get(this.locale, "messages.hello_language"); // From Cache - catalogWrapper.get(this.locale, "roadrunner"); // From Cache - catalogWrapper.get(this.locale, "messages.hello_language"); // From Cache - - verify(mockedXliffCatalogBuilder, times(1)).createCatalog(resourcesLoader, catalog); - } - - @Test - void test_getTargetValue_fromCatalog_cacheNotInit() { - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - CatalogInterface catalog = TestUtilities.getTestCatalog(); - ResourcesLoaderInterface resourcesLoader = TestUtilities.getResourcesLoader(); - XliffCatalogBuilder mockedXliffCatalogBuilder = Mockito.spy(xliffCatalogBuilder); - - CatalogWrapper catalogWrapper = new CatalogWrapper( - TestUtilities.getMockedCacheManager(), - resourcesLoader, - mockedXliffCatalogBuilder, - catalog - ); - - catalogWrapper.get(this.locale, "messages.hello_language"); - - verify(mockedXliffCatalogBuilder, times(1)).createCatalog(resourcesLoader, catalog); - } - - @Test - void test_fillCacheWithCodeBecauseCodeNotExists() { - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - CatalogInterface catalog = TestUtilities.getTestCatalog(); - ResourcesLoaderInterface resourcesLoader = TestUtilities.getResourcesLoader(); - XliffCatalogBuilder mockedXliffCatalogBuilder = Mockito.spy(xliffCatalogBuilder); - - CatalogWrapper catalogWrapper = new CatalogWrapper( - TestUtilities.getMockedCacheManager(), - resourcesLoader, - mockedXliffCatalogBuilder, - catalog - ); - - CatalogWrapper mockedCatalogWrapper = Mockito.spy(catalogWrapper); - mockedCatalogWrapper.initCache(); - - // First: put - assertEquals( - "messages.hello_language_not_exists", - mockedCatalogWrapper.get(this.locale, "messages.hello_language_not_exists").toString() - ); - - // Second: Get from Cache - assertEquals( - "messages.hello_language_not_exists", - mockedCatalogWrapper.get(this.locale, "messages.hello_language_not_exists").toString() - ); - - InOrder orderVerifier = Mockito.inOrder(mockedCatalogWrapper, mockedXliffCatalogBuilder); - // code not exists in cache - orderVerifier.verify(mockedCatalogWrapper).initCache(); - // initCache() called createCatalog() - orderVerifier.verify(mockedXliffCatalogBuilder).createCatalog(resourcesLoader, catalog); - // get() called createCatalog() because code not exists in cache - orderVerifier.verify(mockedXliffCatalogBuilder).createCatalog(resourcesLoader, catalog); - // code add cache - orderVerifier.verify(mockedCatalogWrapper).put( - this.locale, - "messages.hello_language_not_exists", - "messages.hello_language_not_exists" - ); - - verify(mockedCatalogWrapper, times(1)).initCache(); - verify(mockedXliffCatalogBuilder, times(2)).createCatalog(resourcesLoader, catalog); - verify(mockedCatalogWrapper, times(1)).put( - this.locale, - "messages.hello_language_not_exists", - "messages.hello_language_not_exists" - ); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12Test.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12Test.java deleted file mode 100644 index f347a5d..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff12Test.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.TestUtilities; -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class Xliff12Test { - - private Document document; - - @BeforeEach - void beforeEach() throws ParserConfigurationException, IOException, SAXException { - String filePath = "fixtures/xliff12.xliff"; - InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filePath); - this.document = TestUtilities.getDocument(inputStream); - } - - @Test - void test_readXliffFile() { - Xliff12 version = new Xliff12(); - CatalogInterface catalog = new Catalog(); - Locale locale = Locale.forLanguageTag("en"); - version.read(catalog, document, "domain", locale); - - assertEquals("Hallo, Welt!", catalog.get(locale, "domain.code-1")); - assertEquals("Dies ist ein weiterer Satz.", catalog.get(locale, "domain.code-2")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff20Test.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff20Test.java deleted file mode 100644 index b2a822f..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff20Test.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.TestUtilities; -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class Xliff20Test { - - private Document document; - - @BeforeEach - void beforeEach() throws ParserConfigurationException, IOException, SAXException { - String filePath = "fixtures/xliff20.xliff"; - InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filePath); - this.document = TestUtilities.getDocument(inputStream); - } - - @Test - void test_readXliffFile() { - Xliff2 version = new Xliff2(); - CatalogInterface catalog = new Catalog(); - Locale locale = Locale.forLanguageTag("en"); - version.read(catalog, document, "domain", locale); - - assertEquals("Hallo, Welt!", catalog.get(locale, "domain.code-1")); - assertEquals("Dies ist ein weiterer Satz.", catalog.get(locale, "domain.code-2")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff21Test.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff21Test.java deleted file mode 100644 index 0c5c066..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/Xliff21Test.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.TestUtilities; -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class Xliff21Test { - - private Document document; - - @BeforeEach - void beforeEach() throws ParserConfigurationException, IOException, SAXException { - String filePath = "fixtures/xliff21.xliff"; - InputStream inputStream = getClass().getClassLoader().getResourceAsStream(filePath); - this.document = TestUtilities.getDocument(inputStream); - } - - @Test - void test_readXliffFile() { - Xliff2 version = new Xliff2(); - CatalogInterface catalog = new Catalog(); - Locale locale = Locale.forLanguageTag("en"); - version.read(catalog, document, "domain", locale); - - assertEquals("Hallo, Welt!", catalog.get(locale, "domain.code-1")); - //assertEquals("Dies ist ein weiterer Satz.", catalog.get(locale, "code-2")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilderTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilderTest.java deleted file mode 100644 index 31644a4..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffCatalogBuilderTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import io.github.alaugks.spring.messagesource.xliff.catalog.Catalog; -import io.github.alaugks.spring.messagesource.xliff.catalog.CatalogInterface; -import io.github.alaugks.spring.messagesource.xliff.exception.XliffMessageSourceVersionSupportException; -import io.github.alaugks.spring.messagesource.xliff.ressources.ResourcesLoader; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class XliffCatalogBuilderTest { - - @Test - void test_createCatalog() { - ResourcesLoader resourcesLoader = new ResourcesLoader(); - resourcesLoader.setBasenamePattern("translations/*"); - resourcesLoader.setDefaultLocale(Locale.forLanguageTag("en")); - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - CatalogInterface catalog = xliffCatalogBuilder.createCatalog(resourcesLoader, new Catalog()); - assertEquals("Hello EN (messages)", catalog.get(Locale.forLanguageTag("en"), "messages.hello_language")); - } - - @Test - void test_createCatalog_versionNotSupported() { - Catalog catalog = new Catalog(); - ResourcesLoader resourcesLoader = new ResourcesLoader(); - resourcesLoader.setBasenamePattern("fixtures/*"); - resourcesLoader.setDefaultLocale(Locale.forLanguageTag("en-GB")); - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - - XliffMessageSourceVersionSupportException exception = assertThrows( - XliffMessageSourceVersionSupportException.class, () -> { - xliffCatalogBuilder.createCatalog(resourcesLoader, catalog); - } - ); - assertEquals("XLIFF version \"1.0\" not supported.", exception.getMessage()); - } - - @Test - @Disabled("Todo: Handling [Fatal Error] :9:7: The element type \"body\" must be terminated by the matching end-tag \"\".") - void test_createCatalog_parseError() { - // ErrorHandler errorHandler = new SimpleSaxErrorHandler(new NoOpLog()); - var catalog = new Catalog(); - ResourcesLoader resourcesLoader = new ResourcesLoader(); - resourcesLoader.setBasenamePattern("translations_broken/*"); - resourcesLoader.setDefaultLocale(Locale.forLanguageTag("en")); - XliffCatalogBuilder xliffCatalogBuilder = new XliffCatalogBuilder(); - - Throwable exception = assertThrows( - Throwable.class, () -> { - xliffCatalogBuilder.createCatalog(resourcesLoader, catalog); - } - ); - //assertTrue(exception.getMessage().indexOf("body") > 0); - //assertEquals("The element type \"body\" must be terminated by the matching end-tag \"\".", exception.getMessage()); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtilityTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtilityTest.java deleted file mode 100644 index 4db393e..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffParserUtilityTest.java +++ /dev/null @@ -1,116 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Objects; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -class XliffParserUtilityTest { - - @ParameterizedTest(name = "{index} => elementName={0}, translationUnitIdentifiers={1}, expected={2}") - @MethodSource("getCodeProvider") - void test_getCode( - String elementName, - ArrayList translationUnitIdentifiers, - String expected - ) { - NodeList nodeList = XliffParserUtility.getTranslationUnits(getDocument(), elementName); - Element node = (Element) nodeList.item(0); - assertEquals(expected, XliffParserUtility.getCode(node, translationUnitIdentifiers)); - } - - @Test - void test_getElementValue_getCharacterDataFromElement_TextNode() { - String value; - value = XliffParserUtility.getElementValue(getRootElement(), "element"); - assertEquals("value", value); - value = XliffParserUtility.getElementValue(getRootElement(), "element-newline"); - assertEquals("value", value); - value = XliffParserUtility.getElementValue(getRootElement(), "element-with-cdata"); - assertEquals("value", value); - value = XliffParserUtility.getElementValue(getRootElement(), "element-with-cdata-newline"); - assertEquals("value", value); - } - - @Test - void test_getElementValue_getCharacterDataFromElement_Node() { - String value = XliffParserUtility.getElementValue(getRootElement(), "dummy"); - assertNull(value); - } - - private static Document getDocument() { - try { - InputStream fileStream = XliffParserUtilityTest - .class - .getClassLoader() - .getResourceAsStream("fixtures/xliff-parser-utility-test.xliff"); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - return builder.parse(fileStream); - } catch (ParserConfigurationException | IOException | SAXException e) { - return null; - } - } - - private static Element getRootElement() { - return Objects.requireNonNull(getDocument()).getDocumentElement(); - } - - private static Stream getCodeProvider() { - return Stream.of( - Arguments.of( - "trans-unit-a", - new ArrayList<>(Arrays.asList("resname", "id")), - "resname-a" - ), - Arguments.of( - "trans-unit-a", - new ArrayList<>(Arrays.asList("id", "resname")), - "id-a" - ), - Arguments.of( - "trans-unit-b", - new ArrayList<>(Arrays.asList("resname", "id")), - "id-b" - ), - Arguments.of( - "trans-unit-b", - new ArrayList<>(Arrays.asList("id", "resname")), - "id-b" - ), - Arguments.of( - "trans-unit-c", - new ArrayList<>(Arrays.asList("id", "resname")), - null - ), - Arguments.of( - "trans-unit-c", - new ArrayList<>(), - null - ), - Arguments.of( - "trans-unit-c", - null, - null - ) - ); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReaderTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReaderTest.java deleted file mode 100644 index f1f5070..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/catalog/xliff/XliffReaderTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.catalog.xliff; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNull; - -class XliffReaderTest { - - private XliffReader reader; - - @BeforeEach - void beforeEach() { - this.reader = new XliffReader(); - } - - @Test - void test_supportedVersions() { - assertInstanceOf(Xliff12.class, this.reader.getReader("1.2")); - assertInstanceOf(Xliff2.class, this.reader.getReader("2.0")); - assertInstanceOf(Xliff2.class, this.reader.getReader("2.1")); - } - - @Test - void test_versionNotSupported() { - assertNull(this.reader.getReader("1.0")); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandlerTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandlerTest.java new file mode 100644 index 0000000..36f294c --- /dev/null +++ b/src/test/java/io/github/alaugks/spring/messagesource/xliff/exception/SaxErrorHandlerTest.java @@ -0,0 +1,38 @@ +package io.github.alaugks.spring.messagesource.xliff.exception; + +import org.junit.jupiter.api.Test; +import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; + +class SaxErrorHandlerTest { + + @Test + void test_warning() { + var handler = new SaxErrorHandler(); + assertThrows( + XliffMessageSourceSAXParseException.Warning.class, + () -> handler.warning(new SAXParseException("Warning", mock(Locator.class))) + ); + } + + @Test + void test_error() { + var handler = new SaxErrorHandler(); + assertThrows( + XliffMessageSourceSAXParseException.Error.class, + () -> handler.error(new SAXParseException("Error", mock(Locator.class))) + ); + } + + @Test + void test_fatalError() { + var handler = new SaxErrorHandler(); + assertThrows( + XliffMessageSourceSAXParseException.FatalError.class, + () -> handler.fatalError(new SAXParseException("FatalError", mock(Locator.class))) + ); + } +} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParserTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParserTest.java deleted file mode 100644 index b15743c..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesFileNameParserTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.ressources; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class ResourcesFileNameParserTest { - - @Test - void test_domain_withoutLocale() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message").parse(); - assertEquals("message", filename.getDomain()); - assertNull(filename.getLanguage()); - assertNull(filename.getRegion()); - } - - @Test - void test_domain_en() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message_en").parse(); - assertEquals("message", filename.getDomain()); - assertEquals("en", filename.getLanguage()); - assertNull(filename.getRegion()); - } - - @Test - void test_domain_en_withDash() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message-en").parse(); - assertEquals("message", filename.getDomain()); - assertEquals("en", filename.getLanguage()); - assertNull(filename.getRegion()); - } - - @Test - void test_domain_enGB() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message_en_GB").parse(); - assertEquals("message", filename.getDomain()); - assertEquals("en", filename.getLanguage()); - assertEquals("GB", filename.getRegion()); - } - - @Test - void test_domain_enGB_withDash() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message-en-GB").parse(); - assertEquals("message", filename.getDomain()); - assertEquals("en", filename.getLanguage()); - assertEquals("GB", filename.getRegion()); - } - - @Test - void test_hasNoLocale() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message").parse(); - assertFalse(filename.hasLocale()); - } - - @Test - void test_hasLocale() { - ResourcesFileNameParser.Dto filename = new ResourcesFileNameParser("message_de").parse(); - assertTrue(filename.hasLocale()); - } -} diff --git a/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderTest.java b/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderTest.java deleted file mode 100644 index 8f4e10b..0000000 --- a/src/test/java/io/github/alaugks/spring/messagesource/xliff/ressources/ResourcesLoaderTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.github.alaugks.spring.messagesource.xliff.ressources; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - -class ResourcesLoaderTest { - - ArrayList resources; - private ResourcesLoader resourcesLoader; - - @BeforeEach - void beforeEach() throws IOException { - this.resourcesLoader = new ResourcesLoader(); - this.resourcesLoader.setDefaultLocale(Locale.forLanguageTag("en")); - - } - - @Test - void test_setBasenamePattern() throws IOException { - this.resourcesLoader.setBasenamePattern( - "translations/*" - ); - assertEquals(5, this.resourcesLoader.getResourcesInputStream().size()); - } - - @Test - void test_setBasenamePattern_domainMessages() throws IOException { - this.resourcesLoader.setBasenamePattern( - "translations/messages*" - ); - assertEquals(3, this.resourcesLoader.getResourcesInputStream().size()); - } - - - @Test - void test_setBasenamePattern_languageDe() throws IOException { - this.resourcesLoader.setBasenamePattern( - "translations/*_de*" - ); - assertEquals(2, this.resourcesLoader.getResourcesInputStream().size()); - } - - @Test - void test_setBasenamesPattern() throws IOException { - this.resourcesLoader.setBasenamesPattern( - List.of( - "translations_en/*", - "translations_de/*" - ) - ); - assertEquals(4, this.resourcesLoader.getResourcesInputStream().size()); - } - - @Test - void test_Dto() throws IOException { - this.resourcesLoader.setBasenamePattern( - "translations_en_US/*" - ); - ResourcesLoader.Dto dto = this.resourcesLoader.getResourcesInputStream().get(0); - assertEquals("messages", dto.getDomain()); - assertEquals("en_US", dto.getLocale().toString()); - assertInstanceOf(InputStream.class, dto.getInputStream()); - } -} diff --git a/src/test/resources/fixtures/identifierxliff12.xliff b/src/test/resources/fixtures/identifierxliff12.xliff new file mode 100644 index 0000000..1a299cf --- /dev/null +++ b/src/test/resources/fixtures/identifierxliff12.xliff @@ -0,0 +1,23 @@ + + + + + + Source A + Target A + + + Source B + Target B + + + Source C + Target C + + + + diff --git a/src/test/resources/fixtures/identifierxliff2x.xliff b/src/test/resources/fixtures/identifierxliff2x.xliff new file mode 100644 index 0000000..3164584 --- /dev/null +++ b/src/test/resources/fixtures/identifierxliff2x.xliff @@ -0,0 +1,22 @@ + + + + + + Source A + Target A + + + Source B + Target B + + + Source C + Target C + + + + diff --git a/src/test/resources/fixtures/no-xliff.xml b/src/test/resources/fixtures/no-xliff.xml new file mode 100644 index 0000000..d4a7d6d --- /dev/null +++ b/src/test/resources/fixtures/no-xliff.xml @@ -0,0 +1,2 @@ + + diff --git a/src/test/resources/translations_broken/messages_en_US.xliff b/src/test/resources/fixtures/parse_error.xliff similarity index 100% rename from src/test/resources/translations_broken/messages_en_US.xliff rename to src/test/resources/fixtures/parse_error.xliff diff --git a/src/test/resources/fixtures/xliff-fail.xliff b/src/test/resources/fixtures/xliff-fail.xliff new file mode 100644 index 0000000..7c05511 --- /dev/null +++ b/src/test/resources/fixtures/xliff-fail.xliff @@ -0,0 +1,14 @@ + + + + + + Hello World! + Hallo Welt! + + + + diff --git a/src/test/resources/fixtures/xliff-parser-utility-test.xliff b/src/test/resources/fixtures/xliff-parser-utility-test.xliff deleted file mode 100644 index 502785d..0000000 --- a/src/test/resources/fixtures/xliff-parser-utility-test.xliff +++ /dev/null @@ -1,17 +0,0 @@ - - - value - - value - - - - - - - - - - diff --git a/src/test/resources/fixtures/xliff-value-test.xliff b/src/test/resources/fixtures/xliff-value-test.xliff new file mode 100644 index 0000000..0580fe2 --- /dev/null +++ b/src/test/resources/fixtures/xliff-value-test.xliff @@ -0,0 +1,38 @@ + + + + + + value + value + + + + value + + + value + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/fixtures/xliff12.xliff b/src/test/resources/fixtures/xliff12.xliff index 17cae9b..60991eb 100644 --- a/src/test/resources/fixtures/xliff12.xliff +++ b/src/test/resources/fixtures/xliff12.xliff @@ -9,12 +9,8 @@ target-language="de"> - Hello, world! - Hallo, Welt! - - - This is another sentence. - Dies ist ein weiterer Satz. + Postcode (Xliff Version 1.2) + Postcode (Xliff Version 1.2) diff --git a/src/test/resources/fixtures/xliff20.xliff b/src/test/resources/fixtures/xliff20.xliff index 8d7bf74..56a7c5c 100644 --- a/src/test/resources/fixtures/xliff20.xliff +++ b/src/test/resources/fixtures/xliff20.xliff @@ -5,13 +5,9 @@ xsi:schemaLocation="urn:oasis:names:tc:xliff:document:2.0 xliff-core-2.0.xsd"> - - Hello, world! - Hallo, Welt! - - - This is another sentence. - Dies ist ein weiterer Satz. + + Postcode (Xliff Version 2.0) + Postcode (Xliff Version 2.0) diff --git a/src/test/resources/fixtures/xliff21.xliff b/src/test/resources/fixtures/xliff21.xliff index 4338b4a..eee88df 100644 --- a/src/test/resources/fixtures/xliff21.xliff +++ b/src/test/resources/fixtures/xliff21.xliff @@ -6,8 +6,8 @@ - Hello, world! - Hallo, Welt! + Postcode (Xliff Version 2.1) + Postcode (Xliff Version 2.1) diff --git a/src/test/resources/translations/.xliff b/src/test/resources/translations/.xliff deleted file mode 100644 index 47a012b..0000000 --- a/src/test/resources/translations/.xliff +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - Hello EN (messages) - - - Hello EN (messages) - - - - - {0} and {1} - - - {0} and {1} - - - - - diff --git a/src/test/resources/translations/messages.properties b/src/test/resources/translations/messages.properties deleted file mode 100644 index ee052e5..0000000 --- a/src/test/resources/translations/messages.properties +++ /dev/null @@ -1 +0,0 @@ -hello_language=This is only for a jUnit-Test diff --git a/src/test/resources/translations/messages.xliff b/src/test/resources/translations/messages.xliff index c5df9d0..62d0ff8 100644 --- a/src/test/resources/translations/messages.xliff +++ b/src/test/resources/translations/messages.xliff @@ -6,36 +6,12 @@ source-language="en" target-language="en"> - + - Hello EN (messages) + Postcode - Hello EN (messages) - - - - - {0} and {1} - - - {0} and {1} - - - - - Source - - - Target - - - - - Source - - - Target + Postcode diff --git a/src/test/resources/translations/messages_de.xliff b/src/test/resources/translations/messages_de.xliff index 36aefcc..82b3ce0 100644 --- a/src/test/resources/translations/messages_de.xliff +++ b/src/test/resources/translations/messages_de.xliff @@ -6,21 +6,12 @@ source-language="en" target-language="de"> - + - - Hello EN (messages) + Postcode - Hallo DE (messages) - - - - - {0} and {1} - - - {0} und {1} + Postleitzahl diff --git a/src/test/resources/translations/messages_en_US.xliff b/src/test/resources/translations/messages_en_US.xliff index 40a2adc..88bfb28 100644 --- a/src/test/resources/translations/messages_en_US.xliff +++ b/src/test/resources/translations/messages_en_US.xliff @@ -4,22 +4,14 @@ + target-language="en-US"> - + - Hello EN (messages) + Postcode - Hello EN_US (messages) - - - - - {0} and {1} - - - {0} and {1} + Zip code diff --git a/src/test/resources/translations/otherdomain.xlf b/src/test/resources/translations/payment.xlf similarity index 71% rename from src/test/resources/translations/otherdomain.xlf rename to src/test/resources/translations/payment.xlf index ee6164e..746764f 100644 --- a/src/test/resources/translations/otherdomain.xlf +++ b/src/test/resources/translations/payment.xlf @@ -6,12 +6,12 @@ source-language="en" target-language="en"> - + - Hello EN (otherdomain) + Expiry date - Other Hello EN (otherdomain) + Expiry date diff --git a/src/test/resources/translations/otherdomain_de.xlf b/src/test/resources/translations/payment_de.xlf similarity index 72% rename from src/test/resources/translations/otherdomain_de.xlf rename to src/test/resources/translations/payment_de.xlf index 5de1412..d65b7e8 100644 --- a/src/test/resources/translations/otherdomain_de.xlf +++ b/src/test/resources/translations/payment_de.xlf @@ -6,13 +6,12 @@ source-language="en" target-language="de"> - + - - Hello EN (otherdomain) + Expiry date - Hallo DE (otherdomain) + Ablaufdatum diff --git a/src/test/resources/translations_de/messages_de.xliff b/src/test/resources/translations_de/messages_de.xliff index f5786d4..975d8f4 100644 --- a/src/test/resources/translations_de/messages_de.xliff +++ b/src/test/resources/translations_de/messages_de.xliff @@ -6,6 +6,14 @@ source-language="en" target-language="de"> + + + Postcode + + + Postleitzahl + + diff --git a/src/test/resources/translations_de/otherdomain_de.xlf b/src/test/resources/translations_de/payment_de.xlf similarity index 53% rename from src/test/resources/translations_de/otherdomain_de.xlf rename to src/test/resources/translations_de/payment_de.xlf index f5786d4..99648be 100644 --- a/src/test/resources/translations_de/otherdomain_de.xlf +++ b/src/test/resources/translations_de/payment_de.xlf @@ -6,6 +6,14 @@ source-language="en" target-language="de"> + + + Expiry date + + + Ablaufdatum + + diff --git a/src/test/resources/translations_en/messages.xliff b/src/test/resources/translations_en/messages.xliff index 3aa0b87..b42b01c 100644 --- a/src/test/resources/translations_en/messages.xliff +++ b/src/test/resources/translations_en/messages.xliff @@ -6,6 +6,14 @@ source-language="en" target-language="en"> + + + Postcode + + + Postcode + + diff --git a/src/test/resources/translations_en/otherdomain.xlf b/src/test/resources/translations_en/payment.xlf similarity index 53% rename from src/test/resources/translations_en/otherdomain.xlf rename to src/test/resources/translations_en/payment.xlf index 3aa0b87..746764f 100644 --- a/src/test/resources/translations_en/otherdomain.xlf +++ b/src/test/resources/translations_en/payment.xlf @@ -6,6 +6,14 @@ source-language="en" target-language="en"> + + + Expiry date + + + Expiry date + + diff --git a/src/test/resources/translations_en_US/messages_en_US.xliff b/src/test/resources/translations_en_US/messages_en_US.xliff index 3aa0b87..76d28b2 100644 --- a/src/test/resources/translations_en_US/messages_en_US.xliff +++ b/src/test/resources/translations_en_US/messages_en_US.xliff @@ -4,7 +4,7 @@ + target-language="en-US">