diff --git a/src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java b/src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java index fec159cec..fc40490ff 100644 --- a/src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java +++ b/src/test/java/org/springframework/samples/petclinic/system/I18nPropertiesSyncTest.java @@ -15,38 +15,19 @@ import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.fail; -/** - * This test ensures that there are no hard-coded strings without internationalization in - * any HTML files. Also ensures that a string is translated in every language to avoid - * partial translations. - * - * @author Anuj Ashok Potdar - */ public class I18nPropertiesSyncTest { private static final String I18N_DIR = "src/main/resources"; - private static final String BASE_NAME = "messages"; - public static final String PROPERTIES = ".properties"; - private static final Pattern HTML_TEXT_LITERAL = Pattern.compile(">([^<>{}]+)<"); - private static final Pattern BRACKET_ONLY = Pattern.compile("<[^>]*>\\s*[\\[\\]](?: )?\\s*]*>"); - private static final Pattern HAS_TH_TEXT_ATTRIBUTE = Pattern.compile("th:(u)?text\\s*=\\s*\"[^\"]+\""); @Test public void checkNonInternationalizedStrings() throws IOException { Path root = Paths.get("src/main"); - List files; - - try (Stream stream = Files.walk(root)) { - files = stream.filter(p -> p.toString().endsWith(".java") || p.toString().endsWith(".html")) - .filter(p -> !p.toString().contains("/test/")) - .filter(p -> !p.getFileName().toString().endsWith("Test.java")) - .toList(); - } + List files = getFiles(root); StringBuilder report = new StringBuilder(); @@ -55,24 +36,18 @@ public class I18nPropertiesSyncTest { for (int i = 0; i < lines.size(); i++) { String line = lines.get(i).trim(); - if (line.startsWith("//") || line.startsWith("@") || line.contains("log.") - || line.contains("System.out")) + if (isIgnoredLine(line) || !file.toString().endsWith(".html")) { continue; + } - if (file.toString().endsWith(".html")) { - boolean hasLiteralText = HTML_TEXT_LITERAL.matcher(line).find(); - boolean hasThTextAttribute = HAS_TH_TEXT_ATTRIBUTE.matcher(line).find(); - boolean isBracketOnly = BRACKET_ONLY.matcher(line).find(); - - if (hasLiteralText && !line.contains("#{") && !hasThTextAttribute && !isBracketOnly) { - report.append("HTML: ") - .append(file) - .append(" Line ") - .append(i + 1) - .append(": ") - .append(line) - .append("\n"); - } + if (isNonInternationalizedHtmlLine(line)) { + report.append("HTML: ") + .append(file) + .append(" Line ") + .append(i + 1) + .append(": ") + .append(line) + .append("\n"); } } } @@ -82,25 +57,29 @@ public class I18nPropertiesSyncTest { } } - @Test - public void checkI18nPropertyFilesAreInSync() throws IOException { - List propertyFiles; - try (Stream stream = Files.walk(Paths.get(I18N_DIR))) { - propertyFiles = stream.filter(p -> p.getFileName().toString().startsWith(BASE_NAME)) - .filter(p -> p.getFileName().toString().endsWith(PROPERTIES)) + private List getFiles(Path root) throws IOException { + try (Stream stream = Files.walk(root)) { + return stream.filter(p -> p.toString().endsWith(".java") || p.toString().endsWith(".html")) + .filter(p -> !p.toString().contains("/test/")) + .filter(p -> !p.getFileName().toString().endsWith("Test.java")) .toList(); } + } - Map localeToProps = new HashMap<>(); + private boolean isIgnoredLine(String line) { + return line.startsWith("//") || line.startsWith("@") || line.contains("log.") || line.contains("System.out"); + } - for (Path path : propertyFiles) { - Properties props = new Properties(); - try (var reader = Files.newBufferedReader(path)) { - props.load(reader); - localeToProps.put(path.getFileName().toString(), props); - } - } + private boolean isNonInternationalizedHtmlLine(String line) { + return HTML_TEXT_LITERAL.matcher(line).find() && !line.contains("#{") && + !HAS_TH_TEXT_ATTRIBUTE.matcher(line).find() && !BRACKET_ONLY.matcher(line).find(); + } + @Test + public void checkI18nPropertyFilesAreInSync() throws IOException { + List propertyFiles = getPropertyFiles(); + + Map localeToProps = loadProperties(propertyFiles); String baseFile = BASE_NAME + PROPERTIES; Properties baseProps = localeToProps.get(baseFile); if (baseProps == null) { @@ -113,10 +92,9 @@ public class I18nPropertiesSyncTest { for (Map.Entry entry : localeToProps.entrySet()) { String fileName = entry.getKey(); - // We use fallback logic to include english strings, hence messages_en is not - // populated. - if (fileName.equals(baseFile) || fileName.equals("messages_en.properties")) + if (fileName.equals(baseFile) || fileName.equals("messages_en.properties")) { continue; + } Properties props = entry.getValue(); Set missingKeys = new TreeSet<>(baseKeys); @@ -133,4 +111,24 @@ public class I18nPropertiesSyncTest { } } -} + private List getPropertyFiles() throws IOException { + try (Stream stream = Files.walk(Paths.get(I18N_DIR))) { + return stream.filter(p -> p.getFileName().toString().startsWith(BASE_NAME)) + .filter(p -> p.getFileName().toString().endsWith(PROPERTIES)) + .toList(); + } + } + + private Map loadProperties(List propertyFiles) throws IOException { + Map localeToProps = new HashMap<>(); + + for (Path path : propertyFiles) { + Properties props = new Properties(); + try (var reader = Files.newBufferedReader(path)) { + props.load(reader); + localeToProps.put(path.getFileName().toString(), props); + } + } + return localeToProps; + } +} \ No newline at end of file