Skip to content

Commit

Permalink
Merge pull request #1737 from BladeRunnerJS/1736/fix-i18n-csv-encoding
Browse files Browse the repository at this point in the history
fixes 1736. ensure check-i18n command outputs a utf-8 file to support…
  • Loading branch information
thecapdan authored Sep 23, 2016
2 parents ba3e1c0 + eb4209e commit 5efbe5d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
throw new Error("No definition for module " + id + " has been loaded.");
}

// For closer spec compliance we should define id as a nonconfigurable, nonwritable
// For closer spec compliance, we should define id as a nonconfigurable, nonwritable
// property, but this at least works OK in non-es5 browsers (like ie8).
var module = { id: id, exports: new ModuleExports() };
this.incompleteExports[id] = module;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.bladerunnerjs.plugin.checki18n;

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -19,6 +21,7 @@

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.io.FileUtils;
import org.bladerunnerjs.api.App;
import org.bladerunnerjs.api.Aspect;
import org.bladerunnerjs.api.Asset;
Expand Down Expand Up @@ -48,13 +51,13 @@
import org.bladerunnerjs.api.logging.Logger;

public class CheckI18nCommand extends JSAPArgsParsingCommandPlugin {

public class Messages {
public static final String APP_CHECK_I18N_CONSOLE_MSG = "I18N tokens for the app '%s' available at '%s'";
public static final String APP_DOES_NOT_EXIST_EXCEPTION = "The app '%s' does not exist";
public static final String NO_LOCALE_FOR_APP = "The app specified does not contain a default locale";
}

private BRJS brjs;
private Logger logger;
private String locale;
Expand All @@ -69,7 +72,7 @@ public class Messages {
public String getCommandName() {
return "check-i18n";
}

@Override
protected void configureArgsParser(JSAP argsParser) throws JSAPException {
argsParser.registerParameter(new UnflaggedOption("app-name").setRequired(true).setHelp("the application to search for missing translations"));
Expand All @@ -85,49 +88,49 @@ public String getCommandDescription() {
protected int doCommand(JSAPResult parsedArgs) throws CommandArgumentsException, CommandOperationException {
String appName = parsedArgs.getString("app-name");
locale = parsedArgs.getString("locale");

listMissingTokens(appName);
generateAllTranslationsCSV(appName);
return missingTokensExist ? -1 : 0;
}

private void listMissingTokens(String appName) throws CommandArgumentsException {
App app = brjs.app(appName);

try {
appLocales = app.appConf().getLocales();
} catch (ConfigException e) {
e.printStackTrace();
}

if(!app.dirExists())
throw new CommandArgumentsException( String.format(Messages.APP_DOES_NOT_EXIST_EXCEPTION, appName), this );

findMissingTranslationsForAppWithLocale(app);

for (Entry<String, Set<String>> tokensList : missingTokensMap.entrySet()) {
logMissingLocalesToConsole(appName, tokensList.getKey(), tokensList);
logMissingLocalesToConsole(appName, tokensList.getKey(), tokensList);
}
}

private void generateAllTranslationsCSV(String appName) {
logger.println("\ngenerating CSV\n");

TreeSet<String> localeNames = new TreeSet<String>();
for(Locale locale : appLocales ){
localeNames.add(locale.getLanguageCode());
}

List<String> headings = new ArrayList<String>();
headings.add("Token");
for(String localeName : localeNames){
headings.add(localeName);
}
headings.add("IsUsed");

List<List<String>> rows = new ArrayList<List<String>>();
rows.add(headings);

for(Entry<String, HashMap<String, String>> translationMap : allExistingTokens.entrySet()){
List<String> newEntry = new ArrayList<String>();
newEntry.add(translationMap.getKey());
Expand All @@ -139,22 +142,37 @@ private void generateAllTranslationsCSV(String appName) {
newEntry.add(translationMap.getValue().get("used"));
rows.add(newEntry);
}

File file = brjs.storageFile(this.getClass().getSimpleName(), appName + "-tokens.csv" );
file.getParentFile().mkdirs();

try(Writer writer = new BufferedWriter(new FileWriter(file));) {

try{
Writer writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file), "UTF-8"));

writer.append("** the 'IsUsed' column only relates to tokens identified in their entirety and"
+ " will not include tokens which are concatenated e.g. i18n('a.token.' + value);\n");
for(List<String> row : rows){
writer.append(StringUtils.join(row, ",")+"\n");
}
} catch (IOException e) {
}
writer.flush();
writer.close();

String content = FileUtils.readFileToString(file, "UTF-8");
FileUtils.write(file, content, "UTF-8");
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (IOException e){
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
logger.println(Messages.APP_CHECK_I18N_CONSOLE_MSG, appName, file.getAbsolutePath());
}
logger.println(Messages.APP_CHECK_I18N_CONSOLE_MSG, appName, file.getAbsolutePath());
}

private void logMissingLocalesToConsole(String appName, String localeToBeChecked, Entry<String, Set<String>> tokensList) {
String missingTokensMessage = tokensList.getValue().size() == 0 ? " has no missing translations" : " has no translations defined for the following tokens:";
String firstLogLine = "\n" + "For the locale " + tokensList.getKey() + ", " + appName + missingTokensMessage + "\n";
Expand All @@ -168,7 +186,7 @@ private void findMissingTranslationsForAppWithLocale(App app) {
for(Aspect aspect : app.aspects()) {
logger.println("checking " + aspect.getName() + " aspect");
checkMissingLocalsForBundlableNode(aspect);

checkMissingLocales(aspect);
}
for(Bladeset bladeset : app.bladesets()) {
Expand Down Expand Up @@ -215,7 +233,7 @@ private void checkBundletForMissingTokens(BundleSet bundleSet) {
}
checkAssetForMissingTokens(bundleSet, content, I18N_HTML_XML_TOKEN_PATTERN);
}

List<SourceModule> sourcceModules = bundleSet.sourceModules();
for(SourceModule sourceModule : sourcceModules){
String srcContent = null;
Expand Down Expand Up @@ -248,7 +266,7 @@ private void matchTokensForLocale(String content, Pattern pattern, Map<String, S
while (i18nTokenMatcher.find()) {
Boolean tokenIsNotComplete = false;
Boolean propertiesFileContainPartialMatch = false;

if(i18nTokenMatcher.groupCount() > 1){
tokenIsNotComplete = i18nTokenMatcher.group(2) != null && i18nTokenMatcher.group(2).indexOf('+') != -1;
propertiesFileContainPartialMatch = mapContainsPartialToken(propertiesMap, i18nTokenMatcher.group(1)) && tokenIsNotComplete;
Expand All @@ -271,7 +289,7 @@ else if (keyReplacement != null) {
else{
missingTokensMap.get(localeCode).addAll(missingTokens);
}

addUnusedTokensToAllTokensMap(propertiesMap, localeCode);
}

Expand All @@ -280,7 +298,7 @@ private void addUnusedTokensToAllTokensMap(Map<String, String> propertiesMap, St
{
String i18nKey = i18nPair.getKey();
String translation = i18nPair.getValue();

if(!allExistingTokens.containsKey(i18nKey)){
populateAllTokensMap(localeCode, i18nKey, translation, false);
}
Expand All @@ -299,10 +317,10 @@ private void populateAllTokensMap(String localeCode, String i18nKey, String keyR

private boolean mapContainsPartialToken(Map<String, String> propertiesMap, String partialToken) {
for(Entry<String, String> entry : propertiesMap.entrySet()) {
String i18nToken = entry.getKey();
if(i18nToken.contains(partialToken))
return true;
}
String i18nToken = entry.getKey();
if(i18nToken.contains(partialToken))
return true;
}
return false;
}

Expand Down

0 comments on commit 5efbe5d

Please sign in to comment.