ThirdPartyTMSSmartling implements ThirdPartyTMS { @Override public void pushTranslations(Repository repository, String projectId, String pluralSeparator, Map<String, String> localeMapping, String skipTextUnitsWithPattern, String skipAssetsWithPathPattern, List<String> optionList) { List<SmartlingFile> result; SmartlingOptions options = SmartlingOptions.parseList(optionList); AndroidStringDocumentMapper mapper = new AndroidStringDocumentMapper(pluralSeparator, null); result = repository.getRepositoryLocales() .stream() .map(l -> l.getLocale().getBcp47Tag()) .filter(localeTag -> !localeTag.equalsIgnoreCase(repository.getSourceLocale().getBcp47Tag())) .flatMap(localeTag -> Stream.concat( mapWithIndex(partitionSingulars(repository.getId(), localeTag, skipTextUnitsWithPattern, skipAssetsWithPathPattern), (list, batch) -> processTranslationBatch(list, batch, localeTag, mapper, repository, projectId, options, localeMapping, Prefix.SINGULAR)), mapWithIndex(partitionPlurals(repository.getId(), localeTag, skipTextUnitsWithPattern, skipAssetsWithPathPattern, options.getPluralFixForLocales()), (list, batch) -> processTranslationBatch(list, batch, localeTag, mapper, repository, projectId, options, localeMapping, Prefix.PLURAL)) )) .collect(Collectors.toList()); resultProcessor.processPushTranslations(result, options); } @Autowired  ThirdPartyTMSSmartling(SmartlingClient smartlingClient,
                                  TextUnitSearcher textUnitSearcher,
                                  AssetPathAndTextUnitNameKeys assetPathAndTextUnitNameKeys,
                                  TextUnitBatchImporterService textUnitBatchImporterService,
                                  SmartlingResultProcessor resultProcessor);  ThirdPartyTMSSmartling(SmartlingClient smartlingClient,
                                  TextUnitSearcher textUnitSearcher,
                                  AssetPathAndTextUnitNameKeys assetPathAndTextUnitNameKeys,
                                  TextUnitBatchImporterService textUnitBatchImporterService,
                                  SmartlingResultProcessor resultProcessor,
                                  int batchSize); @Override ThirdPartyTMSImage uploadImage(String projectId, String name, byte[] content); @Override List<ThirdPartyTextUnit> getThirdPartyTextUnits(Repository repository, String projectId); @Override void createImageToTextUnitMappings(String projectId, List<ThirdPartyImageToTextUnit> thirdPartyImageToTextUnits); @Override void push(Repository repository,
                     String projectId,
                     String pluralSeparator,
                     String skipTextUnitsWithPattern,
                     String skipAssetsWithPathPattern,
                     List<String> optionList); @Override void pull(Repository repository,
                     String projectId,
                     String pluralSeparator,
                     Map<String, String> localeMapping,
                     String skipTextUnitsWithPattern,
                     String skipAssetsWithPathPattern,
                     List<String> optionList); @Override void pushTranslations(Repository repository,
                                 String projectId,
                                 String pluralSeparator,
                                 Map<String, String> localeMapping,
                                 String skipTextUnitsWithPattern,
                                 String skipAssetsWithPathPattern,
                                 List<String> optionList);  }
