-
다국어 서비스 시 .properties 파일 정리 용 유틸자바 ( Java )/유틸 ( Utility ) 2022. 1. 17. 22:15
파일 정리하던 중 올리는 거라 테스트는 따로 해보셔야 할 겁니다.
한국어를 여러 언어로 번역하여 테스트 할 때 .properties 파일에 여러 사람이 작업하다 보니 key-value 가 많이 섞이는 경우가 있어 한번에 중복키 등을 정리하여 .csv로 출력해주는 코드입니다.
빌드는 adopt-openjdk-11, 언어레벨 11로 테스트 하였습니다.
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.*; public class MessageExporterMain { public static String OUTPUT_FILE = "./out/export.csv"; // csv 파일 출력경로 // some export file like './export.csv' public static String RESOURCE_ROOT_FOLDER_PATH = "[여기는 .properties 파일이 모여있는 폴더 경로]"; // message~.properties root folder public static String DELIMITER = ","; // 변경하지 마세요. public static String FILENAME_FORMAT = "[.properties 파일 명 포맷 String.format() ]"; / ex) messages_%s.properties // .properties 파일명 형태 public static String[] LANGS = new String [] { "ko", "en" }; public static Map<String, Properties> LOAD_PROPS = new HashMap<>(); public static void main(String[] args) throws IOException { Path filePath = null; try { filePath = Files.write(Path.of(OUTPUT_FILE), new byte[0], StandardOpenOption.TRUNCATE_EXISTING); } catch (Exception e) { filePath = Files.write(Path.of(OUTPUT_FILE), new byte[0], StandardOpenOption.CREATE_NEW); } // 파일 출력 PrintWriter writer = new PrintWriter(filePath.toFile()); // 프로퍼티 파일 로딩 for(String lang : LANGS) { Path messageFilePath = Path.of(RESOURCE_ROOT_FOLDER_PATH, String.format(FILENAME_FORMAT, lang)); try ( InputStream is = new FileInputStream(messageFilePath.toFile()) ) { Properties prop = new Properties(); prop.load(is); LOAD_PROPS.put(lang, prop); } catch (IOException e) { e.printStackTrace(); } } // 메시지 프로퍼티 간 키, 값 비교하여 병합 Set<String> compareComplete = new HashSet<>(); Map<String, Map<String, String>> mergeLines = new HashMap<>(); for(Map.Entry<String, Properties> mainEntry : LOAD_PROPS.entrySet()) { String mainLang = mainEntry.getKey(); Properties mainProps = mainEntry.getValue(); Set<Object> mainKeySet = mainProps.keySet(); for(Map.Entry<String, Properties> targetEntry : LOAD_PROPS.entrySet()) { String targetLang = targetEntry.getKey(); Properties targetProps = targetEntry.getValue(); if ( Objects.equals(mainEntry.getKey(), targetEntry.getKey()) ) { continue; } if(compareComplete.contains(mainLang) && compareComplete.contains(targetLang)) { continue; } Set<Object> targetKeySet = targetProps.keySet(); Set<Object> mergeKeySet = new HashSet<>(mainKeySet); mergeKeySet.addAll(targetKeySet); mergeKeySet.stream() .map(String::valueOf) .forEach(key -> { String mainValue = mainProps.getProperty(key, ""); String targetValue = targetProps.getProperty(key, ""); Map<String, String> mergeLine = mergeLines.getOrDefault(key, new HashMap<>()); mergeLine.put(mainLang, mainValue); mergeLine.put(targetLang, targetValue); mergeLines.put(key, mergeLine); }); compareComplete.add(mainLang); compareComplete.add(targetLang); } } // print colum List<String> columns = new ArrayList<>() { @Override public boolean add(String s) { return super.add("\"" + s + "\""); } }; columns.add("key"); Collections.addAll(columns, LANGS); String columnLine = String.join(DELIMITER, columns); writer.println(columnLine); System.out.println(columnLine); // print row for( Map.Entry<String, Map<String, String>> entry : mergeLines.entrySet()) { String key = entry.getKey(); Map<String, String> value = entry.getValue(); List<String> lineFormatArgs = new ArrayList<>() { @Override public boolean add(String s) { return super.add("\"" + s + "\""); } }; lineFormatArgs.add(key); for(String lang : LANGS) { lineFormatArgs.add(value.getOrDefault(lang, "").replace("\\R", "")); } String line = String.join(DELIMITER, lineFormatArgs); System.out.println(line); writer.println(line); } writer.close(); } }