Skip to content

Commit

Permalink
feat: add the 'export_quotes' support for JavaScript files (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrii-bodnar committed Aug 29, 2023
1 parent 08898c5 commit e6c1b08
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@
import com.crowdin.client.sourcefiles.model.Branch;
import com.crowdin.client.sourcefiles.model.ExportOptions;
import com.crowdin.client.sourcefiles.model.FileInfo;
import com.crowdin.client.sourcefiles.model.GeneralFileExportOptions;
import com.crowdin.client.sourcefiles.model.ImportOptions;
import com.crowdin.client.sourcefiles.model.OtherFileImportOptions;
import com.crowdin.client.sourcefiles.model.PropertyFileExportOptions;
import com.crowdin.client.sourcefiles.model.SpreadsheetFileImportOptions;
import com.crowdin.client.sourcefiles.model.JavaScriptFileExportOptions;
import com.crowdin.client.sourcefiles.model.UpdateFileRequest;
import com.crowdin.client.sourcefiles.model.XmlFileImportOptions;
import org.apache.commons.io.FilenameUtils;
Expand All @@ -53,6 +55,8 @@
import static com.crowdin.cli.utils.console.ExecutionStatus.OK;
import static com.crowdin.cli.utils.console.ExecutionStatus.SKIPPED;
import static com.crowdin.cli.utils.console.ExecutionStatus.WARNING;
import static com.crowdin.client.sourcefiles.model.ExportQuotes.SINGLE;
import static com.crowdin.client.sourcefiles.model.ExportQuotes.DOUBLE;

class UploadSourcesAction implements NewAction<PropertiesWithFiles, ProjectClient> {

Expand Down Expand Up @@ -350,21 +354,40 @@ private boolean isXml(java.io.File file) {
}

private ExportOptions buildExportOptions(java.io.File sourceFile, FileBean fileBean, String basePath) {
PropertyFileExportOptions exportOptions = new PropertyFileExportOptions();
String exportPattern = TranslationsUtils.replaceDoubleAsterisk(
fileBean.getSource(),
fileBean.getTranslation(),
StringUtils.removeStart(sourceFile.getAbsolutePath(), basePath)
);

exportPattern = StringUtils.replacePattern(exportPattern, "[\\\\/]+", "/");
exportOptions.setExportPattern(exportPattern);
exportOptions.setEscapeQuotes(fileBean.getEscapeQuotes());
if (fileBean.getEscapeSpecialCharacters() != null) {
exportOptions.setEscapeSpecialCharacters(fileBean.getEscapeSpecialCharacters());
} else if (SourcesUtils.isFileProperties(sourceFile)) {

if (SourcesUtils.isFileProperties(sourceFile)) {
PropertyFileExportOptions exportOptions = new PropertyFileExportOptions();
exportOptions.setExportPattern(exportPattern);
exportOptions.setEscapeQuotes(fileBean.getEscapeQuotes());
exportOptions.setEscapeSpecialCharacters(1);

if (fileBean.getEscapeSpecialCharacters() != null) {
exportOptions.setEscapeSpecialCharacters(fileBean.getEscapeSpecialCharacters());
}

return exportOptions;
} else if (SourcesUtils.isFileJavaScript(sourceFile)) {
JavaScriptFileExportOptions exportOptions = new JavaScriptFileExportOptions();
exportOptions.setExportPattern(exportPattern);

if (fileBean.getExportQuotes() != null) {
exportOptions.setExportQuotes(fileBean.getExportQuotes().equals("double") ? DOUBLE : SINGLE);
}

return exportOptions;
} else {
GeneralFileExportOptions exportOptions = new GeneralFileExportOptions();
exportOptions.setExportPattern(exportPattern);

return exportOptions;
}
return exportOptions;
}

private Branch getOrCreateBranch(Outputter out, String branchName, ProjectClient client, CrowdinProjectFull project) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,8 @@ public static String getCommonPath(List<String> sources, String basePath) {
public static boolean isFileProperties(File source) {
return FilenameUtils.isExtension(source.getName(), "properties");
}

public static boolean isFileJavaScript(File source) {
return FilenameUtils.isExtension(source.getName(), "js");
}
}
64 changes: 40 additions & 24 deletions src/main/java/com/crowdin/cli/properties/FileBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static com.crowdin.cli.properties.PropertiesBuilder.DEST;
import static com.crowdin.cli.properties.PropertiesBuilder.ESCAPE_QUOTES;
import static com.crowdin.cli.properties.PropertiesBuilder.ESCAPE_SPECIAL_CHARACTERS;
import static com.crowdin.cli.properties.PropertiesBuilder.EXPORT_QUOTES;
import static com.crowdin.cli.properties.PropertiesBuilder.EXCLUDED_TARGET_LANGUAGES;
import static com.crowdin.cli.properties.PropertiesBuilder.EXPORT_APPROVED_ONLY;
import static com.crowdin.cli.properties.PropertiesBuilder.FIRST_LINE_CONTAINS_HEADER;
Expand Down Expand Up @@ -60,6 +61,7 @@ public class FileBean {
private Boolean contentSegmentation;
private Integer escapeQuotes;
private Integer escapeSpecialCharacters;
private String exportQuotes;
private Map<String, String> translationReplace;
private Boolean skipTranslatedOnly;
private Boolean skipUntranslatedFiles;
Expand All @@ -79,31 +81,33 @@ private FileBeanConfigurator() {
@Override
public FileBean buildFromMap(Map<String, Object> map) {
FileBean fileBean = new FileBean();
PropertiesBuilder.setPropertyIfExists(fileBean::setSource, map, SOURCE, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setDest, map, DEST, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setType, map, TYPE, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslation, map, TRANSLATION, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setUpdateOption, map, UPDATE_OPTION, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setScheme, map, SCHEME, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setIgnore, map, IGNORE, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslatableElements, map, TRANSLATABLE_ELEMENTS, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setLanguagesMapping, map, LANGUAGES_MAPPING, Map.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslationReplace, map, TRANSLATION_REPLACE, Map.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setEscapeQuotes, map, ESCAPE_QUOTES, Integer.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setEscapeSpecialCharacters, map, ESCAPE_SPECIAL_CHARACTERS, Integer.class);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setFirstLineContainsHeader, map, FIRST_LINE_CONTAINS_HEADER);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setTranslateAttributes, map, TRANSLATE_ATTRIBUTES);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setTranslateContent, map, TRANSLATE_CONTENT);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setContentSegmentation, map, CONTENT_SEGMENTATION);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setMultilingualSpreadsheet, map, MULTILINGUAL_SPREADSHEET);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setSkipTranslatedOnly, map, SKIP_UNTRANSLATED_STRINGS);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setSkipUntranslatedFiles, map, SKIP_UNTRANSLATED_FILES);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setExportApprovedOnly, map, EXPORT_APPROVED_ONLY);
PropertiesBuilder.setPropertyIfExists(fileBean::setSource, map, SOURCE, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setDest, map, DEST, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setType, map, TYPE, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslation, map, TRANSLATION, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setUpdateOption, map, UPDATE_OPTION, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setScheme, map, SCHEME, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setIgnore, map, IGNORE, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslatableElements, map, TRANSLATABLE_ELEMENTS, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setLanguagesMapping, map, LANGUAGES_MAPPING, Map.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setTranslationReplace, map, TRANSLATION_REPLACE, Map.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setEscapeQuotes, map, ESCAPE_QUOTES, Integer.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setEscapeSpecialCharacters, map, ESCAPE_SPECIAL_CHARACTERS, Integer.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setExportQuotes, map, EXPORT_QUOTES, String.class);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setFirstLineContainsHeader, map, FIRST_LINE_CONTAINS_HEADER);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setTranslateAttributes, map, TRANSLATE_ATTRIBUTES);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setTranslateContent, map, TRANSLATE_CONTENT);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setContentSegmentation, map, CONTENT_SEGMENTATION);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setMultilingualSpreadsheet, map, MULTILINGUAL_SPREADSHEET);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setSkipTranslatedOnly, map, SKIP_UNTRANSLATED_STRINGS);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setSkipUntranslatedFiles, map, SKIP_UNTRANSLATED_FILES);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setExportApprovedOnly, map, EXPORT_APPROVED_ONLY);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setExportStringsThatPassedWorkflow, map, EXPORT_STRINGS_THAT_PASSED_WORKFLOW);
PropertiesBuilder.setPropertyIfExists(fileBean::setLabels, map, LABELS, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setExcludedTargetLanguages, map, EXCLUDED_TARGET_LANGUAGES, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setCustomSegmentation, map, CUSTOM_SEGMENTATION, String.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setLabels, map, LABELS, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setExcludedTargetLanguages, map, EXCLUDED_TARGET_LANGUAGES, List.class);
PropertiesBuilder.setPropertyIfExists(fileBean::setCustomSegmentation, map, CUSTOM_SEGMENTATION, String.class);
PropertiesBuilder.setBooleanPropertyIfExists(fileBean::setImportTranslations, map, IMPORT_TRANSLATIONS);

