From a6db4502d88f215967eb11e97e3e990b22f484b3 Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych <malutina.catya14@gmail.com> Date: Mon, 29 Jan 2024 09:50:12 +0200 Subject: [PATCH 1/5] feat: strings based project functionality --- .../cli/client/ClientDistribution.java | 10 +- .../cli/client/CrowdinClientDistribution.java | 24 +- .../cli/client/CrowdinProjectClient.java | 19 +- .../com/crowdin/cli/client/ProjectClient.java | 9 +- .../com/crowdin/cli/commands/Actions.java | 4 +- .../cli/commands/actions/CliActions.java | 8 +- .../actions/DistributionAddAction.java | 44 +++- .../actions/DistributionReleaseAction.java | 53 +++- .../commands/actions/PreTranslateAction.java | 86 ++++--- .../cli/commands/actions/StringAddAction.java | 26 +- .../commands/actions/StringListAction.java | 23 +- .../commands/actions/UploadSourcesAction.java | 115 ++++++--- .../actions/UploadTranslationsAction.java | 229 +++++++++++------- .../functionality/RequestBuilder.java | 39 ++- .../picocli/DistributionAddSubcommand.java | 4 - .../DistributionReleaseSubcommand.java | 6 +- .../commands/picocli/StringAddSubcommand.java | 5 +- .../cli/commands/actions/CliActionsTest.java | 4 +- .../actions/DistributionAddActionTest.java | 41 +++- .../DistributionReleaseActionTest.java | 43 +++- .../commands/actions/StringAddActionTest.java | 52 +++- .../actions/StringListActionTest.java | 33 ++- .../actions/UploadSourcesActionTest.java | 119 +++++++-- .../actions/UploadTranslationsActionTest.java | 63 ++++- .../DistributionAddSubcommandTest.java | 7 +- .../commands/picocli/PicocliTestUtils.java | 2 +- .../picocli/StringAddSubcommandTest.java | 4 +- 27 files changed, 801 insertions(+), 271 deletions(-) diff --git a/src/main/java/com/crowdin/cli/client/ClientDistribution.java b/src/main/java/com/crowdin/cli/client/ClientDistribution.java index 6e25a2aaf..59c66de8d 100644 --- a/src/main/java/com/crowdin/cli/client/ClientDistribution.java +++ b/src/main/java/com/crowdin/cli/client/ClientDistribution.java @@ -1,8 +1,6 @@ package com.crowdin.cli.client; -import com.crowdin.client.distributions.model.AddDistributionRequest; -import com.crowdin.client.distributions.model.Distribution; -import com.crowdin.client.distributions.model.DistributionRelease; +import com.crowdin.client.distributions.model.*; import java.util.List; @@ -12,7 +10,13 @@ public interface ClientDistribution extends Client { Distribution addDistribution(AddDistributionRequest request); + Distribution addDistributionStringsBased(AddDistributionStringsBasedRequest request); + DistributionRelease release(String hash); + DistributionStringsBasedRelease releaseStringsBased(String hash); + DistributionRelease getDistributionRelease(String hash); + + DistributionStringsBasedRelease getDistributionStringsBasedRelease(String hash); } diff --git a/src/main/java/com/crowdin/cli/client/CrowdinClientDistribution.java b/src/main/java/com/crowdin/cli/client/CrowdinClientDistribution.java index b9be24b39..a3c3c5fb3 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinClientDistribution.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinClientDistribution.java @@ -1,8 +1,6 @@ package com.crowdin.cli.client; -import com.crowdin.client.distributions.model.AddDistributionRequest; -import com.crowdin.client.distributions.model.Distribution; -import com.crowdin.client.distributions.model.DistributionRelease; +import com.crowdin.client.distributions.model.*; import java.util.List; @@ -29,6 +27,13 @@ public Distribution addDistribution(AddDistributionRequest distributionRequest) .getData()); } + @Override + public Distribution addDistributionStringsBased(AddDistributionStringsBasedRequest distributionRequest) { + return executeRequest(() -> this.client.getDistributionsApi() + .addDistributionStringsBased(Long.valueOf(projectId), distributionRequest) + .getData()); + } + @Override public DistributionRelease release(String hash) { return executeRequest(() -> this.client.getDistributionsApi() @@ -36,6 +41,13 @@ public DistributionRelease release(String hash) { .getData()); } + @Override + public DistributionStringsBasedRelease releaseStringsBased(String hash) { + return executeRequest(() -> this.client.getDistributionsApi() + .createDistributionStringsBasedRelease(Long.valueOf(projectId), hash) + .getData()); + } + @Override public DistributionRelease getDistributionRelease(String hash) { return executeRequest(() -> this.client.getDistributionsApi() @@ -43,4 +55,10 @@ public DistributionRelease getDistributionRelease(String hash) { .getData()); } + @Override + public DistributionStringsBasedRelease getDistributionStringsBasedRelease(String hash) { + return executeRequest(() -> this.client.getDistributionsApi() + .getDistributionStringsBasedRelease(Long.valueOf(projectId), hash) + .getData()); + } } diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index ccd96b7bf..babadd4c3 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -6,10 +6,7 @@ import com.crowdin.client.projectsgroups.model.ProjectSettings; import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.sourcefiles.model.*; -import com.crowdin.client.sourcestrings.model.AddSourceStringRequest; -import com.crowdin.client.sourcestrings.model.SourceString; -import com.crowdin.client.sourcestrings.model.UploadStringsProgress; -import com.crowdin.client.sourcestrings.model.UploadStringsRequest; +import com.crowdin.client.sourcestrings.model.*; import com.crowdin.client.storage.model.Storage; import com.crowdin.client.stringcomments.model.AddStringCommentRequest; import com.crowdin.client.stringcomments.model.StringComment; @@ -328,6 +325,13 @@ public SourceString addSourceString(AddSourceStringRequest request) { .getData()); } + @Override + public SourceString addSourceStringStringsBased(AddSourceStringStringsBasedRequest request) { + return executeRequest(() -> this.client.getSourceStringsApi() + .addSourceStringStringsBased(this.projectId, request) + .getData()); + } + @Override public List<SourceString> listSourceString(Long fileId, Long branchId, String labelIds, String filter, String croql) { return executeRequestFullList((limit, offset) -> this.client.getSourceStringsApi() @@ -391,6 +395,13 @@ public PreTranslationStatus startPreTranslation(ApplyPreTranslationRequest reque .getData()); } + @Override + public PreTranslationStatus startPreTranslationStringsBased(ApplyPreTranslationStringsBasedRequest request) { + return executeRequest(() ->this.client.getTranslationsApi() + .applyPreTranslationStringsBased(this.projectId, request) + .getData()); + } + @Override public PreTranslationStatus checkPreTranslation(String preTranslationId) { return executeRequest(() -> this.client.getTranslationsApi() diff --git a/src/main/java/com/crowdin/cli/client/ProjectClient.java b/src/main/java/com/crowdin/cli/client/ProjectClient.java index 1b8d852d5..f1deb5f17 100644 --- a/src/main/java/com/crowdin/cli/client/ProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/ProjectClient.java @@ -6,10 +6,7 @@ import com.crowdin.client.labels.model.AddLabelRequest; import com.crowdin.client.labels.model.Label; import com.crowdin.client.sourcefiles.model.*; -import com.crowdin.client.sourcestrings.model.AddSourceStringRequest; -import com.crowdin.client.sourcestrings.model.SourceString; -import com.crowdin.client.sourcestrings.model.UploadStringsProgress; -import com.crowdin.client.sourcestrings.model.UploadStringsRequest; +import com.crowdin.client.sourcestrings.model.*; import com.crowdin.client.stringcomments.model.AddStringCommentRequest; import com.crowdin.client.stringcomments.model.StringComment; import com.crowdin.client.translations.model.*; @@ -83,6 +80,8 @@ default CrowdinProjectFull downloadFullProject() { SourceString addSourceString(AddSourceStringRequest request); + SourceString addSourceStringStringsBased(AddSourceStringStringsBasedRequest request); + List<SourceString> listSourceString(Long fileId, Long branchId, String labelIds, String filter, String croql); void deleteSourceString(Long id); @@ -101,5 +100,7 @@ default CrowdinProjectFull downloadFullProject() { PreTranslationStatus startPreTranslation(ApplyPreTranslationRequest request); + PreTranslationStatus startPreTranslationStringsBased(ApplyPreTranslationStringsBasedRequest request); + PreTranslationStatus checkPreTranslation(String preTranslationId); } diff --git a/src/main/java/com/crowdin/cli/commands/Actions.java b/src/main/java/com/crowdin/cli/commands/Actions.java index 6a9702c96..997c17d40 100644 --- a/src/main/java/com/crowdin/cli/commands/Actions.java +++ b/src/main/java/com/crowdin/cli/commands/Actions.java @@ -48,7 +48,7 @@ NewAction<ProjectProperties, ProjectClient> status( boolean noProgress, String branchName, String languageId, String file, String directory, boolean isVerbose, boolean showTranslated, boolean showApproved, boolean failIfIncomplete); NewAction<ProjectProperties, ProjectClient> stringAdd( - boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, Boolean hidden); + boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, String branch, Boolean hidden); NewAction<ProjectProperties, ProjectClient> stringComment(boolean plainView, boolean noProgress, String text, String stringId, String language, String type, String issueType); @@ -97,7 +97,7 @@ NewAction<ProjectProperties, ClientTask> taskAdd( NewAction<ProjectProperties, ClientDistribution> distributionAdd(boolean noProgress, boolean plainView, String name, ExportMode exportMode, List<String> files, List<Integer> bundleIds, String branch, ProjectClient projectClient); - NewAction<ProjectProperties, ClientDistribution> distributionRelease(boolean noProgress, boolean plainView, String hash); + NewAction<ProjectProperties, ClientDistribution> distributionRelease(boolean noProgress, boolean plainView, String hash, ProjectClient projectClient); NewAction<ProjectProperties, ClientComment> commentList(boolean plainView, boolean isVerbose, String stringId, com.crowdin.client.stringcomments.model.Type type, com.crowdin.client.issues.model.Type issueType, IssueStatus status); 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 2d9a71fab..98518ffd3 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/CliActions.java +++ b/src/main/java/com/crowdin/cli/commands/actions/CliActions.java @@ -80,9 +80,9 @@ public NewAction<ProjectProperties, ProjectClient> status( @Override public NewAction<ProjectProperties, ProjectClient> stringAdd( - boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, Boolean hidden + boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, String branch, Boolean hidden ) { - return new StringAddAction(noProgress, text, identifier, maxLength, context, files, labelNames, hidden); + return new StringAddAction(noProgress, text, identifier, maxLength, context, files, labelNames, branch, hidden); } @Override public NewAction<ProjectProperties, ProjectClient> stringComment(boolean plainView, @@ -189,8 +189,8 @@ public NewAction<ProjectProperties, ClientDistribution> distributionAdd(boolean } @Override - public NewAction<ProjectProperties, ClientDistribution> distributionRelease(boolean noProgress, boolean plainView, String hash) { - return new DistributionReleaseAction(noProgress, plainView, hash); + public NewAction<ProjectProperties, ClientDistribution> distributionRelease(boolean noProgress, boolean plainView, String hash, ProjectClient projectClient) { + return new DistributionReleaseAction(noProgress, plainView, hash, projectClient); } @Override diff --git a/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java b/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java index a3f84615e..ded47b1a5 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java @@ -10,8 +10,10 @@ import com.crowdin.cli.utils.Utils; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.distributions.model.AddDistributionRequest; +import com.crowdin.client.distributions.model.AddDistributionStringsBasedRequest; import com.crowdin.client.distributions.model.Distribution; import com.crowdin.client.distributions.model.ExportMode; +import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.FileInfo; import lombok.AllArgsConstructor; @@ -19,11 +21,13 @@ import java.nio.file.Paths; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; import static com.crowdin.cli.utils.console.ExecutionStatus.OK; +import static com.crowdin.client.distributions.model.ExportMode.DEFAULT; @AllArgsConstructor class DistributionAddAction implements NewAction<ProjectProperties, ClientDistribution> { @@ -49,6 +53,9 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) ); List<Long> fileIds = null; if (files != null) { + if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); + } Map<String, Long> projectBranches = project.getBranches().values().stream() .collect(Collectors.toMap(Branch::getName, Branch::getId)); List<String> projectFiles = project.getFiles().stream() @@ -74,19 +81,36 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) .filter(file -> files.contains(file.getPath())) .map(FileInfo::getId) .collect(Collectors.toList()); + } else if (exportMode == DEFAULT && Objects.equals(project.getType(), Type.FILES_BASED)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.distribution.empty_file")); } - Distribution distribution; - AddDistributionRequest addDistributionRequest = RequestBuilder.addDistribution(name, exportMode, fileIds, bundleIds); - Optional.ofNullable(name).ifPresent(addDistributionRequest::setName); - Optional.ofNullable(exportMode).ifPresent(addDistributionRequest::setExportMode); - Optional.ofNullable(fileIds).ifPresent(addDistributionRequest::setFileIds); - Optional.ofNullable(bundleIds).ifPresent(addDistributionRequest::setBundleIds); + Distribution distribution = null; + if (Objects.equals(project.getType(), Type.FILES_BASED)) { + AddDistributionRequest addDistributionRequest = RequestBuilder.addDistribution(name, exportMode, fileIds, bundleIds); + Optional.ofNullable(name).ifPresent(addDistributionRequest::setName); + Optional.ofNullable(exportMode).ifPresent(addDistributionRequest::setExportMode); + Optional.ofNullable(fileIds).ifPresent(addDistributionRequest::setFileIds); + Optional.ofNullable(bundleIds).ifPresent(addDistributionRequest::setBundleIds); - try { - distribution = client.addDistribution(addDistributionRequest); - } catch (Exception e) { - throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.distribution_is_not_added"), addDistributionRequest), e); + try { + distribution = client.addDistribution(addDistributionRequest); + } catch (Exception e) { + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.distribution_is_not_added"), addDistributionRequest), e); + } + } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + AddDistributionStringsBasedRequest addDistributionRequest = new AddDistributionStringsBasedRequest(); + addDistributionRequest.setName(name); + if (Objects.isNull(bundleIds)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.distribution.empty_bundle_ids")); + } + addDistributionRequest.setBundleIds(bundleIds); + + try { + distribution = client.addDistributionStringsBased(addDistributionRequest); + } catch (Exception e) { + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.distribution_is_not_added"), addDistributionRequest), e); + } } if (!plainView) { diff --git a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java index 989837961..e03183ede 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java @@ -1,13 +1,19 @@ package com.crowdin.cli.commands.actions; import com.crowdin.cli.client.ClientDistribution; +import com.crowdin.cli.client.CrowdinProjectInfo; +import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; import com.crowdin.cli.properties.ProjectProperties; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.distributions.model.DistributionRelease; +import com.crowdin.client.distributions.model.DistributionStringsBasedRelease; +import com.crowdin.client.projectsgroups.model.Type; import lombok.AllArgsConstructor; +import java.util.Objects; + import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; import static com.crowdin.cli.utils.console.ExecutionStatus.OK; @@ -18,13 +24,26 @@ class DistributionReleaseAction implements NewAction<ProjectProperties, ClientDi private boolean plainView; private String hash; + private ProjectClient projectClient; + @Override public void act(Outputter out, ProjectProperties pb, ClientDistribution client) { - this.releaseDistribution(out, client); + CrowdinProjectInfo project = ConsoleSpinner.execute( + out, + "message.spinner.fetching_project_info", "error.collect_project_info", + this.noProgress, + this.plainView, + () -> this.projectClient.downloadProjectInfo() + ); + if (Objects.equals(project.getType(), Type.FILES_BASED)) { + this.releaseDistributionFilesBased(out, client); + } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + this.releaseDistributionStringsBased(out, client); + } out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.distribution.released"), hash))); } - private DistributionRelease releaseDistribution(Outputter out, ClientDistribution client) { + private DistributionRelease releaseDistributionFilesBased(Outputter out, ClientDistribution client) { return ConsoleSpinner.execute( out, "message.spinner.releasing_distribution", @@ -53,4 +72,34 @@ private DistributionRelease releaseDistribution(Outputter out, ClientDistributio } ); } + + private DistributionStringsBasedRelease releaseDistributionStringsBased(Outputter out, ClientDistribution client) { + return ConsoleSpinner.execute( + out, + "message.spinner.releasing_distribution", + "error.distribution_is_not_released", + this.noProgress, + false, + () -> { + DistributionStringsBasedRelease release = client.releaseStringsBased(hash); + + while (!"success".equalsIgnoreCase(release.getStatus())) { + ConsoleSpinner.update( + String.format(RESOURCE_BUNDLE.getString("message.spinner.releasing_distribution_percents"), + release.getProgress())); + Thread.sleep(1000); + + release = client.getDistributionStringsBasedRelease(hash); + + if ("failed".equalsIgnoreCase(release.getStatus())) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.spinner.build_has_failed")); + } + } + + ConsoleSpinner.update(String.format(RESOURCE_BUNDLE.getString("message.spinner.releasing_distribution_percents"), 100)); + + return release; + } + ); + } } 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 8af7f492f..39b723f8c 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java @@ -6,28 +6,21 @@ import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; -import com.crowdin.cli.commands.functionality.ProjectFilesUtils; -import com.crowdin.cli.commands.functionality.PropertiesBeanUtils; -import com.crowdin.cli.commands.functionality.RequestBuilder; -import com.crowdin.cli.commands.functionality.SourcesUtils; +import com.crowdin.cli.commands.functionality.*; import com.crowdin.cli.properties.PropertiesWithFiles; import com.crowdin.cli.utils.PlaceholderUtil; import com.crowdin.cli.utils.Utils; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.labels.model.Label; import com.crowdin.client.languages.model.Language; +import com.crowdin.client.projectsgroups.model.Type; +import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.FileInfo; -import com.crowdin.client.translations.model.ApplyPreTranslationRequest; -import com.crowdin.client.translations.model.AutoApproveOption; -import com.crowdin.client.translations.model.Method; -import com.crowdin.client.translations.model.PreTranslationStatus; +import com.crowdin.client.translations.model.*; import org.apache.commons.lang3.StringUtils; import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; @@ -74,18 +67,27 @@ public void act(Outputter out, PropertiesWithFiles properties, ProjectClient cli this.noProgress, this.plainView, () -> client.downloadFullProject(this.branchName)); List<String> languages = this.prepareLanguageIds(project); - List<Long> fileIds = this.prepareFileIds(out, properties, project); List<Long> labelIds = this.prepareLabelIds(out, client); - if (fileIds == null || fileIds.isEmpty()) { - throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.no_files_found_for_pre_translate"))); + if (Objects.equals(project.getType(), Type.FILES_BASED)) { + List<Long> fileIds = this.prepareFileIds(out, properties, project); + if (fileIds == null || fileIds.isEmpty()) { + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.no_files_found_for_pre_translate"))); + } + ApplyPreTranslationRequest request = RequestBuilder.applyPreTranslation( + languages, fileIds, method, engineId, autoApproveOption, + duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); + this.applyPreTranslation(out, client, request); + } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + Branch branch = BranchUtils.getOrCreateBranch(out, branchName, client, project, false); + if (Objects.isNull(branch)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); + } + ApplyPreTranslationStringsBasedRequest request = RequestBuilder.applyPreTranslationStringsBased( + languages, Collections.singletonList(branch.getId()), method, engineId, autoApproveOption, + duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); + this.applyPreTranslationStringsBased(out, client, request); } - - ApplyPreTranslationRequest request = RequestBuilder.applyPreTranslation( - languages, fileIds, method, engineId, autoApproveOption, - duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); - - this.applyPreTranslation(out, client, request); } private List<String> prepareLanguageIds(CrowdinProjectInfo projectInfo) { @@ -176,19 +178,25 @@ private void applyPreTranslation(Outputter out, ProjectClient client, ApplyPreTr this.plainView, () -> { PreTranslationStatus preTranslationStatus = client.startPreTranslation(request); + preTranslationStatus = handlePreTranslationStatus(client, preTranslationStatus); - while (!preTranslationStatus.getStatus().equalsIgnoreCase("finished")) { - ConsoleSpinner.update( - String.format(RESOURCE_BUNDLE.getString("message.spinner.pre_translate_percents"), - Math.toIntExact(preTranslationStatus.getProgress()))); - Thread.sleep(1000); + ConsoleSpinner.update(String.format(RESOURCE_BUNDLE.getString("message.spinner.pre_translate_done"), 100)); - preTranslationStatus = client.checkPreTranslation(preTranslationStatus.getIdentifier()); + return preTranslationStatus; + } + ); + } - if (preTranslationStatus.getStatus().equalsIgnoreCase("failed")) { - throw new RuntimeException(); - } - } + private void applyPreTranslationStringsBased(Outputter out, ProjectClient client, ApplyPreTranslationStringsBasedRequest request) { + ConsoleSpinner.execute( + out, + "message.spinner.pre_translate", + "error.spinner.pre_translate", + this.noProgress, + this.plainView, + () -> { + PreTranslationStatus preTranslationStatus = client.startPreTranslationStringsBased(request); + preTranslationStatus = handlePreTranslationStatus(client, preTranslationStatus); ConsoleSpinner.update(String.format(RESOURCE_BUNDLE.getString("message.spinner.pre_translate_done"), 100)); @@ -196,4 +204,20 @@ private void applyPreTranslation(Outputter out, ProjectClient client, ApplyPreTr } ); } + + private PreTranslationStatus handlePreTranslationStatus(ProjectClient client, PreTranslationStatus preTranslationStatus) throws InterruptedException { + while (!preTranslationStatus.getStatus().equalsIgnoreCase("finished")) { + ConsoleSpinner.update( + String.format(RESOURCE_BUNDLE.getString("message.spinner.pre_translate_percents"), + Math.toIntExact(preTranslationStatus.getProgress()))); + Thread.sleep(1000); + + preTranslationStatus = client.checkPreTranslation(preTranslationStatus.getIdentifier()); + + if (preTranslationStatus.getStatus().equalsIgnoreCase("failed")) { + throw new RuntimeException(); + } + } + return preTranslationStatus; + } } diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java index bf203459d..1cc425b81 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java @@ -4,16 +4,21 @@ import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; +import com.crowdin.cli.commands.functionality.BranchUtils; import com.crowdin.cli.commands.functionality.ProjectFilesUtils; import com.crowdin.cli.commands.functionality.RequestBuilder; import com.crowdin.cli.properties.ProjectProperties; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.labels.model.Label; +import com.crowdin.client.projectsgroups.model.Type; +import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.FileInfo; import com.crowdin.client.sourcestrings.model.AddSourceStringRequest; +import com.crowdin.client.sourcestrings.model.AddSourceStringStringsBasedRequest; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; @@ -29,10 +34,11 @@ class StringAddAction implements NewAction<ProjectProperties, ProjectClient> { private final String context; private final List<String> files; private final List<String> labelNames; + private final String branchName; private final Boolean hidden; public StringAddAction( - boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, Boolean hidden + boolean noProgress, String text, String identifier, Integer maxLength, String context, List<String> files, List<String> labelNames, String branchName, Boolean hidden ) { this.noProgress = noProgress; this.text = text; @@ -41,6 +47,7 @@ public StringAddAction( this.context = context; this.files = files; this.labelNames = labelNames; + this.branchName = branchName; this.hidden = hidden; } @@ -52,10 +59,22 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { List<Long> labelIds = (labelNames != null && !labelNames.isEmpty()) ? this.prepareLabelIds(client) : null; if (files == null || files.isEmpty()) { - AddSourceStringRequest request = RequestBuilder.addString(this.text, this.identifier, this.maxLength, this.context, null, this.hidden, labelIds); - client.addSourceString(request); + if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + Branch branch = BranchUtils.getOrCreateBranch(out, branchName, client, project, false); + if (Objects.isNull(branch)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); + } + AddSourceStringStringsBasedRequest request = RequestBuilder.addStringStringsBased(this.text, this.identifier, this.maxLength, this.context, branch.getId(), this.hidden, labelIds); + client.addSourceStringStringsBased(request); + } else { + AddSourceStringRequest request = RequestBuilder.addString(this.text, this.identifier, this.maxLength, this.context, null, this.hidden, labelIds); + client.addSourceString(request); + } out.println(OK.withIcon(RESOURCE_BUNDLE.getString("message.source_string_uploaded"))); } else { + if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); + } Map<String, FileInfo> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); boolean containsError = false; for (String file : files) { @@ -79,7 +98,6 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { throw new RuntimeException(); } } - } private List<Long> prepareLabelIds(ProjectClient client) { diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java index 1497756d7..3601da382 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java @@ -9,6 +9,7 @@ import com.crowdin.cli.utils.Utils; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.labels.model.Label; +import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.FileInfo; import com.crowdin.client.sourcestrings.model.SourceString; @@ -16,6 +17,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -52,10 +54,16 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { Map<Long, String> labels = client.listLabels().stream() .collect(Collectors.toMap(Label::getId, Label::getTitle)); - Map<String, FileInfo> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); - Map<Long, String> reversePaths = paths.entrySet() - .stream() - .collect(Collectors.toMap((entry) -> entry.getValue().getId(), Map.Entry::getKey)); + boolean isFileBasedProject = Objects.equals(project.getType(), Type.FILES_BASED); + Map<String, FileInfo> paths = null; + Map<Long, String> reversePaths = null; + if (isFileBasedProject) { + paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); + reversePaths = paths.entrySet() + .stream() + .collect(Collectors.toMap((entry) -> entry.getValue().getId(), Map.Entry::getKey)); + } + Map<Long, String> finalReversePaths = reversePaths; String encodedFilter = filter != null ? Utils.encodeURL(filter) : null; String encodedCroql = croql != null ? Utils.encodeURL(croql) : null; @@ -64,6 +72,9 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { if (StringUtils.isEmpty(file)) { sourceStrings = client.listSourceString(null, branchId, null, encodedFilter, encodedCroql); } else { + if (!isFileBasedProject) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); + } if (paths.containsKey(file)) { sourceStrings = client.listSourceString(paths.get(file).getId(), branchId, null, encodedFilter, encodedCroql); } else { @@ -86,8 +97,8 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { out.println(String.format( RESOURCE_BUNDLE.getString("message.source_string_list_context"), ss.getContext().trim().replaceAll("\n", "\n\t\t"))); } - if (ss.getFileId() != null) { - out.println(String.format(RESOURCE_BUNDLE.getString("message.source_string_list_file"), reversePaths.get(ss.getFileId()))); + if (isFileBasedProject && (ss.getFileId() != null)) { + out.println(String.format(RESOURCE_BUNDLE.getString("message.source_string_list_file"), finalReversePaths.get(ss.getFileId()))); } if (ss.getMaxLength() != null && ss.getMaxLength() != 0) { out.println(String.format(RESOURCE_BUNDLE.getString("message.source_string_list_max_length"), ss.getMaxLength())); diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java index cd31356c6..edbd0a4a5 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java @@ -1,10 +1,6 @@ package com.crowdin.cli.commands.actions; -import com.crowdin.cli.client.CrowdinProjectFull; -import com.crowdin.cli.client.EmptyFileException; -import com.crowdin.cli.client.ExistsResponseException; -import com.crowdin.cli.client.FileInUpdateException; -import com.crowdin.cli.client.ProjectClient; +import com.crowdin.cli.client.*; import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; import com.crowdin.cli.commands.actions.subactions.DeleteObsoleteProjectFilesSubAction; @@ -15,23 +11,12 @@ import com.crowdin.cli.utils.Utils; import com.crowdin.cli.utils.concurrency.ConcurrencyUtil; import com.crowdin.cli.utils.console.ConsoleSpinner; -import com.crowdin.cli.utils.console.ExecutionStatus; import com.crowdin.client.core.model.PatchRequest; import com.crowdin.client.labels.model.Label; import com.crowdin.client.languages.model.Language; -import com.crowdin.client.sourcefiles.model.AddBranchRequest; -import com.crowdin.client.sourcefiles.model.AddFileRequest; -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 com.crowdin.client.projectsgroups.model.Type; +import com.crowdin.client.sourcefiles.model.*; +import com.crowdin.client.sourcestrings.model.UploadStringsRequest; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; @@ -42,16 +27,13 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE; -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.cli.utils.console.ExecutionStatus.*; import static com.crowdin.client.sourcefiles.model.ExportQuotes.DOUBLE; +import static com.crowdin.client.sourcefiles.model.ExportQuotes.SINGLE; class UploadSourcesAction implements NewAction<PropertiesWithFiles, ProjectClient> { @@ -92,18 +74,26 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { Branch branch = (branchName != null) ? BranchUtils.getOrCreateBranch(out, branchName, client, project, plainView) : null; Long branchId = (branch != null) ? branch.getId() : null; - Map<String, Long> directoryPaths = ProjectFilesUtils.buildDirectoryPaths(project.getDirectories(), project.getBranches()) - .entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); - Map<String, FileInfo> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); - + boolean isFilesBasedProject = Objects.equals(Type.FILES_BASED, project.getType()); + Map<String, Long> directoryPaths = null; + Map<String, FileInfo> paths = null; DeleteObsoleteProjectFilesSubAction deleteObsoleteProjectFilesSubAction = new DeleteObsoleteProjectFilesSubAction(out, client); - if (deleteObsolete) { - Map<String, Long> directories = ProjectFilesUtils.buildDirectoryPaths(project.getDirectories(branchId)) + + if (isFilesBasedProject) { + directoryPaths = ProjectFilesUtils.buildDirectoryPaths(project.getDirectories(), project.getBranches()) .entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); - Map<String, com.crowdin.client.sourcefiles.model.File> projectFiles = ProjectFilesUtils.buildFilePaths(project.getDirectories(branchId), project.getFiles(branchId)); - deleteObsoleteProjectFilesSubAction.setData(projectFiles, directories, pb.getPreserveHierarchy(), this.plainView); + paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); + if (deleteObsolete) { + Map<String, Long> directories = ProjectFilesUtils.buildDirectoryPaths(project.getDirectories(branchId)) + .entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + Map<String, com.crowdin.client.sourcefiles.model.File> projectFiles = ProjectFilesUtils.buildFilePaths(project.getDirectories(branchId), project.getFiles(branchId)); + deleteObsoleteProjectFilesSubAction.setData(projectFiles, directories, pb.getPreserveHierarchy(), this.plainView); + } } + Map<String, Long> finalDirectoryPaths = directoryPaths; + Map<String, FileInfo> finalPaths = paths; + List<String> uploadedSources = new ArrayList<>(); Map<String, Long> labels = client.listLabels().stream() @@ -185,8 +175,8 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { uploadedSources.add(fileFullPath); } - FileInfo projectFile = paths.get(fileFullPath); - if (autoUpdate && projectFile != null) { + FileInfo projectFile = isFilesBasedProject ? finalPaths.get(fileFullPath) : null; + if (isFilesBasedProject && autoUpdate && projectFile != null) { final UpdateFileRequest request = new UpdateFileRequest(); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); request.setImportOptions(buildImportOptions(sourceFile, file, srxStorageId)); @@ -235,7 +225,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.uploading_file"), fileFullPath), e); } }; - } else if (projectFile == null) { + } else if (projectFile == null && isFilesBasedProject) { final AddFileRequest request = new AddFileRequest(); request.setName(fileName); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); @@ -254,7 +244,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { return (Runnable) () -> { Long directoryId; try { - directoryId = ProjectUtils.createPath(out, client, directoryPaths, filePath, branch, plainView); + directoryId = ProjectUtils.createPath(out, client, finalDirectoryPaths, filePath, branch, plainView); } catch (Exception e) { errorsPresented.set(true); throw new RuntimeException(RESOURCE_BUNDLE.getString("error.creating_directories"), e); @@ -268,7 +258,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { try (InputStream fileStream = new FileInputStream(sourceFile)) { request.setStorageId(client.uploadStorage(source.substring(source.lastIndexOf(Utils.PATH_SEPARATOR) + 1), fileStream)); - } catch (EmptyFileException e){ + } catch (EmptyFileException e) { errorsPresented.set(false); out.println(SKIPPED.withIcon(String.format(RESOURCE_BUNDLE.getString("message.uploading_file_skipped"), fileFullPath))); return; @@ -292,6 +282,47 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { out.println(fileFullPath); } }; + } else if (Objects.equals(Type.STRINGS_BASED, project.getType())) { + final UploadStringsRequest request = new UploadStringsRequest(); + request.setImportOptions(buildImportOptionsStringsBased(sourceFile, file, srxStorageId)); + if (file.getType() != null) { + request.setType(file.getType()); + } + if (file.getLabels() != null) { + List<Long> labelsIds = file.getLabels().stream().map(labels::get) + .collect(Collectors.toList()); + request.setLabelIds(labelsIds); + } + + return (Runnable) () -> { + if (branch == null) { + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); + } + request.setBranchId(branch.getId()); + + try (InputStream fileStream = new FileInputStream(sourceFile)) { + request.setStorageId(client.uploadStorage(source.substring(source.lastIndexOf(Utils.PATH_SEPARATOR) + 1), fileStream)); + } catch (EmptyFileException e) { + errorsPresented.set(false); + out.println(SKIPPED.withIcon(String.format(RESOURCE_BUNDLE.getString("message.uploading_file_skipped"), fileFullPath))); + return; + } catch (Exception e) { + errorsPresented.set(true); + throw new RuntimeException( + String.format(RESOURCE_BUNDLE.getString("error.upload_to_storage"), sourceFile.getAbsolutePath()), e); + } + try { + client.addSourceStringsBased(request); + } catch (Exception e) { + errorsPresented.set(true); + throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.uploading_file"), fileFullPath), e); + } + if (!plainView) { + out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.uploading_file"), fileFullPath))); + } else { + out.println(fileFullPath); + } + }; } else { return (Runnable) () -> { if (!plainView) { @@ -338,6 +369,16 @@ private ImportOptions buildImportOptions(java.io.File sourceFile, FileBean fileB } } + private com.crowdin.client.sourcestrings.model.ImportOptions buildImportOptionsStringsBased(java.io.File sourceFile, FileBean fileBean, Long srxStorageId) { + com.crowdin.client.sourcestrings.model.ImportOptions importOptions = new com.crowdin.client.sourcestrings.model.ImportOptions(); + if (isSpreadsheet(sourceFile, fileBean)) { + importOptions.setFirstLineContainsHeader(fileBean.getFirstLineContainsHeader()); + importOptions.setScheme(PropertiesBeanUtils.getSchemeObject(fileBean.getScheme())); + importOptions.setImportTranslations(fileBean.getImportTranslations()); + } + return importOptions; + } + private boolean isSpreadsheet(java.io.File file, FileBean fileBean) { return (fileBean.getDest() != null) ? FilenameUtils.isExtension(fileBean.getDest(), "csv", "xls", "xlsx") diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java index 2a40031ab..8f6b8b392 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java @@ -18,17 +18,17 @@ import com.crowdin.cli.utils.concurrency.ConcurrencyUtil; import com.crowdin.cli.utils.console.ConsoleSpinner; import com.crowdin.client.languages.model.Language; +import com.crowdin.client.projectsgroups.model.Type; +import com.crowdin.client.sourcefiles.model.Branch; import com.crowdin.client.sourcefiles.model.File; import com.crowdin.client.translations.model.UploadTranslationsRequest; +import com.crowdin.client.translations.model.UploadTranslationsStringsRequest; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import java.io.FileInputStream; import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; @@ -81,8 +81,6 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { LanguageMapping serverLanguageMapping = project.getLanguageMapping(); - Map<String, File> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFiles()); - List<Language> languages = (languageId != null) ? project.findLanguageById(languageId, true) .map(Collections::singletonList) @@ -105,108 +103,159 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } continue; } - - Map<java.io.File, Pair<List<Language>, UploadTranslationsRequest>> preparedRequests = new HashMap<>(); - String branchPath = (StringUtils.isNotEmpty(this.branchName) ? branchName + Utils.PATH_SEPARATOR : ""); + List<Runnable> tasks = null; AtomicBoolean containsErrors = new AtomicBoolean(false); - fileSourcesWithoutIgnores.forEach(source -> { - String filePath = branchPath + (StringUtils.isNotEmpty(file.getDest()) - ? PropertiesBeanUtils.prepareDest(file.getDest(), StringUtils.removeStart(source, pb.getBasePath()), placeholderUtil) - : StringUtils.removeStart(source, pb.getBasePath() + commonPath)); - - if (!paths.containsKey(filePath)) { - containsErrors.set(true); - if (!plainView) { - out.println(ERROR.withIcon(String.format( - RESOURCE_BUNDLE.getString("error.source_not_exists_in_project"), - StringUtils.removeStart(source, pb.getBasePath()), filePath))); - } - return; - } - Long fileId = paths.get(filePath).getId(); + if (Objects.equals(project.getType(), Type.FILES_BASED)) { + Map<String, File> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFiles()); + Map<java.io.File, Pair<List<Language>, UploadTranslationsRequest>> preparedRequests = new HashMap<>(); + String branchPath = (StringUtils.isNotEmpty(this.branchName) ? branchName + Utils.PATH_SEPARATOR : ""); + fileSourcesWithoutIgnores.forEach(source -> { + String filePath = branchPath + (StringUtils.isNotEmpty(file.getDest()) + ? PropertiesBeanUtils.prepareDest(file.getDest(), StringUtils.removeStart(source, pb.getBasePath()), placeholderUtil) + : StringUtils.removeStart(source, pb.getBasePath() + commonPath)); -// build filePath to each source and project language - String fileSource = StringUtils.removeStart(source, pb.getBasePath()); - String translation = TranslationsUtils.replaceDoubleAsterisk(file.getSource(), file.getTranslation(), fileSource); - translation = placeholderUtil.replaceFileDependentPlaceholders(translation, new java.io.File(source)); - if (file.getScheme() != null && !PlaceholderUtil.containsLangPlaceholders(translation)) { - java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + translation); - if (!transFile.exists()) { + if (!paths.containsKey(filePath)) { + containsErrors.set(true); if (!plainView) { - out.println(SKIPPED.withIcon(String.format( - RESOURCE_BUNDLE.getString("error.translation_not_exists"), - StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); + out.println(ERROR.withIcon(String.format( + RESOURCE_BUNDLE.getString("error.source_not_exists_in_project"), + StringUtils.removeStart(source, pb.getBasePath()), filePath))); } return; } - UploadTranslationsRequest request = RequestBuilder.uploadTranslations(fileId, importEqSuggestions, autoApproveImported, translateHidden); - preparedRequests.put(transFile, Pair.of(languages, request)); - } else { - for (Language language : languages) { - LanguageMapping localLanguageMapping = - LanguageMapping.fromConfigFileLanguageMapping(file.getLanguagesMapping()); - LanguageMapping languageMapping = - LanguageMapping.populate(localLanguageMapping, serverLanguageMapping); - - String transFileName = placeholderUtil.replaceLanguageDependentPlaceholders(translation, languageMapping, language); - transFileName = PropertiesBeanUtils.useTranslationReplace(transFileName, file.getTranslationReplace()); - java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + transFileName); + Long fileId = paths.get(filePath).getId(); + +// build filePath to each source and project language + String fileSource = StringUtils.removeStart(source, pb.getBasePath()); + String translation = TranslationsUtils.replaceDoubleAsterisk(file.getSource(), file.getTranslation(), fileSource); + translation = placeholderUtil.replaceFileDependentPlaceholders(translation, new java.io.File(source)); + if (file.getScheme() != null && !PlaceholderUtil.containsLangPlaceholders(translation)) { + java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + translation); if (!transFile.exists()) { if (!plainView) { out.println(SKIPPED.withIcon(String.format( RESOURCE_BUNDLE.getString("error.translation_not_exists"), StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); } - continue; + return; } UploadTranslationsRequest request = RequestBuilder.uploadTranslations(fileId, importEqSuggestions, autoApproveImported, translateHidden); - preparedRequests.put(transFile, Pair.of(Collections.singletonList(language), request)); + preparedRequests.put(transFile, Pair.of(languages, request)); + } else { + for (Language language : languages) { + LanguageMapping localLanguageMapping = + LanguageMapping.fromConfigFileLanguageMapping(file.getLanguagesMapping()); + LanguageMapping languageMapping = + LanguageMapping.populate(localLanguageMapping, serverLanguageMapping); + + String transFileName = placeholderUtil.replaceLanguageDependentPlaceholders(translation, languageMapping, language); + transFileName = PropertiesBeanUtils.useTranslationReplace(transFileName, file.getTranslationReplace()); + java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + transFileName); + if (!transFile.exists()) { + if (!plainView) { + out.println(SKIPPED.withIcon(String.format( + RESOURCE_BUNDLE.getString("error.translation_not_exists"), + StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); + } + continue; + } + UploadTranslationsRequest request = RequestBuilder.uploadTranslations(fileId, importEqSuggestions, autoApproveImported, translateHidden); + preparedRequests.put(transFile, Pair.of(Collections.singletonList(language), request)); + } } + }); + + tasks = preparedRequests.entrySet() + .stream() + .map(entry -> (Runnable) () -> { + java.io.File translationFile = entry.getKey(); + List<Language> langs = entry.getValue().getLeft(); + UploadTranslationsRequest request = entry.getValue().getRight(); + try (InputStream fileStream = new FileInputStream(translationFile)) { + Long storageId = client.uploadStorage(translationFile.getName(), fileStream); + request.setStorageId(storageId); + } catch (Exception e) { + containsErrors.set(true); + throw new RuntimeException(String.format( + RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) + ), e); + } + try { + for (Language lang : langs) { + try { + client.uploadTranslations(lang.getId(), request); + } catch (WrongLanguageException e) { + out.println(WARNING.withIcon(String.format( + RESOURCE_BUNDLE.getString("message.warning.file_not_uploaded_cause_of_language"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()), lang.getName()))); + } + } + } catch (Exception e) { + containsErrors.set(true); + throw new RuntimeException(String.format( + RESOURCE_BUNDLE.getString("error.upload_translation"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) + ), e); + } + if (!plainView) { + out.println(OK.withIcon(String.format( + RESOURCE_BUNDLE.getString("message.translation_uploaded"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())))); + } else { + out.println(StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())); + } + }) + .collect(Collectors.toList()); + } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + Map<java.io.File, Pair<List<Language>, UploadTranslationsStringsRequest>> preparedRequests = new HashMap<>(); + Branch branch = project.findBranchByName(branchName) + .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))); + for (Language language : languages) { + UploadTranslationsStringsRequest request = new UploadTranslationsStringsRequest(); + request.setBranchId(branch.getId()); + request.setTranslateHidden(translateHidden); + request.setAutoApproveImported(autoApproveImported); + request.setImportEqSuggestions(importEqSuggestions); + preparedRequests.put(new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + file.getTranslation()), Pair.of(Collections.singletonList(language), request)); } - }); - - List<Runnable> tasks = preparedRequests.entrySet() - .stream() - .map(entry -> (Runnable) () -> { - java.io.File translationFile = entry.getKey(); - List<Language> langs = entry.getValue().getLeft(); - UploadTranslationsRequest request = entry.getValue().getRight(); - try (InputStream fileStream = new FileInputStream(translationFile)) { - Long storageId = client.uploadStorage(translationFile.getName(), fileStream); - request.setStorageId(storageId); - } catch (Exception e) { - containsErrors.set(true); - throw new RuntimeException(String.format( - RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) - ), e); - } - try { - for (Language lang : langs) { - try { - client.uploadTranslations(lang.getId(), request); - } catch (WrongLanguageException e) { - out.println(WARNING.withIcon(String.format( - RESOURCE_BUNDLE.getString("message.warning.file_not_uploaded_cause_of_language"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()), lang.getName()))); + tasks = preparedRequests.entrySet() + .stream() + .map(entry -> (Runnable) () -> { + java.io.File translationFile = entry.getKey(); + List<Language> langs = entry.getValue().getLeft(); + UploadTranslationsStringsRequest request = entry.getValue().getRight(); + try (InputStream fileStream = new FileInputStream(translationFile)) { + Long storageId = client.uploadStorage(translationFile.getName(), fileStream); + request.setStorageId(storageId); + } catch (Exception e) { + containsErrors.set(true); + throw new RuntimeException(String.format( + RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) + ), e); + } + try { + for (Language lang : langs) { + client.uploadTranslationStringsBased(lang.getId(), request); } + } catch (Exception e) { + containsErrors.set(true); + throw new RuntimeException(String.format( + RESOURCE_BUNDLE.getString("error.upload_translation"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) + ), e); } - } catch (Exception e) { - containsErrors.set(true); - throw new RuntimeException(String.format( - RESOURCE_BUNDLE.getString("error.upload_translation"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) - ), e); - } - if (!plainView) { - out.println(OK.withIcon(String.format( - RESOURCE_BUNDLE.getString("message.translation_uploaded"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())))); - } else { - out.println(StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())); - } - }) - .collect(Collectors.toList()); + if (!plainView) { + out.println(OK.withIcon(String.format( + RESOURCE_BUNDLE.getString("message.translation_uploaded"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())))); + } else { + out.println(StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath())); + } + }) + .collect(Collectors.toList()); + } ConcurrencyUtil.executeAndWait(tasks, debug); if (containsErrors.get()) { diff --git a/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java b/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java index 51715fe5d..e3eb1a9bf 100644 --- a/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java +++ b/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java @@ -12,6 +12,7 @@ import com.crowdin.client.labels.model.AddLabelRequest; import com.crowdin.client.sourcefiles.model.AddBranchRequest; import com.crowdin.client.sourcestrings.model.AddSourceStringRequest; +import com.crowdin.client.sourcestrings.model.AddSourceStringStringsBasedRequest; import com.crowdin.client.stringcomments.model.AddStringCommentRequest; import com.crowdin.client.stringcomments.model.Type; import com.crowdin.client.tasks.model.CreateTaskRequest; @@ -20,14 +21,7 @@ import com.crowdin.client.translationmemory.model.TranslationMemoryExportRequest; import com.crowdin.client.translationmemory.model.TranslationMemoryFormat; import com.crowdin.client.translationmemory.model.TranslationMemoryImportRequest; -import com.crowdin.client.translations.model.ApplyPreTranslationRequest; -import com.crowdin.client.translations.model.AutoApproveOption; -import com.crowdin.client.translations.model.CharTransformation; -import com.crowdin.client.translations.model.CrowdinTranslationCraeteProjectPseudoBuildForm; -import com.crowdin.client.translations.model.CrowdinTranslationCreateProjectBuildForm; -import com.crowdin.client.translations.model.ExportProjectTranslationRequest; -import com.crowdin.client.translations.model.Method; -import com.crowdin.client.translations.model.UploadTranslationsRequest; +import com.crowdin.client.translations.model.*; import java.util.ArrayList; import java.util.List; @@ -48,6 +42,18 @@ public static AddSourceStringRequest addString(String text, String identifier, I return request; } + public static AddSourceStringStringsBasedRequest addStringStringsBased(String text, String identifier, Integer maxLength, String context, Long branchId, Boolean hidden, List<Long> labelIds) { + AddSourceStringStringsBasedRequest request = new AddSourceStringStringsBasedRequest(); + request.setText(text); + request.setIdentifier(identifier); + request.setMaxLength(maxLength); + request.setContext(context); + request.setBranchId(branchId); + request.setIsHidden(hidden); + request.setLabelIds(labelIds); + return request; + } + public static AddStringCommentRequest addComment(String text, String type, String language, String issueType, String stringId) { AddStringCommentRequest request = new AddStringCommentRequest(); @@ -285,6 +291,23 @@ public static ApplyPreTranslationRequest applyPreTranslation( return request; } + public static ApplyPreTranslationStringsBasedRequest applyPreTranslationStringsBased( + List<String> languageIds, List<Long> branchId, Method method, Long engineId, AutoApproveOption autoApproveOption, + Boolean duplicateTranslations, Boolean translateUntranslatedOnly, Boolean translateWithPerfectMatchOnly, List<Long> labelIds + ) { + ApplyPreTranslationStringsBasedRequest request = new ApplyPreTranslationStringsBasedRequest(); + request.setLanguageIds(languageIds); + request.setBranchIds(branchId); + request.setMethod(method); + request.setEngineId(engineId); + request.setAutoApproveOption(autoApproveOption); + request.setDuplicateTranslations(duplicateTranslations); + request.setTranslateUntranslatedOnly(translateUntranslatedOnly); + request.setTranslateWithPerfectMatchOnly(translateWithPerfectMatchOnly); + request.setLabelIds(labelIds); + return request; + } + public static AddBranchRequest addBranch(String name, String title, String exportPattern, Priority priority) { AddBranchRequest request = new AddBranchRequest(); request.setName(name); diff --git a/src/main/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommand.java index 198a1c988..2cb4325f9 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommand.java @@ -56,10 +56,6 @@ protected List<String> checkOptions() { errors.add(RESOURCE_BUNDLE.getString("error.distribution.empty_name")); } - if (exportMode == DEFAULT && files == null) { - errors.add(RESOURCE_BUNDLE.getString("error.distribution.empty_file")); - } - if (exportMode == BUNDLE && bundleIds == null) { errors.add(RESOURCE_BUNDLE.getString("error.distribution.empty_bundle_ids")); } diff --git a/src/main/java/com/crowdin/cli/commands/picocli/DistributionReleaseSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/DistributionReleaseSubcommand.java index c14cc1b4b..3232ef2f9 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/DistributionReleaseSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/DistributionReleaseSubcommand.java @@ -1,8 +1,10 @@ package com.crowdin.cli.commands.picocli; import com.crowdin.cli.client.ClientDistribution; +import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.Actions; import com.crowdin.cli.commands.NewAction; +import com.crowdin.cli.commands.Outputter; import com.crowdin.cli.properties.ProjectProperties; import picocli.CommandLine; @@ -20,6 +22,8 @@ class DistributionReleaseSubcommand extends ActCommandDistribution { @Override protected NewAction<ProjectProperties, ClientDistribution> getAction(Actions actions) { - return actions.distributionRelease(noProgress, plainView, hash); + Outputter out = new PicocliOutputter(System.out, isAnsi()); + ProjectClient projectClient = this.getProjectClient(this.getProperties(propertiesBuilders, out)); + return actions.distributionRelease(noProgress, plainView, hash, projectClient); } } diff --git a/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java index 0be2193a7..0b6f0faa9 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java @@ -35,6 +35,9 @@ class StringAddSubcommand extends ActCommandProject { @CommandLine.Option(names = {"--label"}, descriptionKey = "params.label", paramLabel = "...", order = -2) protected List<String> labelNames; + @CommandLine.Option(names = {"--branch"}, descriptionKey = "branch", paramLabel = "...", order = -2) + protected String branch; + @CommandLine.Option(names = {"--hidden"}, order = -2) protected Boolean isHidden; @@ -55,6 +58,6 @@ protected List<String> checkOptions() { @Override protected NewAction<ProjectProperties, ProjectClient> getAction(Actions actions) { - return actions.stringAdd(noProgress, text, identifier, maxLength, context, files, labelNames, isHidden); + return actions.stringAdd(noProgress, text, identifier, maxLength, context, files, labelNames, branch, isHidden); } } 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 c3fa94c98..fa8800d13 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/CliActionsTest.java @@ -49,7 +49,7 @@ public void testStatus() { @Test public void testStringAdd() { - assertNotNull(actions.stringAdd(false, null, null, null, null, null, null, null)); + assertNotNull(actions.stringAdd(false, null, null, null, null, null, null, null, null)); } @Test @@ -119,7 +119,7 @@ public void testDistributionList() { @Test public void testDistributionRelease() { - assertNotNull(actions.distributionRelease(false,true,null)); + assertNotNull(actions.distributionRelease(false,true,null, null)); } @Test diff --git a/src/test/java/com/crowdin/cli/commands/actions/DistributionAddActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/DistributionAddActionTest.java index d97021a1c..bc149f075 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/DistributionAddActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/DistributionAddActionTest.java @@ -1,6 +1,7 @@ package com.crowdin.cli.commands.actions; import com.crowdin.cli.client.ClientDistribution; +import com.crowdin.cli.client.CrowdinProjectFull; import com.crowdin.cli.client.ProjectBuilder; import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.NewAction; @@ -13,8 +14,10 @@ import com.crowdin.cli.properties.helper.TempProject; import com.crowdin.cli.utils.Utils; import com.crowdin.client.distributions.model.AddDistributionRequest; +import com.crowdin.client.distributions.model.AddDistributionStringsBasedRequest; import com.crowdin.client.distributions.model.Distribution; import com.crowdin.client.distributions.model.ExportMode; +import com.crowdin.client.projectsgroups.model.Type; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -68,8 +71,10 @@ public void testDistributionAdd(String name, ExportMode exportMode, List<String> "/%original_file_name%-CR-%locale%"))); ProjectClient projectClient = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.FILES_BASED); when(projectClient.downloadFullProject(branch)) - .thenReturn(projectBuilder.build()); + .thenReturn(build); action = new DistributionAddAction(true, true, name, exportMode, files, bundleIds, branch, projectClient); action.act(Outputter.getDefault(), pb, client); @@ -105,4 +110,38 @@ public void testAddDistributionThrows() { verifyNoMoreInteractions(client); } + @Test + public void testDistributionAdd_StringsBasedProject() { + TempProject project = new TempProject(FileHelperTest.class); + + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(project.getBasePath()); + PropertiesWithFiles pb = pbBuilder.build(); + + AddDistributionStringsBasedRequest request = new AddDistributionStringsBasedRequest(); + request.setName("My Distribution 1"); + request.setBundleIds(Arrays.asList(9)); + + ClientDistribution client = mock(ClientDistribution.class); + when(client.addDistributionStringsBased(request)) + .thenReturn(new Distribution() {{ + setName(request.getName()); + setBundleIds(request.getBundleIds()); + }}); + + ProjectBuilder projectBuilder = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())); + projectBuilder.addBranches(1L, "main"); + ProjectClient projectClient = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.STRINGS_BASED); + when(projectClient.downloadFullProject("main")) + .thenReturn(build); + + action = new DistributionAddAction(true, true, "My Distribution 1", ExportMode.BUNDLE, null, Arrays.asList(9), "main", projectClient); + action.act(Outputter.getDefault(), pb, client); + verify(client).addDistributionStringsBased(request); + verifyNoMoreInteractions(client); + } + } diff --git a/src/test/java/com/crowdin/cli/commands/actions/DistributionReleaseActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/DistributionReleaseActionTest.java index dd7f926bd..159efa812 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/DistributionReleaseActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/DistributionReleaseActionTest.java @@ -1,6 +1,9 @@ package com.crowdin.cli.commands.actions; import com.crowdin.cli.client.ClientDistribution; +import com.crowdin.cli.client.CrowdinProjectInfo; +import com.crowdin.cli.client.ProjectBuilder; +import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; import com.crowdin.cli.properties.NewPropertiesWithFilesUtilBuilder; @@ -8,6 +11,8 @@ import com.crowdin.cli.properties.PropertiesWithFiles; import com.crowdin.cli.utils.Utils; import com.crowdin.client.distributions.model.DistributionRelease; +import com.crowdin.client.distributions.model.DistributionStringsBasedRelease; +import com.crowdin.client.projectsgroups.model.Type; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -26,11 +31,17 @@ public void releaseDistributionTest_whenSuccess() { .setBasePath(Utils.PATH_SEPARATOR); PropertiesWithFiles pb = pbBuilder.build(); ClientDistribution client = mock(ClientDistribution.class); + ProjectClient projectClient = mock(ProjectClient.class); + CrowdinProjectInfo projectInfo = mock(CrowdinProjectInfo.class); + when(projectInfo.getType()) + .thenReturn(Type.FILES_BASED); + when(projectClient.downloadProjectInfo()) + .thenReturn(projectInfo); DistributionRelease distributionRelease = new DistributionRelease(); distributionRelease.setStatus("success"); when(client.release(HASH)).thenReturn(distributionRelease); - action = new DistributionReleaseAction(true, true, HASH); + action = new DistributionReleaseAction(true, true, HASH, projectClient); action.act(Outputter.getDefault(), pb, client); verify(client).release(HASH); } @@ -42,14 +53,42 @@ public void releaseDistributionTest_whenFailed() { .setBasePath(Utils.PATH_SEPARATOR); PropertiesWithFiles pb = pbBuilder.build(); ClientDistribution client = mock(ClientDistribution.class); + ProjectClient projectClient = mock(ProjectClient.class); + CrowdinProjectInfo projectInfo = mock(CrowdinProjectInfo.class); + when(projectInfo.getType()) + .thenReturn(Type.FILES_BASED); + when(projectClient.downloadProjectInfo()) + .thenReturn(projectInfo); DistributionRelease distributionRelease = new DistributionRelease(); distributionRelease.setStatus("failed"); when(client.release(any())).thenReturn(distributionRelease); when(client.getDistributionRelease(eq(HASH))).thenReturn(distributionRelease); - action = new DistributionReleaseAction(true, true, HASH); + action = new DistributionReleaseAction(true, true, HASH, projectClient); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); verify(client).release(HASH); verify(client).getDistributionRelease(HASH); } + + @Test + public void releaseDistributionTest_StringsBasedProject() { + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(Utils.PATH_SEPARATOR); + PropertiesWithFiles pb = pbBuilder.build(); + ClientDistribution client = mock(ClientDistribution.class); + ProjectClient projectClient = mock(ProjectClient.class); + CrowdinProjectInfo projectInfo = mock(CrowdinProjectInfo.class); + when(projectInfo.getType()) + .thenReturn(Type.STRINGS_BASED); + when(projectClient.downloadProjectInfo()) + .thenReturn(projectInfo); + DistributionStringsBasedRelease distributionRelease = new DistributionStringsBasedRelease(); + distributionRelease.setStatus("success"); + when(client.releaseStringsBased(HASH)).thenReturn(distributionRelease); + + action = new DistributionReleaseAction(true, true, HASH, projectClient); + action.act(Outputter.getDefault(), pb, client); + verify(client).releaseStringsBased(HASH); + } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/StringAddActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/StringAddActionTest.java index f1ba8f845..9e701368d 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/StringAddActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/StringAddActionTest.java @@ -1,5 +1,6 @@ package com.crowdin.cli.commands.actions; +import com.crowdin.cli.client.CrowdinProjectFull; import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.client.ProjectBuilder; import com.crowdin.cli.client.ResponseException; @@ -11,7 +12,9 @@ import com.crowdin.cli.properties.NewPropertiesWithFilesUtilBuilder; import com.crowdin.cli.utils.Utils; import com.crowdin.client.labels.model.Label; +import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.sourcestrings.model.AddSourceStringRequest; +import com.crowdin.client.sourcestrings.model.AddSourceStringStringsBasedRequest; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -40,7 +43,7 @@ public class StringAddActionTest { @MethodSource public void testStringAdd( String text, String identifier, Integer maxLength, String context, List<Long> labelIds, List<String> labelNames, Boolean hidden, Map<String, Long> files, String[] stringFiles - ) throws ResponseException { + ) { NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") .setBasePath(Utils.PATH_SEPARATOR); @@ -67,11 +70,13 @@ public void testStringAdd( } ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(projectBuilder.build()); + .thenReturn(build); action = - new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), labelNames, hidden); + new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), labelNames, null, hidden); action.act(Outputter.getDefault(), pb, client); verify(client).downloadFullProject(); @@ -131,11 +136,13 @@ public void testStringAdd_throwsNotFound() { } ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(projectBuilder.build()); + .thenReturn(build); action = - new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), labelNames, hidden); + new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), labelNames, null, hidden); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject(); @@ -157,7 +164,7 @@ public void testGetProjectThrows() throws ResponseException { when(client.downloadFullProject()) .thenThrow(new RuntimeException("Whoops")); - action = new StringAddAction(false, null, null, null, null, null, null, null); + action = new StringAddAction(false, null, null, null, null, null, null, null, null); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject(); @@ -205,8 +212,10 @@ public void testStringAdd_UseLabels() { } ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(projectBuilder.build()); + .thenReturn(build); List<Label> labelsResponse = labels.entrySet().stream() .map(entry -> createLabel(entry.getKey(), entry.getValue())) .collect(Collectors.toList()); @@ -215,7 +224,7 @@ public void testStringAdd_UseLabels() { action = - new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), new ArrayList<>(labels.values()), hidden); + new StringAddAction(true, text, identifier, maxLength, context, Arrays.asList(stringFiles), new ArrayList<>(labels.values()), null, hidden); action.act(Outputter.getDefault(), pb, client); verify(client).downloadFullProject(); @@ -233,4 +242,31 @@ private Label createLabel(Long id, String title) { label.setTitle(title); return label; } + + @Test + public void testStringAdd_StringsBasedProject() { + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(Utils.PATH_SEPARATOR); + PropertiesWithFiles pb = pbBuilder.build(); + AddSourceStringStringsBasedRequest request = RequestBuilder.addStringStringsBased( + "first text", "1.1", 42, "It's first text", 1L, false, null); + + ProjectBuilder projectBuilder = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).addBranches(1L, "main"); + + ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = projectBuilder.build(); + build.setType(Type.STRINGS_BASED); + when(client.downloadFullProject()) + .thenReturn(build); + + action = + new StringAddAction(true, "first text", "1.1", 42, "It's first text", null, null, "main", false); + action.act(Outputter.getDefault(), pb, client); + + verify(client).downloadFullProject(); + verify(client).addSourceStringStringsBased(request); + + verifyNoMoreInteractions(client); + } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java index 6b455ef57..ca8690978 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/StringListActionTest.java @@ -1,5 +1,6 @@ package com.crowdin.cli.commands.actions; +import com.crowdin.cli.client.CrowdinProjectFull; import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.client.ProjectBuilder; import com.crowdin.cli.client.ResponseException; @@ -10,6 +11,7 @@ import com.crowdin.cli.properties.PropertiesWithFiles; import com.crowdin.cli.properties.NewPropertiesWithFilesUtilBuilder; import com.crowdin.cli.utils.Utils; +import com.crowdin.client.projectsgroups.model.Type; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -38,9 +40,11 @@ public void testStringList(String file, String filter) throws ResponseException .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") .setBasePath(Utils.PATH_SEPARATOR); pb = pbBuilder.build(); + CrowdinProjectFull projectFull = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.csv", "csv", 101L, null, null).build(); + projectFull.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("first.csv", "csv", 101L, null, null).build()); + .thenReturn(projectFull); when(client.listSourceString(101L, null, null, filter, null)) .thenReturn(Arrays.asList(SourceStringBuilder.standard() .setProjectId(Long.parseLong(pb.getProjectId())) @@ -101,4 +105,29 @@ public void testFileNotExistThrows() throws ResponseException { verify(client).listLabels(); verifyNoMoreInteractions(client); } + + @Test + public void testStringList_StringsBasedProject() { + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(Utils.PATH_SEPARATOR); + pb = pbBuilder.build(); + CrowdinProjectFull projectFull = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.csv", "csv", 101L, null, null).build(); + projectFull.setType(Type.STRINGS_BASED); + when(client.downloadFullProject(null)) + .thenReturn(projectFull); + when(client.listSourceString(101L, null, null, null, null)) + .thenReturn(Arrays.asList(SourceStringBuilder.standard() + .setProjectId(Long.parseLong(pb.getProjectId())) + .setIdentifiers(701L, "7-0-1", "seven-o-one", "7.0.1", 101L).build())); + + action = new StringListAction(true, true, null, null, null, null); + action.act(Outputter.getDefault(), pb, client); + + verify(client).downloadFullProject(null); + verify(client).listLabels(); + verify(client).listSourceString(null, null, null, null, null); + verifyNoMoreInteractions(client); + } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/UploadSourcesActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/UploadSourcesActionTest.java index fc2519891..3624790ee 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/UploadSourcesActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/UploadSourcesActionTest.java @@ -1,5 +1,6 @@ package com.crowdin.cli.commands.actions; +import com.crowdin.cli.client.CrowdinProjectFull; import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.client.ProjectBuilder; import com.crowdin.cli.client.ResponseException; @@ -12,6 +13,7 @@ import com.crowdin.cli.properties.helper.FileHelperTest; import com.crowdin.cli.properties.helper.TempProject; import com.crowdin.cli.utils.Utils; +import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.sourcefiles.model.AddBranchRequest; import com.crowdin.client.sourcefiles.model.AddDirectoryRequest; import com.crowdin.client.sourcefiles.model.AddFileRequest; @@ -24,6 +26,8 @@ import com.crowdin.client.sourcefiles.model.PropertyFileExportOptions; import com.crowdin.client.sourcefiles.model.SpreadsheetFileImportOptions; import com.crowdin.client.sourcefiles.model.UpdateFileRequest; +import com.crowdin.client.sourcestrings.model.ImportOptions; +import com.crowdin.client.sourcestrings.model.UploadStringsRequest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,8 +65,10 @@ public void testUploadOneSource_EmptyProject() throws ResponseException { .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -98,8 +104,10 @@ public void testUploadOneSourceWithNullContentSegmentation_EmptyProject() throws pb.getFiles().get(0).setContentSegmentation(null); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -135,8 +143,10 @@ public void testUploadPropertiesFileWithEscapeQuotes_EmptyProject() throws Respo pb.getFiles().get(0).setEscapeQuotes(1); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.properties"), any())) .thenReturn(1L); @@ -174,8 +184,10 @@ public void testUploadJavaScriptFileWithExportQuotes_EmptyProject() throws Respo pb.getFiles().get(0).setExportQuotes("single"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.js"), any())) .thenReturn(1L); @@ -212,8 +224,10 @@ public void testUploadFewSourceWithDirectories_EmptyProject() throws ResponseExc .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); AddDirectoryRequest addDirectoryRequest = new AddDirectoryRequest() {{ @@ -288,8 +302,10 @@ public void testUploadOneSourceWithBranch_EmptyProject() throws ResponseExceptio .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); Branch branch = BranchBuilder.standard().setProjectId(Long.parseLong(pb.getProjectId())) @@ -332,9 +348,11 @@ public void testUploadOneSourceWithBranch_ProjectWithThatBranch() throws Respons .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addBranches(201L, "newBranch").build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addBranches(201L, "newBranch").build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -369,8 +387,10 @@ public void testUploadOneSourceWithDirectory_ProjectNotPreserveHierarchy() throw .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -406,9 +426,11 @@ public void testUploadOneSourceWithDirectory_ProjectWithPreserveHierarchy() thro PropertiesWithFiles pb = pbBuilder.build(); pb.setPreserveHierarchy(true); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addDirectory("folder", 101L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addDirectory("folder", 101L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -444,8 +466,10 @@ public void testUploadOneSourceWithDest_Project() throws ResponseException { PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setDest("last.po"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -484,15 +508,17 @@ public void testUploadOneSourceWithDestAndDeleteObsoleteOption_Project() throws pb.setPreserveHierarchy(true); pb.setProjectId("551261"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("locale.yml", "yaml", 66l, 209l, null, translationPattern) + .addFile("index.md", "yaml", 77l, 209l, null, translationPattern) + .addDirectory("docs", 207l, 215l, null) + .addDirectory("app", 215l, null, null) + .addDirectory("en", 209l, 207l, null) + .addDirectory("en", 225l, null, null) + .build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("locale.yml", "yaml", 66l, 209l, null, translationPattern) - .addFile("index.md", "yaml", 77l, 209l, null, translationPattern) - .addDirectory("docs", 207l, 215l, null) - .addDirectory("app", 215l, null, null) - .addDirectory("en", 209l, 207l, null) - .addDirectory("en", 225l, null, null) - .build()); + .thenReturn(build); when(client.uploadStorage(eq("/docs/en/index.md"), any())) .thenReturn(1L); @@ -526,9 +552,11 @@ public void testUpdateOneUploadOneSource_Project() throws ResponseException { .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.po", "gettext", 101L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("first.po", "gettext", 101L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); when(client.uploadStorage(eq("second.po"), any())) @@ -579,8 +607,10 @@ public void testAddCsvFile_EmptyProject() throws ResponseException { PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setScheme("identifier,source_phrase,context,uk,ru,fr"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.csv"), any())) .thenReturn(1L); @@ -623,8 +653,10 @@ public void testUploadOneSourceWithDest_DifferentPlaceholders_1_Project() throws PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setDest("%file_name%_file.%file_extension%"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); @@ -660,8 +692,10 @@ public void testUploadOneSourceWithDest_DifferentPlaceholders_2_Project() throws PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setDest("**/%original_file_name%"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); AddDirectoryRequest addDirectoryRequest1 = new AddDirectoryRequest() {{ @@ -705,8 +739,10 @@ public void testUploadOneSourceWithDest_DifferentPlaceholders_3_Project() throws PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setDest("%original_path%/inner/%original_file_name%"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject()) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po"), any())) .thenReturn(1L); AddDirectoryRequest addDirectoryRequest1 = new AddDirectoryRequest() {{ @@ -749,4 +785,35 @@ public void testUploadOneSourceWithDest_DifferentPlaceholders_3_Project() throws verify(client).addSource(eq(addFileRequest)); verifyNoMoreInteractions(client); } + + @Test + public void testUploadOneSource_StringBasedProject() throws ResponseException { + project.addFile(Utils.normalizePath("first.po"), "Hello, World!"); + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%") + .setBasePath(project.getBasePath()); + PropertiesWithFiles pb = pbBuilder.build(); + ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).addBranches(2L, "main").build(); + build.setType(Type.STRINGS_BASED); + when(client.downloadFullProject()) + .thenReturn(build); + when(client.uploadStorage(eq("first.po"), any())) + .thenReturn(1L); + + NewAction<PropertiesWithFiles, ProjectClient> action = new UploadSourcesAction("main", false, false, true, false, false); + action.act(Outputter.getDefault(), pb, client); + + verify(client).downloadFullProject(); + verify(client).listLabels(); + verify(client).uploadStorage(eq("first.po"), any()); + UploadStringsRequest uploadStringsRequest = new UploadStringsRequest() { + { + setStorageId(1L); + setBranchId(2L); + setImportOptions(new ImportOptions()); + }}; + verify(client).addSourceStringsBased(eq(uploadStringsRequest)); + verifyNoMoreInteractions(client); + } } diff --git a/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java index 09f68a4ed..96aadd992 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java @@ -1,5 +1,6 @@ package com.crowdin.cli.commands.actions; +import com.crowdin.cli.client.CrowdinProjectFull; import com.crowdin.cli.client.ProjectClient; import com.crowdin.cli.client.ProjectBuilder; import com.crowdin.cli.client.ResponseException; @@ -10,7 +11,9 @@ import com.crowdin.cli.properties.helper.FileHelperTest; import com.crowdin.cli.properties.helper.TempProject; import com.crowdin.cli.utils.Utils; +import com.crowdin.client.projectsgroups.model.Type; import com.crowdin.client.translations.model.UploadTranslationsRequest; +import com.crowdin.client.translations.model.UploadTranslationsStringsRequest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -49,9 +52,11 @@ public void testUploadOneOfTwoTranslation_Project() throws ResponseException { .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.po", "gettext", 301L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("first.po", "gettext", 301L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po-CR-uk-UA"), any())) .thenReturn(1L); @@ -81,9 +86,11 @@ public void testUploadBothTranslation_Project() throws ResponseException { .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.po", "gettext", 301L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("first.po", "gettext", 301L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po-CR-uk-UA"), any())) .thenReturn(1L); when(client.uploadStorage(eq("first.po-CR-ru-RU"), any())) @@ -123,8 +130,10 @@ public void testUploadOneOfTwoTranslation_EmptyProject() throws ResponseExceptio .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).build()); + .thenReturn(build); NewAction<PropertiesWithFiles, ProjectClient> action = new UploadTranslationsAction(false, null, null, false, false, false, false, false); assertThrows(RuntimeException.class, () -> action.act(Outputter.getDefault(), pb, client)); @@ -143,9 +152,11 @@ public void testUploadSpreadsheetTranslation_Project() throws ResponseException PropertiesWithFiles pb = pbBuilder.build(); pb.getFiles().get(0).setScheme("identifier,source_phrase,context,uk,ru,fr"); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("first.csv", "csv", 301L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("first.csv", "csv", 301L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.csv-CR"), any())) .thenReturn(1L); @@ -175,9 +186,11 @@ public void testUploadWithDest() throws ResponseException { .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addFile("second.po", "gettext", 301L, null, null).build(); + build.setType(Type.FILES_BASED); when(client.downloadFullProject(null)) - .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) - .addFile("second.po", "gettext", 301L, null, null).build()); + .thenReturn(build); when(client.uploadStorage(eq("first.po-CR-uk-UA"), any())) .thenReturn(1L); @@ -196,4 +209,36 @@ public void testUploadWithDest() throws ResponseException { verify(client).uploadTranslations(eq("ua"), eq(uploadTranslationRequest)); verifyNoMoreInteractions(client); } + + @Test + public void testUploadOneOfTwoTranslation_StringBasedProject() throws ResponseException { + project.addFile(Utils.normalizePath("first.po"), "Hello, World!"); + project.addFile(Utils.normalizePath("translation.po"), "Hello, World!"); + NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean("*", "translation.po") + .setBasePath(project.getBasePath()); + PropertiesWithFiles pb = pbBuilder.build(); + ProjectClient client = mock(ProjectClient.class); + CrowdinProjectFull build = ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())).addBranches(2L, "main").build(); + build.setType(Type.STRINGS_BASED); + when(client.downloadFullProject("main")) + .thenReturn(build); + when(client.uploadStorage(eq("translation.po"), any())) + .thenReturn(1L); + + NewAction<PropertiesWithFiles, ProjectClient> action = new UploadTranslationsAction(false, null, "main", false, false, false, false, false); + assertDoesNotThrow(() -> action.act(Outputter.getDefault(), pb, client)); + + verify(client).downloadFullProject("main"); + verify(client).uploadStorage(eq("translation.po"), any()); + UploadTranslationsStringsRequest uploadTranslationRequest = new UploadTranslationsStringsRequest() {{ + setStorageId(1L); + setBranchId(2L); + setImportEqSuggestions(false); + setAutoApproveImported(false); + setTranslateHidden(false); + }}; + verify(client).uploadTranslationStringsBased(eq("ua"), eq(uploadTranslationRequest)); + verifyNoMoreInteractions(client); + } } diff --git a/src/test/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommandTest.java b/src/test/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommandTest.java index 1752788b3..6edb8ea92 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommandTest.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/DistributionAddSubcommandTest.java @@ -60,10 +60,9 @@ public void testSubCommandCheckInvalidOptions(String name, ExportMode exportMode public static Stream<Arguments> testSubCommandCheckInvalidOptions() { return Stream.of( - arguments("Distribution 1", ExportMode.DEFAULT, null, null, Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.empty_file"))), - arguments("Distribution 2", ExportMode.BUNDLE, null, null, Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.empty_bundle_ids"))), - arguments("Distribution 3", ExportMode.BUNDLE, Arrays.asList("file.json"), Arrays.asList(1l), Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.incorrect_file_command_usage"))), - arguments("Distribution 4", ExportMode.DEFAULT, Arrays.asList("file.json"), Arrays.asList(1l), Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.incorrect_bundle_id_command_usage"))) + arguments("Distribution 1", ExportMode.BUNDLE, null, null, Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.empty_bundle_ids"))), + arguments("Distribution 2", ExportMode.BUNDLE, Arrays.asList("file.json"), Arrays.asList(1l), Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.incorrect_file_command_usage"))), + arguments("Distribution 3", ExportMode.DEFAULT, Arrays.asList("file.json"), Arrays.asList(1l), Arrays.asList(RESOURCE_BUNDLE.getString("error.distribution.incorrect_bundle_id_command_usage"))) ); } } diff --git a/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java b/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java index 88238549c..b9f4b566f 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/PicocliTestUtils.java @@ -72,7 +72,7 @@ void mockActions() { .thenReturn(actionMock); when(actionsMock.status(anyBoolean(), any(), any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())) .thenReturn(actionMock); - when(actionsMock.stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any())) + when(actionsMock.stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(actionMock); when(actionsMock.stringComment(anyBoolean(), anyBoolean(), any(), any(), any(), any(), any())) .thenReturn(actionMock); diff --git a/src/test/java/com/crowdin/cli/commands/picocli/StringAddSubcommandTest.java b/src/test/java/com/crowdin/cli/commands/picocli/StringAddSubcommandTest.java index 770e8e364..2d639955d 100644 --- a/src/test/java/com/crowdin/cli/commands/picocli/StringAddSubcommandTest.java +++ b/src/test/java/com/crowdin/cli/commands/picocli/StringAddSubcommandTest.java @@ -12,7 +12,7 @@ public class StringAddSubcommandTest extends PicocliTestUtils { public void testStringAdd() { this.execute(CommandNames.STRING, CommandNames.STRING_ADD, "\"Text\"", "--debug"); verify(actionsMock) - .stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any()); + .stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any(), any()); this.check(true); } @@ -25,7 +25,7 @@ public void testStringAddInvalidOptions() { public void testStringAdd2() { this.execute(CommandNames.STRING, CommandNames.STRING_ADD, "\"Text\"", "--file", "path/to/file.txt"); verify(actionsMock) - .stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any()); + .stringAdd(anyBoolean(), any(), any(), any(), any(), any(), any(), any(), any()); this.check(true); } } From 67862cbbcf70aacc28a6839c3d6bcc64b9c762f7 Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych <malutina.catya14@gmail.com> Date: Wed, 31 Jan 2024 08:34:04 +0200 Subject: [PATCH 2/5] fix upload strings action --- .../actions/DistributionReleaseAction.java | 4 +- .../commands/actions/PreTranslateAction.java | 6 +- .../actions/UploadTranslationsAction.java | 115 ++++++++++-------- .../functionality/RequestBuilder.java | 9 ++ .../commands/picocli/StringAddSubcommand.java | 2 +- .../cli/properties/PropertiesWithFiles.java | 2 +- .../resources/messages/messages.properties | 2 + .../actions/UploadTranslationsActionTest.java | 8 +- 8 files changed, 83 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java index e03183ede..4fd7a6ad3 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java @@ -62,7 +62,7 @@ private DistributionRelease releaseDistributionFilesBased(Outputter out, ClientD release = client.getDistributionRelease(hash); if ("failed".equalsIgnoreCase(release.getStatus())) { - throw new RuntimeException(RESOURCE_BUNDLE.getString("message.spinner.build_has_failed")); + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.distribution_failed")); } } @@ -92,7 +92,7 @@ private DistributionStringsBasedRelease releaseDistributionStringsBased(Outputte release = client.getDistributionStringsBasedRelease(hash); if ("failed".equalsIgnoreCase(release.getStatus())) { - throw new RuntimeException(RESOURCE_BUNDLE.getString("message.spinner.build_has_failed")); + throw new RuntimeException(RESOURCE_BUNDLE.getString("error.distribution_failed")); } } 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 39b723f8c..f82c161f9 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java @@ -79,10 +79,8 @@ public void act(Outputter out, PropertiesWithFiles properties, ProjectClient cli duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); this.applyPreTranslation(out, client, request); } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { - Branch branch = BranchUtils.getOrCreateBranch(out, branchName, client, project, false); - if (Objects.isNull(branch)) { - throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); - } + Branch branch = project.findBranchByName(branchName) + .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))); ApplyPreTranslationStringsBasedRequest request = RequestBuilder.applyPreTranslationStringsBased( languages, Collections.singletonList(branch.getId()), method, engineId, autoApproveOption, duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java index 8f6b8b392..5c86516e1 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java @@ -130,35 +130,14 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { String translation = TranslationsUtils.replaceDoubleAsterisk(file.getSource(), file.getTranslation(), fileSource); translation = placeholderUtil.replaceFileDependentPlaceholders(translation, new java.io.File(source)); if (file.getScheme() != null && !PlaceholderUtil.containsLangPlaceholders(translation)) { - java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + translation); - if (!transFile.exists()) { - if (!plainView) { - out.println(SKIPPED.withIcon(String.format( - RESOURCE_BUNDLE.getString("error.translation_not_exists"), - StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); - } - return; - } + java.io.File transFile = getTranslationFile(out, pb, translation); + if (Objects.isNull(transFile)) return; UploadTranslationsRequest request = RequestBuilder.uploadTranslations(fileId, importEqSuggestions, autoApproveImported, translateHidden); preparedRequests.put(transFile, Pair.of(languages, request)); } else { for (Language language : languages) { - LanguageMapping localLanguageMapping = - LanguageMapping.fromConfigFileLanguageMapping(file.getLanguagesMapping()); - LanguageMapping languageMapping = - LanguageMapping.populate(localLanguageMapping, serverLanguageMapping); - - String transFileName = placeholderUtil.replaceLanguageDependentPlaceholders(translation, languageMapping, language); - transFileName = PropertiesBeanUtils.useTranslationReplace(transFileName, file.getTranslationReplace()); - java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + transFileName); - if (!transFile.exists()) { - if (!plainView) { - out.println(SKIPPED.withIcon(String.format( - RESOURCE_BUNDLE.getString("error.translation_not_exists"), - StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); - } - continue; - } + java.io.File transFile = getTranslationFileWithPlaceholders(out, pb, placeholderUtil, serverLanguageMapping, file, translation, language); + if (Objects.isNull(transFile)) continue; UploadTranslationsRequest request = RequestBuilder.uploadTranslations(fileId, importEqSuggestions, autoApproveImported, translateHidden); preparedRequests.put(transFile, Pair.of(Collections.singletonList(language), request)); } @@ -171,16 +150,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { java.io.File translationFile = entry.getKey(); List<Language> langs = entry.getValue().getLeft(); UploadTranslationsRequest request = entry.getValue().getRight(); - try (InputStream fileStream = new FileInputStream(translationFile)) { - Long storageId = client.uploadStorage(translationFile.getName(), fileStream); - request.setStorageId(storageId); - } catch (Exception e) { - containsErrors.set(true); - throw new RuntimeException(String.format( - RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) - ), e); - } + request.setStorageId(uploadToStorage(pb, client, containsErrors, translationFile)); try { for (Language lang : langs) { try { @@ -211,30 +181,32 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { Map<java.io.File, Pair<List<Language>, UploadTranslationsStringsRequest>> preparedRequests = new HashMap<>(); Branch branch = project.findBranchByName(branchName) .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))); - for (Language language : languages) { - UploadTranslationsStringsRequest request = new UploadTranslationsStringsRequest(); - request.setBranchId(branch.getId()); - request.setTranslateHidden(translateHidden); - request.setAutoApproveImported(autoApproveImported); - request.setImportEqSuggestions(importEqSuggestions); - preparedRequests.put(new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + file.getTranslation()), Pair.of(Collections.singletonList(language), request)); - } + fileSourcesWithoutIgnores.forEach(source -> { + String fileSource = StringUtils.removeStart(source, pb.getBasePath()); + String translation = TranslationsUtils.replaceDoubleAsterisk(file.getSource(), file.getTranslation(), fileSource); + translation = placeholderUtil.replaceFileDependentPlaceholders(translation, new java.io.File(source)); + if (file.getScheme() != null && !PlaceholderUtil.containsLangPlaceholders(translation)) { + java.io.File transFile = getTranslationFile(out, pb, translation); + if (Objects.isNull(transFile)) return; + UploadTranslationsStringsRequest request = RequestBuilder.uploadTranslationsStrings(branch.getId(), importEqSuggestions, autoApproveImported, translateHidden); + preparedRequests.put(transFile, Pair.of(languages, request)); + } else { + for (Language language : languages) { + java.io.File transFile = getTranslationFileWithPlaceholders(out, pb, placeholderUtil, serverLanguageMapping, file, translation, language); + if (Objects.isNull(transFile)) continue; + UploadTranslationsStringsRequest request = RequestBuilder.uploadTranslationsStrings(branch.getId(), importEqSuggestions, autoApproveImported, translateHidden); + preparedRequests.put(transFile, Pair.of(Collections.singletonList(language), request)); + } + } + + }); tasks = preparedRequests.entrySet() .stream() .map(entry -> (Runnable) () -> { java.io.File translationFile = entry.getKey(); List<Language> langs = entry.getValue().getLeft(); UploadTranslationsStringsRequest request = entry.getValue().getRight(); - try (InputStream fileStream = new FileInputStream(translationFile)) { - Long storageId = client.uploadStorage(translationFile.getName(), fileStream); - request.setStorageId(storageId); - } catch (Exception e) { - containsErrors.set(true); - throw new RuntimeException(String.format( - RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), - StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) - ), e); - } + request.setStorageId(uploadToStorage(pb, client, containsErrors, translationFile)); try { for (Language lang : langs) { client.uploadTranslationStringsBased(lang.getId(), request); @@ -263,4 +235,41 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } } } + + private Long uploadToStorage(PropertiesWithFiles pb, ProjectClient client, AtomicBoolean containsErrors, java.io.File translationFile) { + try (InputStream fileStream = new FileInputStream(translationFile)) { + Long storageId = client.uploadStorage(translationFile.getName(), fileStream); + return storageId; + } catch (Exception e) { + containsErrors.set(true); + throw new RuntimeException(String.format( + RESOURCE_BUNDLE.getString("error.upload_translation_to_storage"), + StringUtils.removeStart(translationFile.getAbsolutePath(), pb.getBasePath()) + ), e); + } + } + + private java.io.File getTranslationFileWithPlaceholders(Outputter out, PropertiesWithFiles pb, PlaceholderUtil placeholderUtil, LanguageMapping serverLanguageMapping, FileBean file, String translation, Language language) { + LanguageMapping localLanguageMapping = + LanguageMapping.fromConfigFileLanguageMapping(file.getLanguagesMapping()); + LanguageMapping languageMapping = + LanguageMapping.populate(localLanguageMapping, serverLanguageMapping); + + String transFileName = placeholderUtil.replaceLanguageDependentPlaceholders(translation, languageMapping, language); + transFileName = PropertiesBeanUtils.useTranslationReplace(transFileName, file.getTranslationReplace()); + return getTranslationFile(out, pb, transFileName); + } + + private java.io.File getTranslationFile(Outputter out, PropertiesWithFiles pb, String translation) { + java.io.File transFile = new java.io.File(pb.getBasePath() + Utils.PATH_SEPARATOR + translation); + if (!transFile.exists()) { + if (!plainView) { + out.println(SKIPPED.withIcon(String.format( + RESOURCE_BUNDLE.getString("error.translation_not_exists"), + StringUtils.removeStart(transFile.getAbsolutePath(), pb.getBasePath())))); + } + return null; + } + return transFile; + } } diff --git a/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java b/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java index e3eb1a9bf..bc323cdc2 100644 --- a/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java +++ b/src/main/java/com/crowdin/cli/commands/functionality/RequestBuilder.java @@ -110,6 +110,15 @@ public static UploadTranslationsRequest uploadTranslations(Long fileId, boolean return request; } + public static UploadTranslationsStringsRequest uploadTranslationsStrings(Long branchId, boolean importEqSuggestions, boolean autoApproveImported, boolean translateHidden) { + UploadTranslationsStringsRequest request = new UploadTranslationsStringsRequest(); + request.setBranchId(branchId); + request.setImportEqSuggestions(importEqSuggestions); + request.setAutoApproveImported(autoApproveImported); + request.setTranslateHidden(translateHidden); + return request; + } + public static PatchRequest patch(Object value, PatchOperation op, String path) { PatchRequest request = new PatchRequest(); request.setValue(value); diff --git a/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java b/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java index 0b6f0faa9..9c25c170d 100644 --- a/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java +++ b/src/main/java/com/crowdin/cli/commands/picocli/StringAddSubcommand.java @@ -35,7 +35,7 @@ class StringAddSubcommand extends ActCommandProject { @CommandLine.Option(names = {"--label"}, descriptionKey = "params.label", paramLabel = "...", order = -2) protected List<String> labelNames; - @CommandLine.Option(names = {"--branch"}, descriptionKey = "branch", paramLabel = "...", order = -2) + @CommandLine.Option(names = {"-b", "--branch"}, descriptionKey = "branch", paramLabel = "...", order = -2) protected String branch; @CommandLine.Option(names = {"--hidden"}, order = -2) diff --git a/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java b/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java index 3cd1cb4b8..8b3ba4a29 100644 --- a/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java +++ b/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java @@ -65,7 +65,7 @@ public void populateWithDefaultValues(PropertiesWithFiles props) { public PropertiesBuilder.Messages checkProperties(PropertiesWithFiles props, CheckType checkType) { PropertiesBuilder.Messages messages = new PropertiesBuilder.Messages(); if (props.getFiles() == null || props.getFiles().isEmpty()) { - messages.addError(RESOURCE_BUNDLE.getString("error.config.empty_or_missed_section_files")); + messages.addWarning(RESOURCE_BUNDLE.getString("message.warning.empty_or_missed_section_files")); } else { for (FileBean fileBean : props.getFiles()) { messages.addAllErrors(FileBean.CONFIGURATOR.checkProperties(fileBean)); diff --git a/src/main/resources/messages/messages.properties b/src/main/resources/messages/messages.properties index d4f063754..84699dccf 100755 --- a/src/main/resources/messages/messages.properties +++ b/src/main/resources/messages/messages.properties @@ -541,6 +541,7 @@ error.comment_should_not_have_issue_type=Comment should not have the --issue-typ error.distribution_is_not_added=Distribution was not added error.distribution_is_not_released=Distribution was not released +error.distribution_failed=Distribution release failed error.distribution.empty_file=The '--file' value can not be empty for the 'default' export mode error.distribution.empty_bundle_ids=The '--bundle-id' value can not be empty for the 'bundle' export mode error.distribution.incorrect_file_command_usage=The '--file' is used only for the 'default' export mode @@ -747,6 +748,7 @@ message.no_manager_access=You need to have @|yellow manager access|@ in the proj message.no_manager_access_in_upload_sources=You need to have @|yellow manager access|@ in the project to apply 'excluded-languages' or/and 'delete-obsolete' options message.no_manager_access_in_upload_sources_dryrun=You need to have @|yellow manager access|@ in the project to apply 'delete-obsolete' options +message.warning.empty_or_missed_section_files=Required section 'files' is missing (or empty) in the configuration file. If you are working with a string-based project, you can ignore this message message.warning.not_yml=File @|bold '%s'|@ is not a YAML or YML file message.warning.browser_not_found=\nError opening a web browser. Please open the following link manually:\n@|bold %s|@ message.warning.file_not_uploaded_cause_of_language=Translation file @|yellow,bold '%s'|@ @|yellow hasn't been uploaded|@ since @|bold %s|@ is not enabled as a target language for the source file in your Crowdin project diff --git a/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java index 96aadd992..27d16c2f8 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/UploadTranslationsActionTest.java @@ -213,9 +213,9 @@ public void testUploadWithDest() throws ResponseException { @Test public void testUploadOneOfTwoTranslation_StringBasedProject() throws ResponseException { project.addFile(Utils.normalizePath("first.po"), "Hello, World!"); - project.addFile(Utils.normalizePath("translation.po"), "Hello, World!"); + project.addFile(Utils.normalizePath("first.po-CR-uk-UA"), "Hello, World!"); NewPropertiesWithFilesUtilBuilder pbBuilder = NewPropertiesWithFilesUtilBuilder - .minimalBuiltPropertiesBean("*", "translation.po") + .minimalBuiltPropertiesBean("*", Utils.PATH_SEPARATOR + "%original_file_name%-CR-%locale%", Arrays.asList("*-CR-*")) .setBasePath(project.getBasePath()); PropertiesWithFiles pb = pbBuilder.build(); ProjectClient client = mock(ProjectClient.class); @@ -223,14 +223,14 @@ public void testUploadOneOfTwoTranslation_StringBasedProject() throws ResponseEx build.setType(Type.STRINGS_BASED); when(client.downloadFullProject("main")) .thenReturn(build); - when(client.uploadStorage(eq("translation.po"), any())) + when(client.uploadStorage(eq("first.po-CR-uk-UA"), any())) .thenReturn(1L); NewAction<PropertiesWithFiles, ProjectClient> action = new UploadTranslationsAction(false, null, "main", false, false, false, false, false); assertDoesNotThrow(() -> action.act(Outputter.getDefault(), pb, client)); verify(client).downloadFullProject("main"); - verify(client).uploadStorage(eq("translation.po"), any()); + verify(client).uploadStorage(eq("first.po-CR-uk-UA"), any()); UploadTranslationsStringsRequest uploadTranslationRequest = new UploadTranslationsStringsRequest() {{ setStorageId(1L); setBranchId(2L); From 4fc77432eb1e5edc50337c21651af8bf84c921bd Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych <malutina.catya14@gmail.com> Date: Wed, 31 Jan 2024 12:22:31 +0200 Subject: [PATCH 3/5] manager access check in file upload --- .../cli/commands/actions/FileUploadAction.java | 11 +++++++++++ .../commands/actions/FileUploadTranslationAction.java | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java index fb9a2f9c3..13f2517d0 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java @@ -4,6 +4,7 @@ import com.crowdin.cli.commands.NewAction; import com.crowdin.cli.commands.Outputter; import com.crowdin.cli.commands.functionality.*; +import com.crowdin.cli.properties.FileBean; import com.crowdin.cli.properties.ProjectProperties; import com.crowdin.cli.utils.PlaceholderUtil; import com.crowdin.cli.utils.Utils; @@ -47,6 +48,16 @@ class FileUploadAction implements NewAction<ProjectProperties, ProjectClient> { public void act(Outputter out, ProjectProperties properties, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.plainView, this.plainView, client::downloadFullProject); + + if (!project.isManagerAccess()) { + if (!plainView) { + out.println(WARNING.withIcon(RESOURCE_BUNDLE.getString("message.no_manager_access"))); + return; + } else { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_manager_access")); + } + } + PlaceholderUtil placeholderUtil = new PlaceholderUtil(project.getSupportedLanguages(), project.getProjectLanguages(false), properties.getBasePath()); Optional<List<Long>> attachLabelIds = Optional.empty(); diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java index 5dd5b7e43..869151f0e 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java @@ -40,6 +40,15 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.plainView, this.plainView, () -> client.downloadFullProject(branchName)); + if (!project.isManagerAccess()) { + if (!plainView) { + out.println(WARNING.withIcon(RESOURCE_BUNDLE.getString("message.no_manager_access"))); + return; + } else { + throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_manager_access")); + } + } + if (!project.findLanguageById(languageId, true).isPresent()) { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.language_not_exist"), languageId)); } From 3fa8cd4cc83a92be1e6940e95cb19fefc1e28ee8 Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych <malutina.catya14@gmail.com> Date: Wed, 31 Jan 2024 15:58:48 +0200 Subject: [PATCH 4/5] return error to files section validation --- .../java/com/crowdin/cli/properties/PropertiesWithFiles.java | 2 +- src/main/resources/messages/messages.properties | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java b/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java index 8b3ba4a29..3cd1cb4b8 100644 --- a/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java +++ b/src/main/java/com/crowdin/cli/properties/PropertiesWithFiles.java @@ -65,7 +65,7 @@ public void populateWithDefaultValues(PropertiesWithFiles props) { public PropertiesBuilder.Messages checkProperties(PropertiesWithFiles props, CheckType checkType) { PropertiesBuilder.Messages messages = new PropertiesBuilder.Messages(); if (props.getFiles() == null || props.getFiles().isEmpty()) { - messages.addWarning(RESOURCE_BUNDLE.getString("message.warning.empty_or_missed_section_files")); + messages.addError(RESOURCE_BUNDLE.getString("error.config.empty_or_missed_section_files")); } else { for (FileBean fileBean : props.getFiles()) { messages.addAllErrors(FileBean.CONFIGURATOR.checkProperties(fileBean)); diff --git a/src/main/resources/messages/messages.properties b/src/main/resources/messages/messages.properties index 84699dccf..2638ca3f4 100755 --- a/src/main/resources/messages/messages.properties +++ b/src/main/resources/messages/messages.properties @@ -748,7 +748,6 @@ message.no_manager_access=You need to have @|yellow manager access|@ in the proj message.no_manager_access_in_upload_sources=You need to have @|yellow manager access|@ in the project to apply 'excluded-languages' or/and 'delete-obsolete' options message.no_manager_access_in_upload_sources_dryrun=You need to have @|yellow manager access|@ in the project to apply 'delete-obsolete' options -message.warning.empty_or_missed_section_files=Required section 'files' is missing (or empty) in the configuration file. If you are working with a string-based project, you can ignore this message message.warning.not_yml=File @|bold '%s'|@ is not a YAML or YML file message.warning.browser_not_found=\nError opening a web browser. Please open the following link manually:\n@|bold %s|@ message.warning.file_not_uploaded_cause_of_language=Translation file @|yellow,bold '%s'|@ @|yellow hasn't been uploaded|@ since @|bold %s|@ is not enabled as a target language for the source file in your Crowdin project From 1f017ad1a21f9dceb605185174a4090b53b725de Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych <malutina.catya14@gmail.com> Date: Thu, 1 Feb 2024 18:09:19 +0200 Subject: [PATCH 5/5] fix project type check --- .../com/crowdin/cli/client/CrowdinProjectClient.java | 3 ++- .../cli/commands/actions/DistributionAddAction.java | 10 ++++++---- .../commands/actions/DistributionReleaseAction.java | 6 ++++-- .../cli/commands/actions/FileDeleteAction.java | 3 ++- .../cli/commands/actions/FileDownloadAction.java | 3 ++- .../actions/FileDownloadTranslationAction.java | 3 ++- .../cli/commands/actions/FileUploadAction.java | 9 +++++---- .../actions/FileUploadTranslationAction.java | 5 +++-- .../cli/commands/actions/PreTranslateAction.java | 5 +++-- .../cli/commands/actions/StringAddAction.java | 5 +++-- .../cli/commands/actions/StringListAction.java | 8 ++++---- .../cli/commands/actions/UploadSourcesAction.java | 12 ++++++------ .../commands/actions/UploadTranslationsAction.java | 5 +++-- 13 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java index babadd4c3..3d6e7a809 100644 --- a/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java +++ b/src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java @@ -64,7 +64,8 @@ private void populateProjectWithStructure(CrowdinProjectFull project, String bra .ifPresent(project::setBranch); Long branchId = Optional.ofNullable(project.getBranch()).map(Branch::getId).orElse(null); - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + if (isStringsBasedProject) { return; } project.setFiles(executeRequestFullList((limit, offset) -> this.client.getSourceFilesApi() diff --git a/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java b/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java index ded47b1a5..d747e1426 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DistributionAddAction.java @@ -51,9 +51,11 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) this.plainView, () -> this.projectClient.downloadFullProject(this.branch) ); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + List<Long> fileIds = null; if (files != null) { - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + if (isStringsBasedProject) { throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); } Map<String, Long> projectBranches = project.getBranches().values().stream() @@ -81,12 +83,12 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) .filter(file -> files.contains(file.getPath())) .map(FileInfo::getId) .collect(Collectors.toList()); - } else if (exportMode == DEFAULT && Objects.equals(project.getType(), Type.FILES_BASED)) { + } else if (exportMode == DEFAULT && !isStringsBasedProject) { throw new RuntimeException(RESOURCE_BUNDLE.getString("error.distribution.empty_file")); } Distribution distribution = null; - if (Objects.equals(project.getType(), Type.FILES_BASED)) { + if (!isStringsBasedProject) { AddDistributionRequest addDistributionRequest = RequestBuilder.addDistribution(name, exportMode, fileIds, bundleIds); Optional.ofNullable(name).ifPresent(addDistributionRequest::setName); Optional.ofNullable(exportMode).ifPresent(addDistributionRequest::setExportMode); @@ -98,7 +100,7 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) } catch (Exception e) { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.distribution_is_not_added"), addDistributionRequest), e); } - } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + } else if (isStringsBasedProject) { AddDistributionStringsBasedRequest addDistributionRequest = new AddDistributionStringsBasedRequest(); addDistributionRequest.setName(name); if (Objects.isNull(bundleIds)) { diff --git a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java index 4fd7a6ad3..5b6ae340f 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/DistributionReleaseAction.java @@ -35,9 +35,11 @@ public void act(Outputter out, ProjectProperties pb, ClientDistribution client) this.plainView, () -> this.projectClient.downloadProjectInfo() ); - if (Objects.equals(project.getType(), Type.FILES_BASED)) { + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + + if (!isStringsBasedProject) { this.releaseDistributionFilesBased(out, client); - } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + } else { this.releaseDistributionStringsBased(out, client); } out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.distribution.released"), hash))); diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileDeleteAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileDeleteAction.java index 83babd4de..f37f7713d 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileDeleteAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileDeleteAction.java @@ -30,7 +30,8 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien CrowdinProjectFull project = ConsoleSpinner .execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", true, true, client::downloadFullProject); - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + if (isStringsBasedProject) { out.println(SKIPPED.withIcon(RESOURCE_BUNDLE.getString("message.no_file_string_project"))); return; } diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileDownloadAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileDownloadAction.java index 86b2a6c18..8b9a021e2 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileDownloadAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileDownloadAction.java @@ -35,7 +35,8 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien CrowdinProjectFull project = ConsoleSpinner .execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", false, false, () -> client.downloadFullProject(branch)); - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + if (isStringsBasedProject) { out.println(WARNING.withIcon(RESOURCE_BUNDLE.getString("message.no_file_string_project"))); return; } diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileDownloadTranslationAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileDownloadTranslationAction.java index dc2e3ff5a..5d9937b94 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileDownloadTranslationAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileDownloadTranslationAction.java @@ -39,7 +39,8 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien CrowdinProjectFull project = ConsoleSpinner .execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", false, false, client::downloadFullProject); - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); + if (isStringsBasedProject) { out.println(WARNING.withIcon(RESOURCE_BUNDLE.getString("message.no_file_string_project"))); return; } diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java index 13f2517d0..e9931e479 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileUploadAction.java @@ -48,6 +48,7 @@ class FileUploadAction implements NewAction<ProjectProperties, ProjectClient> { public void act(Outputter out, ProjectProperties properties, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.plainView, this.plainView, client::downloadFullProject); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); if (!project.isManagerAccess()) { if (!plainView) { @@ -67,7 +68,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien String fileFullPath = file.getPath(); String fileDestName = file.getName(); - if (Objects.equals(Type.FILES_BASED, project.getType())) { + if (!isStringsBasedProject) { String commonPath = SourcesUtils.getCommonPath(Collections.singletonList(this.file.getAbsolutePath()), properties.getBasePath()); final String filePath = (nonNull(dest)) ? PropertiesBeanUtils.prepareDest(dest, StringUtils.removeStart(file.getAbsolutePath(), properties.getBasePath()), placeholderUtil) @@ -121,7 +122,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien Optional<Branch> branch = Optional.empty(); if (StringUtils.isNotEmpty(branchName)) { branch = Optional.ofNullable(BranchUtils.getOrCreateBranch(out, branchName, client, project, plainView)); - } else if (Objects.equals(Type.STRINGS_BASED, project.getType())) { + } else if (isStringsBasedProject) { throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); } @@ -132,7 +133,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien excludedLanguageNames = Optional.of(filterExcludedLanguages(excludedLanguages, project)); } - if (Objects.equals(Type.FILES_BASED, project.getType())) { + if (!isStringsBasedProject) { AddFileRequest request = new AddFileRequest(); request.setName(fileDestName); request.setStorageId(storageId); @@ -152,7 +153,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien } } - if (Objects.equals(Type.STRINGS_BASED, project.getType())) { + if (isStringsBasedProject) { UploadStringsRequest request = new UploadStringsRequest(); request.setBranchId(branch.orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))).getId()); request.setCleanupMode(cleanupMode); diff --git a/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java b/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java index 869151f0e..1f56ec0ac 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java @@ -39,6 +39,7 @@ public class FileUploadTranslationAction implements NewAction<ProjectProperties, public void act(Outputter out, ProjectProperties properties, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.plainView, this.plainView, () -> client.downloadFullProject(branchName)); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); if (!project.isManagerAccess()) { if (!plainView) { @@ -53,7 +54,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.language_not_exist"), languageId)); } - if (Objects.equals(Type.FILES_BASED, project.getType())) { + if (!isStringsBasedProject) { if (Objects.isNull(dest)) throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file.dest_required"), languageId)); String sourcePath = Utils.toUnixPath(Utils.sepAtStart(dest)); @@ -72,7 +73,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien throw new RuntimeException(String.format( RESOURCE_BUNDLE.getString("error.upload_translation"), file.getPath()), e); } - } else if (Objects.equals(Type.STRINGS_BASED, project.getType())) { + } else { UploadTranslationsStringsRequest request = new UploadTranslationsStringsRequest(); Branch branch = project.findBranchByName(branchName) .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))); 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 f82c161f9..2e99ff9df 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/PreTranslateAction.java @@ -65,11 +65,12 @@ public PreTranslateAction( public void act(Outputter out, PropertiesWithFiles properties, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, this.plainView, () -> client.downloadFullProject(this.branchName)); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); List<String> languages = this.prepareLanguageIds(project); List<Long> labelIds = this.prepareLabelIds(out, client); - if (Objects.equals(project.getType(), Type.FILES_BASED)) { + if (!isStringsBasedProject) { List<Long> fileIds = this.prepareFileIds(out, properties, project); if (fileIds == null || fileIds.isEmpty()) { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.no_files_found_for_pre_translate"))); @@ -78,7 +79,7 @@ public void act(Outputter out, PropertiesWithFiles properties, ProjectClient cli languages, fileIds, method, engineId, autoApproveOption, duplicateTranslations, translateUntranslatedOnly, translateWithPerfectMatchOnly, labelIds); this.applyPreTranslation(out, client, request); - } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + } else { Branch branch = project.findBranchByName(branchName) .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project"))); ApplyPreTranslationStringsBasedRequest request = RequestBuilder.applyPreTranslationStringsBased( diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java index 1cc425b81..11c890fbe 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringAddAction.java @@ -55,11 +55,12 @@ public StringAddAction( public void act(Outputter out, ProjectProperties pb, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, false, client::downloadFullProject); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); List<Long> labelIds = (labelNames != null && !labelNames.isEmpty()) ? this.prepareLabelIds(client) : null; if (files == null || files.isEmpty()) { - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + if (isStringsBasedProject) { Branch branch = BranchUtils.getOrCreateBranch(out, branchName, client, project, false); if (Objects.isNull(branch)) { throw new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")); @@ -72,7 +73,7 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { } out.println(OK.withIcon(RESOURCE_BUNDLE.getString("message.source_string_uploaded"))); } else { - if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + if (isStringsBasedProject) { throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); } Map<String, FileInfo> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); diff --git a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java index 3601da382..b78b66ba4 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/StringListAction.java @@ -46,6 +46,7 @@ public StringListAction(boolean noProgress, boolean isVerbose, String file, Stri public void act(Outputter out, ProjectProperties pb, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, false, () -> client.downloadFullProject(this.branchName)); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); Long branchId = Optional.ofNullable(project.getBranch()) .map(Branch::getId) @@ -54,10 +55,9 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { Map<Long, String> labels = client.listLabels().stream() .collect(Collectors.toMap(Label::getId, Label::getTitle)); - boolean isFileBasedProject = Objects.equals(project.getType(), Type.FILES_BASED); Map<String, FileInfo> paths = null; Map<Long, String> reversePaths = null; - if (isFileBasedProject) { + if (!isStringsBasedProject) { paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); reversePaths = paths.entrySet() .stream() @@ -72,7 +72,7 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { if (StringUtils.isEmpty(file)) { sourceStrings = client.listSourceString(null, branchId, null, encodedFilter, encodedCroql); } else { - if (!isFileBasedProject) { + if (isStringsBasedProject) { throw new RuntimeException(RESOURCE_BUNDLE.getString("message.no_file_string_project")); } if (paths.containsKey(file)) { @@ -97,7 +97,7 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) { out.println(String.format( RESOURCE_BUNDLE.getString("message.source_string_list_context"), ss.getContext().trim().replaceAll("\n", "\n\t\t"))); } - if (isFileBasedProject && (ss.getFileId() != null)) { + if (!isStringsBasedProject && (ss.getFileId() != null)) { out.println(String.format(RESOURCE_BUNDLE.getString("message.source_string_list_file"), finalReversePaths.get(ss.getFileId()))); } if (ss.getMaxLength() != null && ss.getMaxLength() != 0) { diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java index edbd0a4a5..4f741a4ff 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadSourcesAction.java @@ -57,6 +57,7 @@ public UploadSourcesAction(String branchName, boolean deleteObsolete, boolean no public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, this.plainView, client::downloadFullProject); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); boolean containsExcludedLanguages = pb.getFiles().stream() .map(FileBean::getExcludedTargetLanguages).filter(Objects::nonNull).anyMatch(l -> !l.isEmpty()); @@ -74,12 +75,11 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { Branch branch = (branchName != null) ? BranchUtils.getOrCreateBranch(out, branchName, client, project, plainView) : null; Long branchId = (branch != null) ? branch.getId() : null; - boolean isFilesBasedProject = Objects.equals(Type.FILES_BASED, project.getType()); Map<String, Long> directoryPaths = null; Map<String, FileInfo> paths = null; DeleteObsoleteProjectFilesSubAction deleteObsoleteProjectFilesSubAction = new DeleteObsoleteProjectFilesSubAction(out, client); - if (isFilesBasedProject) { + if (!isStringsBasedProject) { directoryPaths = ProjectFilesUtils.buildDirectoryPaths(project.getDirectories(), project.getBranches()) .entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFileInfos()); @@ -175,8 +175,8 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { uploadedSources.add(fileFullPath); } - FileInfo projectFile = isFilesBasedProject ? finalPaths.get(fileFullPath) : null; - if (isFilesBasedProject && autoUpdate && projectFile != null) { + FileInfo projectFile = !isStringsBasedProject ? finalPaths.get(fileFullPath) : null; + if (!isStringsBasedProject && autoUpdate && projectFile != null) { final UpdateFileRequest request = new UpdateFileRequest(); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); request.setImportOptions(buildImportOptions(sourceFile, file, srxStorageId)); @@ -225,7 +225,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.uploading_file"), fileFullPath), e); } }; - } else if (projectFile == null && isFilesBasedProject) { + } else if (projectFile == null && !isStringsBasedProject) { final AddFileRequest request = new AddFileRequest(); request.setName(fileName); request.setExportOptions(buildExportOptions(sourceFile, file, pb.getBasePath())); @@ -282,7 +282,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { out.println(fileFullPath); } }; - } else if (Objects.equals(Type.STRINGS_BASED, project.getType())) { + } else if (isStringsBasedProject) { final UploadStringsRequest request = new UploadStringsRequest(); request.setImportOptions(buildImportOptionsStringsBased(sourceFile, file, srxStorageId)); if (file.getType() != null) { diff --git a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java index 5c86516e1..b49a35e60 100644 --- a/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java +++ b/src/main/java/com/crowdin/cli/commands/actions/UploadTranslationsAction.java @@ -67,6 +67,7 @@ public UploadTranslationsAction( public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { CrowdinProjectFull project = ConsoleSpinner.execute(out, "message.spinner.fetching_project_info", "error.collect_project_info", this.noProgress, this.plainView, () -> client.downloadFullProject(this.branchName)); + boolean isStringsBasedProject = Objects.equals(project.getType(), Type.STRINGS_BASED); if (!project.isManagerAccess()) { if (!plainView) { @@ -105,7 +106,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } List<Runnable> tasks = null; AtomicBoolean containsErrors = new AtomicBoolean(false); - if (Objects.equals(project.getType(), Type.FILES_BASED)) { + if (!isStringsBasedProject) { Map<String, File> paths = ProjectFilesUtils.buildFilePaths(project.getDirectories(), project.getBranches(), project.getFiles()); Map<java.io.File, Pair<List<Language>, UploadTranslationsRequest>> preparedRequests = new HashMap<>(); String branchPath = (StringUtils.isNotEmpty(this.branchName) ? branchName + Utils.PATH_SEPARATOR : ""); @@ -177,7 +178,7 @@ public void act(Outputter out, PropertiesWithFiles pb, ProjectClient client) { } }) .collect(Collectors.toList()); - } else if (Objects.equals(project.getType(), Type.STRINGS_BASED)) { + } else { Map<java.io.File, Pair<List<Language>, UploadTranslationsStringsRequest>> preparedRequests = new HashMap<>(); Branch branch = project.findBranchByName(branchName) .orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.branch_required_string_project")));