diff --git a/src/main/java/com/crowdin/cli/commands/Actions.java b/src/main/java/com/crowdin/cli/commands/Actions.java index 3c00e9fc..ed1bbb3d 100644 --- a/src/main/java/com/crowdin/cli/commands/Actions.java +++ b/src/main/java/com/crowdin/cli/commands/Actions.java @@ -109,7 +109,7 @@ NewAction taskAdd( NewAction checkNewVersion(); NewAction preTranslate( - List languageIds, List files, Method method, Long engineId, String branchName, AutoApproveOption autoApproveOption, Boolean duplicateTranslations, + List languageIds, List files, Method method, Long engineId, String branchName, String directory, AutoApproveOption autoApproveOption, Boolean duplicateTranslations, Boolean translateUntranslatedOnly, Boolean translateWithPerfectMatchOnly, boolean noProgress, boolean plainView, List labelNames, Long aiPrompt); NewAction branchAdd(String name, String title, String exportPattern, Priority priority, boolean plainView); diff --git a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java index 6b4141db..f77e8c8f 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java +++ b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java @@ -222,10 +222,10 @@ public NewAction checkNewVersion() { @Override public NewAction preTranslate( - List languageIds, List files, Method method, Long engineId, String branchName, AutoApproveOption autoApproveOption, Boolean duplicateTranslations, - Boolean translateUntranslatedOnly, Boolean translateWithPerfectMatchOnly, boolean noProgress, boolean plainView, List labelNames, Long aiPrompt + List languageIds, List files, Method method, Long engineId, String branchName, String directory, AutoApproveOption autoApproveOption, + Boolean duplicateTranslations, Boolean translateUntranslatedOnly, Boolean translateWithPerfectMatchOnly, boolean noProgress, boolean plainView, List labelNames, Long aiPrompt ) { - return new PreTranslateAction(languageIds, files, method, engineId, branchName, autoApproveOption, duplicateTranslations, + return new PreTranslateAction(languageIds, files, method, engineId, branchName, directory, autoApproveOption, duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, noProgress, plainView, labelNames, aiPrompt); } diff --git a/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java b/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java index 0222b873..e6610d50 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java @@ -18,6 +18,7 @@ import com.crowdin.client.sourcefiles.model.FileInfo; import com.crowdin.client.translations.model.*; import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; import java.util.*; import java.util.stream.Collectors; @@ -33,6 +34,7 @@ class PreTranslateAction implements NewAction labelIds = this.prepareLabelIds(out, client); if (isStringsBasedProject) { - if (files != null && !files.isEmpty()) { + if ((files != null && !files.isEmpty()) || directory != null) { throw new ExitCodeExceptionMapper.ValidationException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); } Branch branch = project.findBranchByName(branchName) @@ -64,8 +66,8 @@ public void act(Outputter out, PropertiesWithFiles properties, ProjectClient cli return; } - if (files == null || files.isEmpty()) { - throw new ExitCodeExceptionMapper.ValidationException(RESOURCE_BUNDLE.getString("error.file_required")); + if ((files == null || files.isEmpty()) && StringUtils.isEmpty(directory)) { + throw new ExitCodeExceptionMapper.ValidationException(RESOURCE_BUNDLE.getString("error.file_or_directory_required")); } Optional branch = Optional.ofNullable(branchName).flatMap(project::findBranchByName); @@ -75,26 +77,36 @@ public void act(Outputter out, PropertiesWithFiles properties, ProjectClient cli } List fileInfos = project - .getFileInfos() - .stream().filter(f -> !branch.isPresent() || branch.get().getId().equals(f.getBranchId())) - .collect(Collectors.toList()); + .getFileInfos() + .stream() + .filter(f -> (branch.isEmpty() && f.getBranchId() == null) + || (branch.isPresent() && branch.get().getId().equals(f.getBranchId()))) + .collect(Collectors.toList()); Map paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), fileInfos); boolean containsError = false; List fileIds = new ArrayList<>(); - for (String file : files) { - if (!paths.containsKey(file)) { - if (files.size() > 1) { - containsError = true; - out.println(WARNING.withIcon(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file))); - continue; - } else { - throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file)); + if ((files != null && !files.isEmpty())) { + for (String file : files) { + if (!paths.containsKey(file)) { + if (files.size() > 1) { + containsError = true; + out.println(WARNING.withIcon(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file))); + continue; + } else { + throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file)); + } + } + Long fileId = paths.get(file).getId(); + fileIds.add(fileId); + } + } else if (!StringUtils.isEmpty(directory)) { + for (Map.Entry entry : paths.entrySet()) { + if (entry.getKey().startsWith(directory)) { + fileIds.add(entry.getValue().getId()); } } - Long fileId = paths.get(file).getId(); - fileIds.add(fileId); } if (fileIds.isEmpty()) { diff --git a/src/main/java/com/crowdin/cli/commands/picocli/PreTranslateSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/PreTranslateSubcommand.java index f1fbb6ed..09b688ad 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/PreTranslateSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/PreTranslateSubcommand.java @@ -39,6 +39,9 @@ public class PreTranslateSubcommand extends ActCommandWithFiles { @CommandLine.Option(names = {"-b", "--branch"}, paramLabel = "...", descriptionKey = "branch", order = -2) protected String branch; + @CommandLine.Option(names = {"--directory"}, paramLabel = "...", order = -2, descriptionKey = "crowdin.pre-translate.directory-path") + protected String directory; + @CommandLine.Option(names = {"--auto-approve-option"}, descriptionKey = "crowdin.pre-translate.auto-approve-option", paramLabel = "...", order = -2) protected String autoApproveOption; @@ -80,6 +83,7 @@ protected NewAction getAction(Actions action method, engineId, branch, + directory, autoApproveOptionWrapper.get(autoApproveOption), duplicateTranslations, translateUntranslatedOnly, @@ -94,6 +98,9 @@ protected NewAction getAction(Actions action @Override protected List checkOptions() { List errors = new ArrayList<>(); + if (directory != null && files != null && !files.isEmpty()) { + errors.add(RESOURCE_BUNDLE.getString("error.pre_translate.directory_or_file_only")); + } if ((Method.MT == method) && (engineId == null)) { errors.add(RESOURCE_BUNDLE.getString("error.pre_translate.engine_id")); } @@ -122,6 +129,9 @@ protected List checkOptions() { files.set(i, normalizedFile); } } + if (directory != null) { + directory = StringUtils.removeStart(Utils.normalizePath(directory), Utils.PATH_SEPARATOR); + } return errors; } } diff --git a/src/main/resources/messages/messages.properties b/src/main/resources/messages/messages.properties index fc40f7c2..a1e9717a 100755 --- a/src/main/resources/messages/messages.properties +++ b/src/main/resources/messages/messages.properties @@ -372,6 +372,7 @@ crowdin.pre-translate.file=Path to the file in the Crowdin project. Can be speci crowdin.pre-translate.method=Defines pre-translation method. Supported values: mt, tm, ai crowdin.pre-translate.engine-id=Machine Translation engine Identifier crowdin.pre-translate.ai-prompt=AI Prompt Identifier. Required for 'ai' method +crowdin.pre-translate.directory-path=Path to the directory in Crowdin crowdin.pre-translate.auto-approve-option=Defines which translations added by TM pre-translation should be auto-approved. Supported values: all, except-auto-substituted, perfect-match-only. Default: none crowdin.pre-translate.duplicate-translations=Adds translations even if the same translation already exists crowdin.pre-translate.translate-untranslated-only=Applies pre-translation for untranslated strings only @@ -496,6 +497,7 @@ error.while_checking_base_path=Failed to check the base path. Try to run the app error.skip_untranslated_both_strings_and_files=You cannot skip strings and files at the same time. Please use one of these parameters instead. error.file_not_exists=Project doesn't contain the '%s' file error.file_required=The '--file' parameter is required for this type of project +error.file_or_directory_required=The '--file' or '--directory' parameter is required for this type of project error.dir_not_exists=Project doesn't contain the '%s' directory error.branch_not_exists=Project doesn't contain the '%s' branch error.source_string_no_edit=Specify some parameters to edit the string @@ -564,6 +566,7 @@ error.distribution.empty_bundle_ids=The '--bundle-id' value can not be empty for error.distribution.incorrect_file_command_usage=The '--file' is used only for the 'default' export mode error.distribution.incorrect_bundle_id_command_usage=The '--bundle-id' is used only for the 'bundle' export mode +error.pre_translate.directory_or_file_only=Either '--file' or '--directory' can be specified error.pre_translate.engine_id=Machine Translation should be used with the '--engine-id' parameter error.pre_translate.ai_prompt=AI should be used with the '--ai-prompt' parameter error.pre_translate.duplicate_translations='--duplicate-translations' only works with the TM pre-translation method diff --git a/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java b/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java index ca13ceb9..e8d9dc9e 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java @@ -127,6 +127,11 @@ public void testCheckNewVersion() { assertNotNull(actions.checkNewVersion()); } + @Test + void testPreTranslate() { + assertNotNull(actions.preTranslate(null, null, null, null, null, null, null, null, null, null,false, false, null, null)); + } + @Test void testScreenshotList() { assertNotNull(actions.screenshotList(null, false)); diff --git a/src/test/java/com/crowdin/cli/commands/actions/PreTranslateActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/PreTranslateActionTest.java new file mode 100644 index 00000000..321c4027 --- /dev/null +++ b/src/test/java/com/crowdin/cli/commands/actions/PreTranslateActionTest.java @@ -0,0 +1,169 @@ +package com.crowdin.cli.commands.actions; + +import com.crowdin.cli.client.CrowdinProjectFull; +import com.crowdin.cli.client.ProjectBuilder; +import com.crowdin.cli.client.ProjectClient; +import com.crowdin.cli.commands.Outputter; +import com.crowdin.cli.properties.NewPropertiesWithFilesUtilBuilder; +import com.crowdin.cli.properties.PropertiesWithFiles; +import com.crowdin.cli.properties.helper.FileHelperTest; +import com.crowdin.cli.properties.helper.TempProject; +import com.crowdin.cli.utils.Utils; +import com.crowdin.client.labels.model.Label; +import com.crowdin.client.projectsgroups.model.Type; +import com.crowdin.client.translations.model.ApplyPreTranslationRequest; +import com.crowdin.client.translations.model.ApplyPreTranslationStringsBasedRequest; +import com.crowdin.client.translations.model.PreTranslationStatus; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +class PreTranslateActionTest { + + private TempProject project; + + @BeforeEach + public void createProj() { + project = new TempProject(FileHelperTest.class); + } + + @AfterEach + public void deleteProj() { + project.delete(); + } + + @Test + public void testPreTranslate() { + String fileName = "first.po"; + String labelName = "label_1"; + String branchName = "main"; + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(project.getBasePath()); + PropertiesWithFiles pb = pbBuilder.build(); + ProjectBuilder projectBuilder = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile(fileName, "gettext", 101L, null, 81L) + .addBranches(81L, branchName); + CrowdinProjectFull crowdinProjectFull = projectBuilder.build(); + crowdinProjectFull.setType(Type.FILES_BASED); + + Label label1 = new Label() {{ + setId(91L); + setTitle(labelName); + }}; + List