return fileBean;
}

Expand All @@ -123,7 +127,6 @@ public void populateWithDefaultValues(FileBean bean) {
}
}


//Ignore
if (bean.getIgnore() != null && !bean.getIgnore().isEmpty()) {
List<String> ignores = new ArrayList<>();
Expand Down Expand Up @@ -164,18 +167,22 @@ public void populateWithDefaultValues(FileBean bean) {
@Override
public List<String> checkProperties(FileBean bean) {
List<String> errors = new ArrayList<>();

if (StringUtils.isEmpty(bean.getSource())) {
errors.add(RESOURCE_BUNDLE.getString("error.config.empty_source_section"));
}

if (StringUtils.isEmpty(bean.getTranslation())) {
errors.add(RESOURCE_BUNDLE.getString("error.config.empty_translation_section"));
} else {
if (!checkForDoubleAsterisks(bean.getSource(), bean.getTranslation())) {
errors.add(RESOURCE_BUNDLE.getString("error.config.double_asterisk"));
}

if (!PlaceholderUtil.containsLangPlaceholders(bean.getTranslation()) && bean.getScheme() == null) {
errors.add(RESOURCE_BUNDLE.getString("error.config.translation_has_no_language_placeholders"));
}

if (hasRelativePaths(bean.getTranslation())) {
errors.add(RESOURCE_BUNDLE.getString("error.config.translation_contains_relative_paths"));
}
Expand All @@ -185,22 +192,31 @@ public List<String> checkProperties(FileBean bean) {
if (updateOption != null && !(updateOption.equals("update_as_unapproved") || updateOption.equals("update_without_changes"))) {
errors.add(RESOURCE_BUNDLE.getString("error.config.update_option"));
}

Integer escQuotes = bean.getEscapeQuotes();
if (escQuotes != null && (escQuotes < 0 || escQuotes > 3)) {
errors.add(RESOURCE_BUNDLE.getString("error.config.escape_quotes"));
}

Integer escSpecialCharacters = bean.getEscapeSpecialCharacters();
if (escSpecialCharacters != null && (escSpecialCharacters < 0 || escSpecialCharacters > 1)) {
errors.add(RESOURCE_BUNDLE.getString("error.config.escape_special_characters"));
}

String exportQuotes = bean.getExportQuotes();
if (exportQuotes != null && !(exportQuotes.equals("single") || exportQuotes.equals("double"))) {
errors.add(RESOURCE_BUNDLE.getString("error.config.export_quotes"));
}

if (StringUtils.isNotEmpty(bean.getDest()) && !checkDest(bean.getDest(), bean.getSource())) {
errors.add(RESOURCE_BUNDLE.getString("error.dest_and_pattern_in_source"));
}

if (bean.getSkipTranslatedOnly() != null && bean.getSkipUntranslatedFiles() != null
&& bean.getSkipTranslatedOnly() && bean.getSkipUntranslatedFiles()) {
errors.add(RESOURCE_BUNDLE.getString("error.skip_untranslated_both_strings_and_files"));
}

return errors;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public abstract class PropertiesBuilder<T extends Properties, P extends Params>

public static final String ESCAPE_SPECIAL_CHARACTERS = "escape_special_characters";

public static final String EXPORT_QUOTES = "export_quotes";

public static final String MULTILINGUAL_SPREADSHEET = "multilingual_spreadsheet";

public static final String SCHEME = "scheme";
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/messages/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ error.config.translation_contains_relative_paths=The 'translation' parameter can
error.config.update_option=Configuration file contains unexpected 'update_option' value. The expected values are 'update_as_unapproved' or 'update_without_changes'
error.config.escape_quotes=Acceptable values for 'escape_quotes' are: 0, 1, 2, 3. Default is 3. Read more about 'escape_quotes': https://developer.crowdin.com/configuration-file/#escape-quotes-options-for-properties-file-format
error.config.escape_special_characters=Acceptable values for 'escape_special_characters' are: 0 and 1. Default is 1. Read more about 'escape_special_characters': https://developer.crowdin.com/configuration-file/#escape-quotes-options-for-properties-file-format
error.config.export_quotes=Acceptable values for the 'export_quotes' are: 'single' and 'double'. Default is 'single'
error.config.params_xor_source_translation=Both the 'source' and the 'translation' must be specified in the parameters
error.config.params_dest='dest' must be specified with both 'source' and 'translation' parameters
error.config.target_has_no_name=Required target 'name' field is missing in the configuration file
Expand Down
Loading

0 comments on commit e6c1b08

Please sign in to comment.