/*
* Copyright (C) 2013-2015 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
* Akvo FLOW is free software: you can redistribute it and modify it under the terms of
* the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
* either version 3 of the License or any later version.
*
* Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License included below for more details.
*
* The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
*/
package services;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
public class TranslationGenerator {
private static final Map<String, String> PATTERNS = new HashMap<String, String>();
private static final Pattern ANCHOR = Pattern.compile("<a.*?>.*?</a>");
private static final Pattern T_HELPER = Pattern.compile("\\{\\{t\\s\\_\\w+\\}\\}");
private static final Pattern BINDING = Pattern.compile(">\\{\\{.*?\\}\\}<");
private static final Pattern AKVO_ORG = Pattern.compile(">akvo.org</a>");
static {
PATTERNS.put("{{t ", "}}");
PATTERNS.put("{{tooltip ", "}}");
PATTERNS.put("promptBinding=\"Ember.STRINGS.", "\"");
PATTERNS.put("placeholderBinding=\"Ember.STRINGS.", "\"");
PATTERNS.put("String.loc('", "'");
PATTERNS.put("(t> ", ")");
}
private static final String[] EXTS = {
"handlebars", "js", "cljs"
};
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("<Dashboard> and <output> directories are required");
return;
}
final File sources = new File(args[0]);
final File output = new File(args[1]);
final Properties ui_strings = new Properties();
ui_strings.load(new FileInputStream(new File(output,
"/ui-strings.properties")));
final Map<String, String> trlKeys = new HashMap<String, String>();
final List<String> enValues = new ArrayList<String>();
for (File f : (List<File>) FileUtils.listFiles(sources, EXTS, true)) {
if (f.getAbsolutePath().contains("vendor")
|| f.getAbsolutePath().contains("plugins")
|| f.getAbsolutePath().contains("tests")) {
continue; // skipping
}
final List<String> lines = FileUtils.readLines(f, "UTF-8");
int ln = 1;
for (String line : lines) {
if (containsTranslatableKeys(line)) {
final List<String> keys = getKeys(line);
if (!keys.isEmpty()) {
for (String k : keys) {
if (trlKeys.containsKey(k)) {
continue; // skip
}
final String en = ui_strings.getProperty(k);
if (en == null) {
System.err.println("Translation key `"
+ k
+ "` not found in ui-strings.properties");
ui_strings.put(k, "");
}
trlKeys.put(k, (en == null ? "" : en));
if (en != null && !"".equals(en)
&& !enValues.contains(en)) {
enValues.add(en);
}
}
}
}
if (f.getAbsolutePath().endsWith(".handlebars") &&
containsMissingTranslation(line)) {
System.err.println("Check for missing translation in " + f.getName() + ":" + ln
+ " " + line);
}
ln++;
}
}
Collections.sort(enValues);
StringBuffer sb = new StringBuffer();
for (String val : enValues) {
sb.append(val.replaceAll(" ", "\\\\ ")).append(" = ").append(val)
.append("\n");
}
FileUtils.writeStringToFile(new File(output, "/en.properties"),
sb.toString(), "ISO-8859-1");
final List<String> tmp = new ArrayList<String>(trlKeys.keySet());
Collections.sort(tmp);
final StringBuffer uisource = new StringBuffer();
for (String ui : tmp) {
uisource.append(ui).append(" = ").append(trlKeys.get(ui))
.append("\n");
}
FileUtils.writeStringToFile(new File(output, "/ui-strings.properties"),
uisource.toString(), "ISO-8859-1");
}
private static boolean containsMissingTranslation(String line) {
final Matcher m = ANCHOR.matcher(line);
if (!m.find()) {
return false;
}
final Matcher m2 = T_HELPER.matcher(m.group());
final Matcher m3 = BINDING.matcher(m.group());
final Matcher m4 = AKVO_ORG.matcher(m.group()); // Hack to remove false positive
if (!m2.find() && !m3.find() && !m4.find()) {
return true;
}
return false;
}
private static boolean containsTranslatableKeys(String line) {
for (String pattern : PATTERNS.keySet()) {
if (line.contains(pattern)) {
return true;
}
}
return false;
}
private static List<String> getKeys(String line) {
if (!containsTranslatableKeys(line)) {
return Collections.emptyList();
}
final List<String> keys = new ArrayList<String>();
for (String pattern : PATTERNS.keySet()) {
keys.addAll(getKeysFromLine(line, pattern, PATTERNS.get(pattern)));
}
return keys;
}
private static List<String> getKeysFromLine(String line, String prefix,
String suffix) {
final List<String> keys = new ArrayList<String>();
int start = line.indexOf(prefix);
int end = -1;
if (start != -1) {
start += prefix.length();
end = line.indexOf(suffix, start);
}
while (start > 0 && end > 0) {
keys.add(line.substring(start, end));
start = line.indexOf(prefix, end + 1);
if (start == -1) {
break;
}
start = start + prefix.length();
end = line.indexOf(suffix, start);
}
return keys;
}
}