diff --git a/CHANGELOG.md b/CHANGELOG.md index fa55fdd..273e436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [1.5.0] 07-12-2021 + +* Added `-FormatTranslationUnit` parameter to `Test-XliffTranslations` function. (GitHub issue [#21](https://github.com/rvanbekkum/ps-xliff-sync/issues/21)) +* Added `-FormatTranslationUnit` parameter to `Sync-XliffTranslations` and `Test-BcAppXliffTranslations` functions. The latter has a default value that will print the AL object/field/action/control concerned. (GitHub issue [#21](https://github.com/rvanbekkum/ps-xliff-sync/issues/21)) +* Write parameters when `-Verbose` switch is used with `Sync-XliffTranslations` or `Test-XliffTranslations` functions. +* Use `List[]` instead of array(s) in the `Test-XliffTranslations` function. (GitHub issue [#18](https://github.com/rvanbekkum/ps-xliff-sync/issues/18)) +* Use `List[]` instead of array(s) in the `Sync-XliffTranslations` function. (GitHub issue [#18](https://github.com/rvanbekkum/ps-xliff-sync/issues/18)) +* Added parameters `-syncAdditionalParameters` and `-testAdditionalParameters` to `Test-BcAppXliffTranslations` function. (GitHub issue [#22](https://github.com/rvanbekkum/ps-xliff-sync/issues/22)) +* Fixed detected source text changes not being included in the detected issues. + +### Thank You (for 1.5.0) + +* [Jan Hoek](https://github.com/jhoek) for your [Pull Request #26 "Added -FormatTranslationUnit parameter"](https://github.com/rvanbekkum/ps-xliff-sync/pull/26) which adds the `-FormatTranslationUnit` parameter to `Test-XliffTranslations`. +* [Jan Hoek](https://github.com/jhoek) for your [Pull Request #27 "Use List[] instead of arrays"](https://github.com/rvanbekkum/ps-xliff-sync/pull/27) which changes `Test-XliffTranslations` to use lists instead of arrays. +* [Jan Hoek](https://github.com/jhoek) for your thoughts on aligning the parameters of `Test-BcAppXliffTranslations` (via DM). +* [Sergio Castelluccio](https://github.com/eclipses) for reporting `Test-BcAppXliffTranslations` not failing builds in Azure DevOps if errors are detected in a specific scenario (via DM). + ## [1.4.0] 29-11-2021 * Changes in usage of `Resolve-Path` for scenarios where the `-targetLanguage` parameter of `Sync-XliffTranslations` is used. diff --git a/README.md b/README.md index cc88af9..d0620cc 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You need to have Powershell 5.0 or newer. This module uses classes. ## Installation -You can install the module from PowerShell Gallery by running: +You can install the module from [PowerShell Gallery](https://www.powershellgallery.com/packages/XliffSync/) by running: ```powershell Install-Module -Name XliffSync @@ -73,6 +73,19 @@ When finished the function will report the number of missing translations and nu Translation units without translations will be marked with `state="needs-translation"` and translation units with a problem in the translation will be marked with a 'needs-work' state and an "XLIFF Sync"-note that explains the detected problem. The function will return the translation units with problems, which you can assign to a variable (e.g., `$unitsWithProblems`) or omit, to have the output printed. +If you use the `-printProblems` parameter, then you can use the `-FormatTranslationUnit` to specify which part of the trans-units should be printed. +The default value for this parameter is set to show the ID of the trans-unit, i.e.: + +```powershell +-FormatTranslationUnit { param($TranslationUnit) $TranslationUnit.id } +``` + +For Business Central app translation use cases, you could change this to show the XLIFF Generator note, which is also the default for [`Test-BcAppXliffTranslations`](#check-translations-of-your-microsoft-dynamics-365-business-central-apps), i.e.: + +```powershell +-FormatTranslationUnit { param($TranslationUnit) $TranslationUnit.note | Where-Object from -EQ 'Xliff Generator' | Select-Object -ExpandProperty '#text' }, +``` + Please check the documentation of the function for more information and the available parameters. ### Get XLIFF Translation Files Diff @@ -111,4 +124,11 @@ An example usage: Test-BcAppXliffTranslations -translationRulesEnableAll -AzureDevOps 'error' -printProblems ``` +This function invokes the `Sync-XliffTranslations` and `Test-XliffTranslations` functions for each XLIFF translation file in the app folder(s). +Note that you can use the `-syncAdditionalParameters` and `-testAdditionalParameters` parameters to pass arguments specific to each of these functions respectively, e.g.: + +```powershell +-syncAdditionalParameters @{ "parseFromDeveloperNote" = $true } +``` + Please check the documentation of the function for more information and the available parameters. diff --git a/XliffSync/Public/Sync-XliffTranslations.ps1 b/XliffSync/Public/Sync-XliffTranslations.ps1 index b820fc5..236f366 100644 --- a/XliffSync/Public/Sync-XliffTranslations.ps1 +++ b/XliffSync/Public/Sync-XliffTranslations.ps1 @@ -47,6 +47,9 @@ Specifies whether the command should report progress. .Parameter printProblems Specifies whether the command should print all detected problems. + .Parameter FormatTranslationUnit + A scriptblock that determines how translation units are represented in warning/error messages. + By default, the ID of the translation unit is returned. #> function Sync-XliffTranslations { Param ( @@ -83,15 +86,19 @@ function Sync-XliffTranslations { [ValidateSet('no', 'error', 'warning')] [string] $AzureDevOps = 'no', [switch] $reportProgress, - [switch] $printProblems + [switch] $printProblems, + [ValidateNotNull()] + [ScriptBlock]$FormatTranslationUnit = { param($TranslationUnit) $TranslationUnit.id } ) + Write-Verbose "Passed parameters:`n$($PsBoundParameters | Out-String)"; + # Abort if both $targetPath and $targetLanguage are missing. if (-not $targetPath -and -not $targetLanguage) { throw "Missing -targetPath or -targetLanguage parameter."; } if ($targetPath -and (-not (Test-Path $targetPath))) { - throw "File $targetPath could not be found." + throw "File $targetPath could not be found."; } Write-Host "Loading source document $sourcePath"; @@ -105,12 +112,12 @@ function Sync-XliffTranslations { [XlfDocument] $targetDocument = $null; if (-not $targetPath) { - $targetPath = (Resolve-Path $sourcePath) -replace '(\.g)?\.xlf', ".$targetLanguage.xlf" + $targetPath = (Resolve-Path $sourcePath) -replace '(\.g)?\.xlf', ".$targetLanguage.xlf"; } if (Test-Path $targetPath) { Write-Host "Loading target document $targetPath"; - $targetDocument = [XlfDocument]::LoadFromPath($targetPath); ; + $targetDocument = [XlfDocument]::LoadFromPath($targetPath); } else { Write-Host "Creating new document for language '$targetLanguage'"; $targetDocument = [XlfDocument]::CreateCopyFrom($mergedDocument, $targetLanguage); @@ -141,10 +148,10 @@ function Sync-XliffTranslations { if ($onePercentCount -eq 0) { $onePercentCount = 1; } - [System.Xml.XmlNode[]] $detectedSourceTextChanges = @(); + $detectedSourceTextChanges = New-Object -TypeName 'System.Collections.Generic.List[System.Xml.XmlNode]'; Write-Host "Processing unit nodes... (Please be patient)"; - [string] $progressMessage = "Syncing translation units." + [string] $progressMessage = "Syncing translation units."; if ($reportProgress) { if ($AzureDevOps -ne 'no') { Write-Host "##vso[task.setprogress value=0;]$progressMessage"; @@ -253,7 +260,7 @@ function Sync-XliffTranslations { if ($mergedSourceText -ne $origSourceText) { $mergedDocument.SetXliffSyncNote($unit, 'Source text has changed. Please review the translation.'); $mergedDocument.SetState($unit, [XlfTranslationState]::NeedsWorkTranslation); - $detectedSourceTextChanges += $unit; + $detectedSourceTextChanges.Add($unit); } } } @@ -269,12 +276,14 @@ function Sync-XliffTranslations { } $detectedSourceTextChanges | ForEach-Object { - Write-Host ($detectedMessage -f $_.id); + Write-Host ($detectedMessage -f (Invoke-Command -ScriptBlock $FormatTranslationUnit -ArgumentList $_)); } } } - Write-Host "Saving document to $targetPath" + Write-Host "Saving document to $targetPath"; $mergedDocument.SaveToFilePath($targetPath); + + $detectedSourceTextChanges; } Export-ModuleMember -Function Sync-XliffTranslations diff --git a/XliffSync/Public/Test-XliffTranslations.ps1 b/XliffSync/Public/Test-XliffTranslations.ps1 index a8457ac..29ac607 100644 --- a/XliffSync/Public/Test-XliffTranslations.ps1 +++ b/XliffSync/Public/Test-XliffTranslations.ps1 @@ -23,6 +23,9 @@ Specifies whether the command should report progress. .Parameter printProblems Specifies whether the command should print all detected problems. + .Parameter FormatTranslationUnit + A scriptblock that determines how translation units are represented in warning/error messages. + By default, the ID of the translation unit is returned. #> function Test-XliffTranslations { Param ( @@ -48,9 +51,12 @@ function Test-XliffTranslations { [string] $AzureDevOps = 'no', [switch] $reportProgress, [switch] $printProblems, - [switch] $PassThru + [ValidateNotNull()] + [ScriptBlock]$FormatTranslationUnit = { param($TranslationUnit) $TranslationUnit.id } ) + Write-Verbose "Passed parameters:`n$($PsBoundParameters | Out-String)" + # Abort if both $checkForMissing and $checkForProblems are missing. if (-not $checkForMissing -and -not $checkForProblems) { throw "You need to use at least one of the following parameters: -checkForMissing, -checkForProblems"; @@ -73,8 +79,8 @@ function Test-XliffTranslations { $onePercentCount = 1; } - [System.Xml.XmlNode[]] $missingTranslationUnits = @(); - [System.Xml.XmlNode[]] $needWorkTranslationUnits = @(); + $missingTranslationUnits = New-Object -TypeName 'System.Collections.Generic.List[System.Xml.XmlNode]' + $needWorkTranslationUnits = New-Object -TypeName 'System.Collections.Generic.List[System.Xml.XmlNode]' [bool] $problemResolvedInFile = $false; Write-Host "Processing unit nodes... (Please be patient)"; @@ -105,7 +111,7 @@ function Test-XliffTranslations { if ($checkForMissing) { if (HasMissingTranslation -targetDocument $targetDocument -unit $unit -missingTranslationText $missingTranslation) { $targetDocument.SetState($unit, [XlfTranslationState]::MissingTranslation); - $missingTranslationUnits += $unit; + $missingTranslationUnits.Add($unit); } } @@ -113,7 +119,7 @@ function Test-XliffTranslations { if ($checkForProblems -and $translationRules) { if (HasProblem -targetDocument $targetDocument -unit $unit -enabledRules $translationRules) { $targetDocument.SetState($unit, [XlfTranslationState]::NeedsWorkTranslation); - $needWorkTranslationUnits += $unit; + $needWorkTranslationUnits.Add($unit); } # Check for resolved problem (to delete XLIFF Sync note) @@ -136,7 +142,7 @@ function Test-XliffTranslations { } $missingTranslationUnits | ForEach-Object { - Write-Host ($detectedMessage -f $_.id); + Write-Host ($detectedMessage -f (Invoke-Command -ScriptBlock $FormatTranslationUnit -ArgumentList $_)); } } } @@ -152,7 +158,7 @@ function Test-XliffTranslations { } $needWorkTranslationUnits | ForEach-Object { - Write-Host ($detectedMessage -f $_.id); + Write-Host ($detectedMessage -f (Invoke-Command -ScriptBlock $FormatTranslationUnit -ArgumentList $_)); } } } @@ -163,7 +169,8 @@ function Test-XliffTranslations { $targetDocument.SaveToFilePath($targetPath); } - return $missingTranslationUnits + $needWorkTranslationUnits; + $missingTranslationUnits + $needWorkTranslationUnits; } function HasMissingTranslation { diff --git a/XliffSync/Public/bc/Test-BcAppXliffTranslations.ps1 b/XliffSync/Public/bc/Test-BcAppXliffTranslations.ps1 index e4dc4df..b6f0ad9 100644 --- a/XliffSync/Public/bc/Test-BcAppXliffTranslations.ps1 +++ b/XliffSync/Public/bc/Test-BcAppXliffTranslations.ps1 @@ -21,6 +21,13 @@ Specifies whether the command should print all detected problems. .Parameter printUnitsWithErrors Specifies whether the command should print the units with errors. + .Parameter FormatTranslationUnit + A scriptblock that determines how translation units are represented in warning/error messages. + By default, the ID of the translation unit is returned. + .Parameter syncAdditionalParameters + Specifies additional parameters to pass as arguments to the Sync-XliffTranslations function that is invoked by this function. + .Parameter testAdditionalParameters + Specifies additional parameters to pass as arguments to the Test-XliffTranslations function that is invoked by this function. #> function Test-BcAppXliffTranslations { Param( @@ -39,7 +46,11 @@ function Test-BcAppXliffTranslations { [string] $AzureDevOps = 'warning', [switch] $reportProgress, [switch] $printProblems, - [switch] $printUnitsWithErrors + [switch] $printUnitsWithErrors, + [ValidateNotNull()] + [ScriptBlock]$FormatTranslationUnit = { param($TranslationUnit) $TranslationUnit.note | Where-Object from -EQ 'Xliff Generator' | Select-Object -ExpandProperty '#text' }, + $syncAdditionalParameters = @{}, + $testAdditionalParameters = @{} ) if ((-not $appFolders) -or ($appFolders.Length -eq 0)) { @@ -48,7 +59,7 @@ function Test-BcAppXliffTranslations { } Sort-AppFoldersByDependencies -appFolders $appFolders -baseFolder $buildProjectFolder -WarningAction SilentlyContinue | ForEach-Object { - Write-Host "Checking translations for $_" + Write-Host "##[group]Checking translations for `"$_`"" $appProjectFolder = Join-Path $buildProjectFolder $_ $appTranslationsFolder = Join-Path $appProjectFolder "Translations" Write-Host "Retrieving translation files from $appTranslationsFolder" @@ -58,6 +69,8 @@ function Test-BcAppXliffTranslations { $allUnitsWithIssues = @() foreach ($targetXliffFile in $targetXliffFiles) { + Write-Host "##[section]Processing `"$($targetXliffFile.BaseName)`"" + $unitsWithIssues = @() [string]$AzureDevOpsSeverityForFile = $AzureDevOps if (($AzureDevOps -eq 'error') -and ($restrictErrorsToLanguages.Length -gt 0)) { if ($null -eq ($restrictErrorsToLanguages | Where-Object { $targetXliffFile.Name -match $_ })) { @@ -67,12 +80,13 @@ function Test-BcAppXliffTranslations { } Write-Host "Syncing to file $($targetXliffFile.FullName)" - Sync-XliffTranslations -sourcePath $baseXliffFile.FullName -targetPath $targetXliffFile.FullName -AzureDevOps $AzureDevOpsSeverityForFile -reportProgress:$reportProgress -printProblems:$printProblems + $unitsWithIssues += Sync-XliffTranslations -sourcePath $baseXliffFile.FullName -targetPath $targetXliffFile.FullName -AzureDevOps $AzureDevOpsSeverityForFile -reportProgress:$reportProgress -printProblems:$printProblems -FormatTranslationUnit $FormatTranslationUnit @syncAdditionalParameters Write-Host "Checking translations in file $($targetXliffFile.FullName)" - $unitsWithIssues = Test-XliffTranslations -targetPath $targetXliffFile.FullName -checkForMissing -checkForProblems -translationRules $translationRules -translationRulesEnableAll:$translationRulesEnableAll -AzureDevOps $AzureDevOpsSeverityForFile -reportProgress:$reportProgress -printProblems:$printProblems + $unitsWithIssues += Test-XliffTranslations -targetPath $targetXliffFile.FullName -checkForMissing -checkForProblems -translationRules $translationRules -translationRulesEnableAll:$translationRulesEnableAll -AzureDevOps $AzureDevOpsSeverityForFile -reportProgress:$reportProgress -FormatTranslationUnit $FormatTranslationUnit -printProblems:$printProblems @testAdditionalParameters - if ($unitsWithIssues.Count -gt 0) { - Write-Host "Issues detected in file $($targetXliffFile.FullName)." + $fileIssueCount = $unitsWithIssues.Count + if ($fileIssueCount -gt 0) { + Write-Host "$fileIssueCount issues detected in file $($targetXliffFile.FullName)." if ($printUnitsWithErrors) { Write-Host "Units with issues:" Write-Host $unitsWithIssues @@ -88,8 +102,9 @@ function Test-BcAppXliffTranslations { Write-Host "##vso[task.logissue type=warning]There are no target translation files for $($baseXliffFile.Name)" } - if (($AzureDevOps -eq 'error') -and ($allUnitsWithIssues.Count -gt 0)) { - throw "Issues detected in translation files!" + $issueCount = $allUnitsWithIssues.Count + if (($AzureDevOps -eq 'error') -and ($issueCount -gt 0)) { + throw "$issueCount issues detected in translation files!" } } } diff --git a/XliffSync/XliffSync.psd1 b/XliffSync/XliffSync.psd1 index b9ff8ac..1bc7ee8 100644 --- a/XliffSync/XliffSync.psd1 +++ b/XliffSync/XliffSync.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'XliffSync.psm1' - ModuleVersion = '1.4.0.0' + ModuleVersion = '1.5.0.0' GUID = 'a7614fd7-ce84-44db-9475-bc1f5fa4f0e5' Author = 'Rob van Bekkum' CompanyName = 'WSB Solutions B.V.'