@Test public void testPushTranslationsSingularsNoBatches() throws RepositoryLocaleCreationException, RepositoryNameAlreadyUsedException { List<SmartlingFile> result; Repository repository = repositoryService.createRepository(testIdWatcher.getEntityName("batchRepo")); Locale frCA = localeService.findByBcp47Tag("fr-CA"); Locale jaJP = localeService.findByBcp47Tag("ja-JP"); repositoryService.addRepositoryLocale(repository, frCA.getBcp47Tag()); repositoryService.addRepositoryLocale(repository, jaJP.getBcp47Tag()); TM tm = repository.getTm(); Asset asset = assetService.createAssetWithContent(repository.getId(), "fake_for_test", "fake for test"); AssetExtraction assetExtraction = new AssetExtraction(); assetExtraction.setAsset(asset); assetExtraction = assetExtractionRepository.save(assetExtraction); int textUnits = 5; for (int i = 0; i < textUnits; i++){ String name = "singular_message_test" + i; String content = "Singular Message Test #" + i; String comment = "Singular Comment" + i; TMTextUnit textUnit = tmService.addTMTextUnit(tm.getId(), asset.getId(), name, content, comment); assetExtractionService.createAssetTextUnit(assetExtraction, name, content, comment); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), frCA.getId(), String.format("%s in %s", content, frCA.getBcp47Tag())); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), jaJP.getId(), String.format("%s in %s", content, jaJP.getBcp47Tag())); } prepareAssetAndTextUnits(assetExtraction, asset, tm); tmsSmartling.pushTranslations(repository, "projectId", pluralSep, ImmutableMap.of(), null, null, ImmutableList.of()); result = resultProcessor.pushTranslationFiles; assertThat(result).hasSize(2); Stream.of(jaJP, frCA).forEach(locale -> { SmartlingFile file = result.stream() .filter(f -> f.getFileName().contains(locale.getBcp47Tag())) .findFirst() .get(); assertThat(file.getFileName()).isEqualTo(singularTargetFileName(repository, locale, 0)); assertThat(readTextUnits(file, pluralSep)).allSatisfy(tu -> { assertThat(tu.getComment()).startsWith("Singular Comment"); assertThat(tu.getName()).startsWith("singular_message_test"); assertThat(tu.getAssetPath()).isEqualTo("fake_for_test"); assertThat(tu.getTarget()).startsWith("Singular Message Test #"); assertThat(tu.getTarget()).endsWith(locale.getBcp47Tag()); }); verify(smartlingClient, times(1)).uploadLocalizedFile( eq("projectId"), eq(singularFileName(repository, 0)), eq("android"), eq(locale.getBcp47Tag()), startsWith("<?xml version="), eq(null), eq(null)); }); }
@Test public void testPushTranslationsDryRun() throws RepositoryLocaleCreationException, RepositoryNameAlreadyUsedException { List<SmartlingFile> result; Repository repository = repositoryService.createRepository(testIdWatcher.getEntityName("batchRepo")); Locale frCA = localeService.findByBcp47Tag("fr-CA"); Locale jaJP = localeService.findByBcp47Tag("ja-JP"); repositoryService.addRepositoryLocale(repository, frCA.getBcp47Tag()); repositoryService.addRepositoryLocale(repository, jaJP.getBcp47Tag()); TM tm = repository.getTm(); Asset asset = assetService.createAssetWithContent(repository.getId(), "fake_for_test", "fake for test"); AssetExtraction assetExtraction = new AssetExtraction(); assetExtraction.setAsset(asset); assetExtraction = assetExtractionRepository.save(assetExtraction); int textUnits = 5; for (int i = 0; i < textUnits; i++){ String name = "singular_message_test" + i; String content = "Singular Message Test #" + i; String comment = "Singular Comment" + i; TMTextUnit textUnit = tmService.addTMTextUnit(tm.getId(), asset.getId(), name, content, comment); assetExtractionService.createAssetTextUnit(assetExtraction, name, content, comment); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), frCA.getId(), String.format("%s in %s", content, frCA.getBcp47Tag())); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), jaJP.getId(), String.format("%s in %s", content, jaJP.getBcp47Tag())); } prepareAssetAndTextUnits(assetExtraction, asset, tm); tmsSmartling.pushTranslations(repository, "projectId", pluralSep, ImmutableMap.of(), null, null, ImmutableList.of("dry-run=true")); result = resultProcessor.pushTranslationFiles; assertThat(result).hasSize(2); Stream.of(jaJP, frCA).forEach(locale -> { SmartlingFile file = result.stream() .filter(f -> f.getFileName().contains(locale.getBcp47Tag())) .findFirst() .get(); assertThat(file.getFileName()).isEqualTo(singularTargetFileName(repository, locale, 0)); assertThat(readTextUnits(file, pluralSep)).allSatisfy(tu -> { assertThat(tu.getComment()).startsWith("Singular Comment"); assertThat(tu.getName()).startsWith("singular_message_test"); assertThat(tu.getAssetPath()).isEqualTo("fake_for_test"); assertThat(tu.getTarget()).startsWith("Singular Message Test #"); assertThat(tu.getTarget()).endsWith(locale.getBcp47Tag()); }); verify(smartlingClient, never()).uploadLocalizedFile( eq("projectId"), eq(singularFileName(repository, 0)), eq("android"), eq(locale.getBcp47Tag()), startsWith("<?xml version="), eq(null), eq(null)); }); }
@Test public void testPushTranslationsNoBatches() throws RepositoryLocaleCreationException, RepositoryNameAlreadyUsedException { List<SmartlingFile> result; Repository repository = repositoryService.createRepository(testIdWatcher.getEntityName("batchRepo")); Locale frCA = localeService.findByBcp47Tag("fr-CA"); Locale jaJP = localeService.findByBcp47Tag("ja-JP"); repositoryService.addRepositoryLocale(repository, frCA.getBcp47Tag()); repositoryService.addRepositoryLocale(repository, jaJP.getBcp47Tag()); PluralForm one = pluralFormService.findByPluralFormString("one"); TM tm = repository.getTm(); Asset asset = assetService.createAssetWithContent(repository.getId(), "fake_for_test", "fake for test"); AssetExtraction assetExtraction = new AssetExtraction(); assetExtraction.setAsset(asset); assetExtraction = assetExtractionRepository.save(assetExtraction); int textUnits = 5; for (int i = 0; i < textUnits; i++){ String name = "singular_message" + i; String content = "Singular Message Test #" + i; String comment = "Singular Comment" + i; TMTextUnit textUnit = tmService.addTMTextUnit(tm.getId(), asset.getId(), name, content, comment); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), frCA.getId(), String.format("%s in %s", content, frCA.getBcp47Tag())); tmService.addCurrentTMTextUnitVariant(textUnit.getId(), jaJP.getId(), String.format("%s in %s", content, jaJP.getBcp47Tag())); assetExtractionService.createAssetTextUnit(assetExtraction, name, content, comment); } for (int i = 0; i < textUnits; i++){ DateTime now = DateTime.now(); String name = "plural_message" + i; String content = "Plural Message Test #" + i; String comment = "Plural Comment" + i; String pluralFormOther = "plural_form_other" + i; TMTextUnit tu = tmService.addTMTextUnit(tm, asset, name, content, comment, now, one, pluralFormOther); assetExtractionService.createAssetTextUnit(assetExtraction, name, content, comment); tmService.addCurrentTMTextUnitVariant(tu.getId(), frCA.getId(), String.format("%s in %s", content, frCA.getBcp47Tag())); tmService.addCurrentTMTextUnitVariant(tu.getId(), jaJP.getId(), String.format("%s in %s", content, jaJP.getBcp47Tag())); } prepareAssetAndTextUnits(assetExtraction, asset, tm); tmsSmartling.pushTranslations(repository, "projectId", pluralSep, ImmutableMap.of(), null, null, ImmutableList.of()); result = resultProcessor.pushTranslationFiles; assertThat(result).hasSize(4); Stream.of(jaJP, frCA).forEach(locale -> { SmartlingFile singularFile = result.stream() .filter(f -> f.getFileName().matches(singularTargetFileName(repository, locale, 0))) .findFirst() .get(); SmartlingFile pluralFile = result.stream() .filter(f -> f.getFileName().matches(pluralTargetFileName(repository, locale, 0))) .findFirst() .get(); assertThat(singularFile.getFileName()).isEqualTo(singularTargetFileName(repository, locale, 0)); assertThat(readTextUnits(singularFile, pluralSep)).allSatisfy(tu -> { assertThat(tu.getComment()).startsWith("Singular Comment"); assertThat(tu.getName()).startsWith("singular_message"); assertThat(tu.getAssetPath()).isEqualTo("fake_for_test"); assertThat(tu.getTarget()).matches("Singular Message Test #\\d in " + locale.getBcp47Tag()); }); assertThat(pluralFile.getFileName()).isEqualTo(pluralTargetFileName(repository, locale, 0)); List<TextUnitDTO> plurals = readTextUnits(pluralFile, pluralSep); assertThat(plurals).hasSize(textUnits); assertThat(plurals).allSatisfy(tu -> { assertThat(tu.getName()).endsWith("_one"); assertThat(tu.getPluralForm()).isEqualTo("one"); assertThat(tu.getTarget()).matches("Plural Message Test #\\d in " + locale.getBcp47Tag()); }); verify(smartlingClient, times(1)).uploadLocalizedFile( eq("projectId"), eq(singularFileName(repository, 0)), eq("android"), eq(locale.getBcp47Tag()), startsWith("<?xml version="), eq(null), eq(null)); verify(smartlingClient, times(1)).uploadLocalizedFile( eq("projectId"), eq(pluralFileName(repository, 0)), eq("android"), eq(locale.getBcp47Tag()), startsWith("<?xml version="), eq(null), eq(null)); }); }
@Test public void testPushTranslationsPluralFix() throws RepositoryLocaleCreationException, RepositoryNameAlreadyUsedException { List<Locale> locales = new ArrayList<>(); List<SmartlingFile> result; Repository repository = repositoryService.createRepository(testIdWatcher.getEntityName("batchRepo")); Locale frCA = localeService.findByBcp47Tag("fr-CA"); Locale jaJP = localeService.findByBcp47Tag("ja-JP"); locales.add(frCA); locales.add(jaJP); repositoryService.addRepositoryLocale(repository, frCA.getBcp47Tag()); repositoryService.addRepositoryLocale(repository, jaJP.getBcp47Tag()); PluralForm one = pluralFormService.findByPluralFormString("one"); PluralForm many = pluralFormService.findByPluralFormString("many"); PluralForm other = pluralFormService.findByPluralFormString("other"); List<PluralForm> pluralForms = ImmutableList.of(one, many, other); TM tm = repository.getTm(); Asset asset = assetService.createAssetWithContent(repository.getId(), "fake_for_test", "fake for test"); AssetExtraction tmpAe = new AssetExtraction(); tmpAe.setAsset(asset); final AssetExtraction assetExtraction = assetExtractionRepository.save(tmpAe); int textUnits = 3; for (int i = 0; i < textUnits; i++){ DateTime now = DateTime.now(); String name = "plural_message" + i; String content = "Plural Message Test #" + i; String comment = "Plural Comment" + i; String pluralFormOther = name + pluralSep + other.getName(); List<TMTextUnit> tmTextUnits = pluralForms.stream() .map(pf -> tmService.addTMTextUnit(tm, asset, name + pluralSep + pf.getName(), content, comment, now, pf, pluralFormOther)) .peek(tmTextUnit -> assetExtractionService.createAssetTextUnit(assetExtraction, tmTextUnit.getName(), tmTextUnit.getContent(), tmTextUnit.getComment())) .collect(Collectors.toList()); locales.forEach(locale -> tmTextUnits.forEach(tu -> tmService.addCurrentTMTextUnitVariant(tu.getId(), locale.getId(), String.format("%s in %s", content, locale.getBcp47Tag())))); } prepareAssetAndTextUnits(assetExtraction, asset, tm); tmsSmartling.pushTranslations(repository, "projectId", pluralSep, ImmutableMap.of(), null, null, ImmutableList.of("smartling-plural-fix=" + frCA.getBcp47Tag())); result = resultProcessor.pushTranslationFiles; assertThat(result).hasSize(locales.size()); List<TextUnitDTO> jpPlurals = readTextUnits(result.stream() .filter(f -> f.getFileName().matches(pluralTargetFileName(repository, jaJP, 0))) .findFirst() .get(), pluralSep); List<TextUnitDTO> frPlurals = readTextUnits(result.stream() .filter(f -> f.getFileName().matches(pluralTargetFileName(repository, frCA, 0))) .findFirst() .get(), pluralSep); assertThat(jpPlurals).hasSize(pluralForms.size() * textUnits); assertThat(frPlurals).hasSize((pluralForms.size()-1) * textUnits); assertThat(jpPlurals.stream().map(TextUnitDTO::getPluralForm).distinct()).contains("many"); assertThat(frPlurals.stream().map(TextUnitDTO::getPluralForm).distinct()).doesNotContain("many"); locales.forEach(locale -> verify(smartlingClient, times(1)).uploadLocalizedFile( eq("projectId"), eq(pluralFileName(repository, 0)), eq("android"), eq(locale.getBcp47Tag()), startsWith("<?xml version="), eq(null), eq(null)) ); }