Online translation (#241)

* Online translation added to Developer panel settings

* Added special characters conversion on file import and export for online translations

* fix: Parse text nodes separately

* fix: broken js on page prevents working developer panel

* fix: workaround for online translations using freemarker template models

* fix: safe way to convert array of objects to array of strings

* fix: convert char codes on read/write property files

* refact: corrected constant names
This commit is contained in:
Georgy Litvinov 2022-04-07 16:21:49 +02:00 committed by GitHub
parent 67b4df3c0b
commit bbd714ceb9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 780 additions and 9 deletions

View file

@ -10,6 +10,9 @@ import java.util.ResourceBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
/**
* A wrapper for a ResourceBundle that will not throw an exception, no matter
* what string you request.
@ -20,7 +23,9 @@ import org.apache.commons.logging.LogFactory;
*/
public class I18nBundle {
private static final Log log = LogFactory.getLog(I18nBundle.class);
private static final String START_SEP = "\u25a4";
private static final String END_SEP = "\u25a5";
public static final String INT_SEP = "\u25a6";
private static final String MESSAGE_BUNDLE_NOT_FOUND = "Text bundle ''{0}'' not found.";
private static final String MESSAGE_KEY_NOT_FOUND = "Text bundle ''{0}'' has no text for ''{1}''";
@ -75,13 +80,27 @@ public class I18nBundle {
key);
log.warn(message);
textString = "ERROR: " + message;
}
String result = formatString(textString, parameters);
}
String message = formatString(textString, parameters);
if (i18nLogger != null) {
i18nLogger.log(bundleName, key, parameters, textString, result);
i18nLogger.log(bundleName, key, parameters, textString, message);
}
return result;
if (isNeedExportInfo()) {
String separatedArgs = "";
for (int i = 0; i < parameters.length; i++) {
separatedArgs += parameters[i] + INT_SEP;
}
return START_SEP + key + INT_SEP + textString + INT_SEP + separatedArgs + message + END_SEP;
} else {
return message;
}
}
private static boolean isNeedExportInfo() {
return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
}
private static String formatString(String textString, Object... parameters) {

View file

@ -8,6 +8,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.i18n.I18nBundle;
import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
@ -65,7 +68,11 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
.get(i));
}
try {
return MessageFormat.format(textString, unwrappedArgs);
if(isOnlineTranslationsEnabled()) {
return getOnlineTranslationsFormattedMessage(textString, unwrappedArgs);
} else {
return MessageFormat.format(textString, unwrappedArgs);
}
} catch (Exception e) {
String message = "Can't format '" + key + "' from bundle '"
+ bundleName + "', wrong argument types: " + args
@ -75,5 +82,40 @@ public class I18nStringTemplateModel implements TemplateMethodModelEx,
}
}
}
/**
* Splits preProcessed string, formats message with arguments, lists arguments before message
* and combines preProcessed string back to be used with online translations.
* Substitutes arguments in message which is a part of preProcessed string
* @param preProcessed String "startSep + key + intSep + textString + intSep + message + endSep"
* @param arguments that should be listed before message and substituted in the message itself
* @return
*/
private String getOnlineTranslationsFormattedMessage(String preProcessed, Object[] args) {
String[] parts = preProcessed.split(I18nBundle.INT_SEP);
final int messageIndex = parts.length -1;
String message = MessageFormat.format(parts[messageIndex], args);
String[] arguments = convertToArrayOfStrings(args);
parts[messageIndex] = "";
String result = String.join(I18nBundle.INT_SEP, parts) +
String.join(I18nBundle.INT_SEP, arguments) +
I18nBundle.INT_SEP + message ;
return result;
}
private String[] convertToArrayOfStrings(Object[] args) {
String[] result = new String[args.length];
for (int i = 0; i < result.length; i++)
if (args[i] != null) {
result[i] = args[i].toString();
} else {
result[i] = "";
}
return result;
}
private static boolean isOnlineTranslationsEnabled() {
return DeveloperSettings.getInstance().getBoolean(Key.I18N_ONLINE_TRANSLATION);
}
}

View file

@ -43,7 +43,10 @@ public enum Key {
* Load language property files every time they are requested.
*/
I18N_DEFEAT_CACHE("developer.i18n.defeatCache", true),
/**
* Enable online translations.
*/
I18N_ONLINE_TRANSLATION("developer.i18n.onlineTranslation", true),
/**
* Enable the I18nLogger to log each string request.
*/