Translation/Translate-BCDevXliff.ps1
Function Translate-BCDevXliff() { Param( [Parameter(Position = 0, Mandatory = $true)] [String]$SourceFile, [Parameter(Position = 1, Mandatory = $true)] [String]$TargetLanguage, [switch]$ExportExcel ) if (-not (Test-Path $SourceFile)) { throw "Xliff File $SourceFile not found." } if ($TargetLanguage -notmatch '^[a-z]{2}(-[A-Z]{2})?$') { throw "Language $TargetLanguage is not valid. Use format xx-XX." } if ($SourceFile -notmatch '\.g\.xlf$') { throw "Xliff File $SourceFile is not a .g.xlf file." } Write-Verbose "Translate Xliff File: $SourceFile to $TargetLanguage." $DestXliffFile = $SourceFile -replace '.g.xlf', ".g.$TargetLanguage.xlf" $MemXliffFile = $SourceFile -replace '.g.xlf', ".memory.g.$TargetLanguage.xlf" $ShortLanguage = $TargetLanguage.split('-')[0] if (test-Path $DestXliffFile) { Rename-Item -Path $DestXliffFile -NewName $MemXliffFile -Force } $WorkDirectory = Split-Path -Path $SourceFile -Parent # Get Microsoft Dictionary try { $DictionaryFile = (Get-BCDevRef -Type Dictionary) + "/microsoft/bc-dictionary.$ShortLanguage.json" Get-ToolFile -SourceURl $DictionaryFile.ToLowerInvariant() -destination "$WorkDirectory\dictionary.json" $Dictionary = Read-BCDevDictionary -DictionaryFile "$WorkDirectory\dictionary.json" Remove-Item "$WorkDirectory\dictionary.json" -Force } catch { $Dictionary = @{} } Write-Verbose "Microsoft Dictionary: $($Dictionary.keys.Count)" # Get Bricklead Dictionary try { $DictionaryFile = (Get-BCDevRef -Type Dictionary) + "/bricklead/bricklead-dictionary.$ShortLanguage.json" Get-ToolFile -SourceURl $DictionaryFile.ToLowerInvariant() -destination "$WorkDirectory\dictionary.json" $Bricklead = Read-BCDevDictionary -DictionaryFile "$WorkDirectory\dictionary.json" Remove-Item "$WorkDirectory\dictionary.json" -Force } catch { $Bricklead = @{} } Write-Verbose "Bricklead Dictionary: $($Bricklead.keys.Count)" # Get Memory Dictionary if (test-Path $MemXliffFile) { Convert-BCDevXliffToDictionary -XliffFile $MemXliffFile -DictionaryFile "$MemXliffFile.json" -OnlyFinal $Memory = Read-BCDevDictionary -DictionaryFile "$MemXliffFile.json" Remove-Item "$MemXliffFile.json" -Force Remove-Item $MemXliffFile -Force } else { $Memory = @{} } Write-Verbose "Memory Dictionary : $($Memory.keys.Count)" $AzureDictionary = @{} # Initialize $FinalCpt = 0 $DictionaryCpt = 0 $BrickleadCpt = 0 $AzureTranslationCpt = 0 $NeedsReviewCpt = 0 $TranslatorUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=en&to=$ShortLanguage".ToLowerInvariant() $region = "westeurope" $subscriptionKey = "24msbahbXTHu8IHX22yjBb63j3sAFjL70uzO5FzWWXZUL6Fk4mkCJQQJ99BHAC5RqLJXJ3w3AAAbACOGTghg" $headers = @{ "Ocp-Apim-Subscription-Key" = $subscriptionKey "Ocp-Apim-Subscription-Region" = $region "Content-Type" = "application/json" } # Read Xliff [xml]$xlf = Get-Content $SourceFile $ns = New-Object System.Xml.XmlNamespaceManager($xlf.NameTable) $ns.AddNamespace("x", $xlf.DocumentElement.NamespaceURI) $sources = $xlf.SelectNodes("//x:source", $ns) Write-Verbose "Xliff Sources to migrate: $($sources.Count)" $xlf.xliff.file.'target-language' = $TargetLanguage # Translation Loop for ($i = 0; $i -le ($sources.Count - 1); $i++) { $target = $xlf.CreateElement("target") $Text = $sources[$i].InnerText switch ($true) { { ($Text -eq '') -or ($Text -eq ' ') } { $target.InnerText = $Text $target.SetAttribute("state", "final") $target.SetAttribute("state-qualifier", "memory") $FinalCpt += 1 break } { $Memory.ContainsKey($Text) } { $target.InnerText = $Memory[$Text] $target.SetAttribute("state", "final") $target.SetAttribute("state-qualifier", "memory") $FinalCpt += 1 break } { $Bricklead.ContainsKey($Text) } { $target.InnerText = $Bricklead[$Text] $target.SetAttribute("state", "translated") $target.SetAttribute("state-qualifier", "bricklead") $BrickleadCpt += 1 break } { $Dictionary.ContainsKey($Text) } { $target.InnerText = $Dictionary[$Text] $target.SetAttribute("state", "translated") $target.SetAttribute("state-qualifier", "microsoft") $DictionaryCpt += 1 break } default { if ($AzureDictionary.ContainsKey($Text)) { $NewText = $AzureDictionary[$Text] } else { $body = '[' + (@( @{ Text = $Text } ) | ConvertTo-Json -Compress) + ']' try { $response = Invoke-RestMethod -Method Post -Uri $TranslatorUrl -Headers $headers -Body $body $NewText = $response[0].translations[0].text $AzureTranslationCpt += 1 } catch { $NewText = $Text } $AzureDictionary.add($Text, $NewText) } $target.InnerText = $NewText $target.SetAttribute("state", "needs-review-translation") $target.SetAttribute("state-qualifier", "tm-suggestion") $NeedsReviewCpt += 1 } } $sources[$i].ParentNode.InsertAfter($target, $sources[$i]) | Out-Null } # Write Translate File $settings = New-Object System.Xml.XmlWriterSettings $settings.Indent = $true # Active l'indentation $settings.NewLineHandling = "Replace" $settings.NewLineOnAttributes = $false # Chaque élément sur sa ligne $settings.NewLineChars = "`r`n" # Saut de ligne = LF $settings.Encoding = [System.Text.Encoding]::UTF8 $writer = [System.Xml.XmlWriter]::Create($DestXliffFile, $settings) $xlf.Save($writer) $writer.Close() # Fix content $tempFile = Get-Content $DestXliffFile -Encoding UTF8 $tempFile = $tempFile.replace('source><target state', "source>`r`n <target state") $tempFile | Set-Content $DestXliffFile -Force -Encoding UTF8 # Statistics Write-Verbose "Summary of translation" Write-Verbose "Memory : $FinalCpt" Write-Verbose "Microsoft : $DictionaryCpt" Write-Verbose "Bricklead : $BrickleadCpt" Write-Verbose "New translations: $AzureTranslationCpt" Write-Verbose "Actions" Write-Verbose "Needs review : $NeedsReviewCpt" # Excel file with Azure Dictionary to translate if ($ExportExcel -and ($AzureDictionary.Count -gt 0) -and ($ShortLanguage -in @('fr', 'nl', 'pt'))) { $ExcelFile = $SourceFile -replace '.g.xlf', ".g.$ShortLanguage.xlsx" $AzureDictionary.GetEnumerator() | Sort-Object Name | Select-Object @{Name = 'Source'; Expression = { $_.Name } }, @{Name = 'Target'; Expression = { $_.Value } } | Export-Excel -Path $ExcelFile -WorksheetName "Translation" -AutoSize -Title "Translation to review" -TitleBold -AutoFilter Write-Verbose "Excel file with Azure translations to review: $ExcelFile" } } Export-ModuleMember -Function Translate-BCDevXliff # SIG # Begin signature block # MIIn2wYJKoZIhvcNAQcCoIInzDCCJ8gCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDD64kDOQhyQkGZ # 79sNJvTzVJUuNJbkecA6LhaXS1ooIKCCIOwwggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqG # SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4 # RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYg # MjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphB # cr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6p # vF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHe # HYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEd # gkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjU # jsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bR # VFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeS # LsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIV # NSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL # 6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2Zd # SoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFU # eEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/ # BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0j # BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E # PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw # DQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/ # T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQ # E7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9r # EVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y # 1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gx # dEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3t # y9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcy # tL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEB # YTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud # /v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiS # uEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZP # ubdcMIIGvzCCBKegAwIBAgIRAIFOQhehKX/tWszUF/iRrXUwDQYJKoZIhvcNAQEL # BQAwUzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKTAn # BgNVBAMTIEdsb2JhbFNpZ24gQ29kZSBTaWduaW5nIFJvb3QgUjQ1MB4XDTI0MDYx # OTAzMjUxMVoXDTM4MDcyODAwMDAwMFowWTELMAkGA1UEBhMCQkUxGTAXBgNVBAoT # EEdsb2JhbFNpZ24gbnYtc2ExLzAtBgNVBAMTJkdsb2JhbFNpZ24gR0NDIFI0NSBD # b2RlU2lnbmluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC # AgEA1kJN+eNPxiP0bB2BpjD3SD3P0OWN5SAilgdENV0Gzw8dcGDmJlT6UyNgAqhf # AgL3jsluPal4Bb2O9U8ZJJl8zxEWmx97a9Kje2hld6vYsSw/03IGMlxbrFBnLCVN # VgY2/MFiTH19hhaVml1UulDQsH+iRBnp1m5sPhPCnxHUXzRbUWgxYwr4W9Deullf # Ma+JaDhAPgjoU2dOY7Yhju/djYVBVZ4cvDfclaDEcacfG6VJbgogWX6Jo1gVlwAl # ad/ewmpQZU5T+2uhnxgeig5fVF694FvP8gwE0t4IoRAm97Lzei7CjpbBP86l2vRZ # KIw3ZaExlguOpHZ3FUmEZoIl50MKd1KxmVFC/6Gy3ZzS3BjZwYapQB1Bl2KGvKj/ # osdjFwb9Zno2lAEgiXgfkPR7qVJOak9UBiqAr57HUEL6ZQrjAfSxbqwOqOOBGag4 # yJ4DKIakdKdHlX5yWip7FWocxGnmsL5AGZnL0n1VTiKcEOChW8OzLnqLxN7xSx+M # KHkwRX9sE7Y9LP8tSooq7CgPLcrUnJiKSm1aNiwv37rL4kFKCHcYiK01YZQS86Ry # 6+42nqdRJ5E896IazPyH5ZfhUYdp6SLMg8C3D0VsB+FDT9SMSs7PY7G1pBB6+Q0M # KLBrNP4haCdv7Pj6JoRbdULNiSZ5WZ1rq2NxYpAlDQgg8f8CAwEAAaOCAYYwggGC # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8E # CDAGAQH/AgEAMB0GA1UdDgQWBBTas43AJJCja3fTDKBZ3SFnZHYLeDAfBgNVHSME # GDAWgBQfAL9GgAr8eDm3pbRD2VZQu86WOzCBkwYIKwYBBQUHAQEEgYYwgYMwOQYI # KwYBBQUHMAGGLWh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5n # cm9vdHI0NTBGBggrBgEFBQcwAoY6aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNv # bS9jYWNlcnQvY29kZXNpZ25pbmdyb290cjQ1LmNydDBBBgNVHR8EOjA4MDagNKAy # hjBodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NS5j # cmwwLgYDVR0gBCcwJTAIBgZngQwBBAEwCwYJKwYBBAGgMgEyMAwGCisGAQQBoDIK # BAIwDQYJKoZIhvcNAQELBQADggIBADIQ5LwXpYMQQJ3Tqf0nz0VyqcUfSzNZbywy # MXlxhNY2Z9WrdPzU8gY6brXWy/FCg5a9fd6VLBrtauNBHKbIiTHCWWyJvCojA1lQ # R0n9b1MOKijMSFTv8yMYW5I2TryjY9TD+wAPgNEgwsrllrrwmluqpCV6Gdv623tT # T/m2o9lj1XVfAaUo27YYKRRleZzbtOuImBRTUGAxDGazUeNuySkmZPAU0XN4xISN # PhSlklmreUFG6jTPgXZGOpF4GXO+/gb118GEOaBwTAo1AF7YKjAkHzJ3tuF837NG # QeH6bY3j4wufL0DZpToNZMm+jNEayWUgOuIA+k56ITdBcJmdUB+Ze3WQdHNNRaVO # WH/ddmqQWIlmk2Sj/lT3Tarr5SDuddeIsh0MPLyhkqBW5Ef8Zw/qeCnfj6PH2eMx # eKcLKZRrHCddISeH4qPvyECQLlwXKCXTAUQXq4DafJSoWyP8IJ6bkaGQ/7MN5XJE # LEcV89SRcib58gXjAWf3abXeBbb+KJCMf6EpO7cs2mQiaZbE9NNXDSqFxrtoaKyL # 8VJLZG6quLfsTRQc+qgUOM7sJevkYt01+bh7B10bQ2cCCGs9vyUjg4GWcwfu/lha # PDfaoNtf0pw6RpKcxCYcCTDaJeQOHZBz1B6HTmmEgZHNZX7nNfqDgGrTNB1Gp3gI # pngyJWZ6MIIG6zCCBNOgAwIBAgIMfDeOzfSMBpXQEWmrMA0GCSqGSIb3DQEBCwUA # MFkxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS8wLQYD # VQQDEyZHbG9iYWxTaWduIEdDQyBSNDUgQ29kZVNpZ25pbmcgQ0EgMjAyMDAeFw0y # NDA5MTkxMjE3MjJaFw0yNTEwMjcwODE1NTlaMFkxCzAJBgNVBAYTAkZSMREwDwYD # VQQIEwhNb3JiaWhhbjEPMA0GA1UEBxMGVmFubmVzMRIwEAYDVQQKEwlCUklDS0xF # QUQxEjAQBgNVBAMTCUJSSUNLTEVBRDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBANysgL1dmPiIH07tM4uKTz5r2+xZ0EHWijxeWhGiJAb0DvOSfJX08pqk # b3Q8MMcmSgTIggnzr68GzO8oU9JqM8+uHFJUVsAWMptAa8FxaUI0q9/8MdVKOoTk # RmyDGBMKbgDdYf+YVbLeYmsE267LQeOF1koiSmK7WRkytnjwbOZMFr/qObysIL6D # nMiM802AC4dFP1Z6hDKJuAu1mOmSZpqgBQZ4atM2TiOBw2qApZHbbur+bM2fEah2 # j46TIjTiQZ/YD7Sznuv2feHDB9h3on8MMWff8POZURkZRFbJRn8EUk/S4+3xRLE2 # ylNuYIg6gFW1QJaaUEU90ay1hLdfFJLF5WMnRyFaTaJwX3cYjP8khR/vbA966bQ4 # l0lHMbf2tLUpeMShi0vr5f1vOqSZ10qR3hzYyYMLSmj/dIHFR3ngprG5QTcjfIwF # Sdro8Aij0HYmN1tQ6HC8rV4yUJ8pDzKayQy5JDIKVYfq9jwaD45KGLUUtrot1lCP # I9Zm0Hf6lMjGBLpM16MKK8U9E8ZXz5gseqUaMJg4g34vl+gbEObOPdGtbEVicEqi # p1mSHseRHrDIOzTNA8IzI9F10csChBOlVfGZZYLZTN2DJQyhYdm6gEFzrNmBE48r # H+Fzdcf4J1VvRgDrxSAdtpVLqbe5iR996zpfb/50JtGrc3e59YmxAgMBAAGjggGx # MIIBrTAOBgNVHQ8BAf8EBAMCB4AwgZsGCCsGAQUFBwEBBIGOMIGLMEoGCCsGAQUF # BzAChj5odHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9nc2djY3I0 # NWNvZGVzaWduY2EyMDIwLmNydDA9BggrBgEFBQcwAYYxaHR0cDovL29jc3AuZ2xv # YmFsc2lnbi5jb20vZ3NnY2NyNDVjb2Rlc2lnbmNhMjAyMDBWBgNVHSAETzBNMEEG # CSsGAQQBoDIBMjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu # LmNvbS9yZXBvc2l0b3J5LzAIBgZngQwBBAEwCQYDVR0TBAIwADBFBgNVHR8EPjA8 # MDqgOKA2hjRodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjQ1Y29kZXNp # Z25jYTIwMjAuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFNqz # jcAkkKNrd9MMoFndIWdkdgt4MB0GA1UdDgQWBBT6laBcJjcU8FGox8y/wQdZCLUf # 2zANBgkqhkiG9w0BAQsFAAOCAgEAaJ+rcBMAnoJ+aDWDFOBe363c6HTqXcC5Rf4R # IJt/mbzGNBYDf6S2y+oA1q4mHJ/8TByYTKIvHKCQHFTvN1tl2zsulY7FtaeXC6PI # CPxXI5YujeYTAO6b9GMjCbxQ/IdJex6KJXuwHViTXP86G6ZwKAfczYXAmqRoC5cm # lt+XQy9bZNC5+GpKc6qvbVON1h7lWl1Y5Mm9rTvEzWNC06CRwZbhPeeFMRXs2/z9 # VtunN+S9k+uXLR/vaC2ptuZkZjacAK9GjX9Pbw+TJ1dxR8/0wq5eIXQfgEe/Q8ZR # 3LWUudZBsRWRIswUBsNjyfTI02B0vuG4tv8kuS+i45mtOPGZ5KZRquIGLjrhsOop # mbAFNOh+iBLCq1ouWoNqkqOMZq81PN3fYb4rTdKX9OogYQn0AQ4UXFsAChqEC4B1 # XhXy/TW7fRWWxZRA8HXbyvid8n/9XX7p56PFipX/HJDG85PVLg+h8CJmsjrNw6qq # 0M3949guYO79tylNhDEdI6eC5roGS4qReRsjvwYd+xUNM98oSCA8rXjMkLEZufRm # JVfJt+OiqEst933qbVeUyfN/tqbd1vpxwm1Owm5Dl0ap0GuAo01DEzlm8602Rw+Y # 7h53dsMMnQRrK4YLB6L1My2rUikqdtvzx7uUogzLDLAVR5hkpjF5DA6AeXNfpTJF # tbyN51kwggbtMIIE1aADAgECAhAKgO8YS43xBYLRxHanlXRoMA0GCSqGSIb3DQEB # CwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8G # A1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBT # SEEyNTYgMjAyNSBDQTEwHhcNMjUwNjA0MDAwMDAwWhcNMzYwOTAzMjM1OTU5WjBj # MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMT # MkRpZ2lDZXJ0IFNIQTI1NiBSU0E0MDk2IFRpbWVzdGFtcCBSZXNwb25kZXIgMjAy # NSAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EasLRLGntDqrmBW # sytXum9R/4ZwCgHfyjfMGUIwYzKomd8U1nH7C8Dr0cVMF3BsfAFI54um8+dnxk36 # +jx0Tb+k+87H9WPxNyFPJIDZHhAqlUPt281mHrBbZHqRK71Em3/hCGC5KyyneqiZ # 7syvFXJ9A72wzHpkBaMUNg7MOLxI6E9RaUueHTQKWXymOtRwJXcrcTTPPT2V1D/+ # cFllESviH8YjoPFvZSjKs3SKO1QNUdFd2adw44wDcKgH+JRJE5Qg0NP3yiSyi5Mx # gU6cehGHr7zou1znOM8odbkqoK+lJ25LCHBSai25CFyD23DZgPfDrJJJK77epTwM # P6eKA0kWa3osAe8fcpK40uhktzUd/Yk0xUvhDU6lvJukx7jphx40DQt82yepyekl # 4i0r8OEps/FNO4ahfvAk12hE5FVs9HVVWcO5J4dVmVzix4A77p3awLbr89A90/nW # GjXMGn7FQhmSlIUDy9Z2hSgctaepZTd0ILIUbWuhKuAeNIeWrzHKYueMJtItnj2Q # +aTyLLKLM0MheP/9w6CtjuuVHJOVoIJ/DtpJRE7Ce7vMRHoRon4CWIvuiNN1Lk9Y # +xZ66lazs2kKFSTnnkrT3pXWETTJkhd76CIDBbTRofOsNyEhzZtCGmnQigpFHti5 # 8CSmvEyJcAlDVcKacJ+A9/z7eacCAwEAAaOCAZUwggGRMAwGA1UdEwEB/wQCMAAw # HQYDVR0OBBYEFOQ7/PIx7f391/ORcWMZUEPPYYzoMB8GA1UdIwQYMBaAFO9vU0rp # 5AZ8esrikFb2L9RJ7MtOMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggr # BgEFBQcDCDCBlQYIKwYBBQUHAQEEgYgwgYUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBdBggrBgEFBQcwAoZRaHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5NlNI # QTI1NjIwMjVDQTEuY3J0MF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly9jcmwzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZT # SEEyNTYyMDI1Q0ExLmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s # BwEwDQYJKoZIhvcNAQELBQADggIBAGUqrfEcJwS5rmBB7NEIRJ5jQHIh+OT2Ik/b # NYulCrVvhREafBYF0RkP2AGr181o2YWPoSHz9iZEN/FPsLSTwVQWo2H62yGBvg7o # uCODwrx6ULj6hYKqdT8wv2UV+Kbz/3ImZlJ7YXwBD9R0oU62PtgxOao872bOySCI # LdBghQ/ZLcdC8cbUUO75ZSpbh1oipOhcUT8lD8QAGB9lctZTTOJM3pHfKBAEcxQF # oHlt2s9sXoxFizTeHihsQyfFg5fxUFEp7W42fNBVN4ueLaceRf9Cq9ec1v5iQMWT # FQa0xNqItH3CPFTG7aEQJmmrJTV3Qhtfparz+BW60OiMEgV5GWoBy4RVPRwqxv7M # k0Sy4QHs7v9y69NBqycz0BZwhB9WOfOu/CIJnzkQTwtSSpGGhLdjnQ4eBpjtP+XB # 3pQCtv4E5UCSDag6+iX8MmB10nfldPF9SVD7weCC3yXZi/uuhqdwkgVxuiMFzGVF # wYbQsiGnoa9F5AaAyBjFBtXVLcKtapnMG3VH3EmAp/jsJ3FVF3+d1SVDTmjFjLbN # FZUWMXuZyvgLfgyPehwJVxwC+UpX2MSey2ueIu9THFVkT+um1vshETaWyQo8gmBt # o/m3acaP9QsuLj3FNwFlTxq25+T4QwX9xa6ILs84ZPvmpovq90K8eWyG2N01c4Ih # SOxqt81nMYIGRTCCBkECAQEwaTBZMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xv # YmFsU2lnbiBudi1zYTEvMC0GA1UEAxMmR2xvYmFsU2lnbiBHQ0MgUjQ1IENvZGVT # aWduaW5nIENBIDIwMjACDHw3js30jAaV0BFpqzANBglghkgBZQMEAgEFAKCBhDAY # BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3 # AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEi # BCBvN47j1+F+8mg/vFa0GC4xqkvYmDR/dkrFzk1qmiK1+jANBgkqhkiG9w0BAQEF # AASCAgDEjEXQ4G8DhgCbWOYJoUlirGkIGqjNwb3nkEgAFt6VEHPqSU1gvVspl0ip # Z+2Fs/YOpZBWfjYsicTI4G3Ptof/L7mwz87Zcg7JM3aD5H5iwXfwqfOQVm1ivqaU # dSd0v7L1ulVhtyOR4IWAreVaLMPXQKEHA21//Zfw3Q/x+mlPLdNicMTdI+BQj3fk # sap1yZDS5m37nM8HxTY93jt5CctA9ngMqBbqpYr4VRIyrwTXkV0fClUpzjQXwb61 # 4nCGLJM+ycx022torpebOYMBJHsd4UF5dNSQhp5JtJTYgCTEdabQC/ZXL9gxN6CU # Sa2b5QBlybsC+PqeYLRW0ZxIRicbg9xEN0DPcZ3EOkqY8tjy7prLgTJqDJd4+rhg # mpp9yu5thvMxi+O+PblpGGf2V7y8m9ZJhk/ufgr3UykmkLeTOasb0X57PWkNoi/2 # ZIK/fzchAl+IyvCjbvzwHl3fi33pG4xAVnalMqn7RiKNXVAxt0vF4ByqpOkNURVN # zE4JEkIO+WPPwMmlDQKFUI57s+W8Mq/cxuSNFxoL1bcoNF+vFTDxVY4+r9kcJ/Kd # CwoVCMihO5mpIVKC3h/mWpW65X7akSv58TI3TAll3Mwk7G1+7Bhn7NpOrT3gYZ6I # 971znnWUMk8DboBm1xdo/S20qk9WDmCyyy5UFXXX0zQR0Ba0p6GCAyYwggMiBgkq # hkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5E # aWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1l # U3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAqA7xhLjfEFgtHEdqeV # dGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG # CSqGSIb3DQEJBTEPFw0yNTEwMDkxMDA5NDRaMC8GCSqGSIb3DQEJBDEiBCDmN7mn # Tk0p+Ca9RNSNe5w9KnTWsDbEHpNHGzPZDtf6LTANBgkqhkiG9w0BAQEFAASCAgCB # y4SIgxGshb4FpsQE0akK/+3EkCKBPVuCQrVoKWyp/PMS7lY6S1NsdjUk8d61NT55 # kvkZUqlI7YykPBEf8tS3YWFDttrfOE/+UyEwT06lSS4TKuSrm6cXhCVSmKdjO7eu # LyVjOfvBugQps7o1c7Eebv1SfzqKbvIieAqpy3JluL7ArP1a2gYuHIi1nptPWA1w # SJeb0vAIOAjKtaPMOye3eCULTbzuqxI7O39azF43OyUphxhZsl1IZmQqu2Fbdan/ # a7ZtT3atfGAxRHrseyLJVvdMzRoV5TN5W+bSLHzDJzGVxrtbxwjm0kEW9tyGCcuD # kZDyeipIEOjUZTtfa8VKIcFm/AcHGwHYqCBTam3KJ6YyhZmdC2CHBvGuT0PLSkZP # T86AkjzXgI+jMxNcMI/jnjd4cIduFOYJS7vtLFCY5ESZPx7VTnRBWfX3fmM+sq4f # GNCH/Ivr4R9ruGQwfvwXUsTI33tKAIeFrdza3+SG2MKjBIzSxYpYAF1YNdoDwZLf # 1sxgHrflbeUjIKuvOdIlf2bX/OHANdLtg38DIrxcDo885TNhdb42dqzBnQ4K8+AE # K+5Bt0SBaVVBAfhVUg9JS/uvdNId0wKPdhIhGYF1EduhCIf/l/ByRQ1d1bfHC2uc # 4sL0UGnSsIuFP49IujqU0tsDwMK2MvwCKfEJTNXzow== # SIG # End signature block |