Introduction
I made a lot of PowerShell scripts that are multi-lingual. Based on the current Windows language, the GUI is shown in that Windows language. The entries are all stored in a JSON file. The GUI is shown in English if the current Windows language is not in the JSON file.
I made that JSON file with all the translations manually with Google Translate. That was very time intensive. So, time to automate that process.
Background information
See this JSON content:
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5": "This is the last line to be translated.",
"extra" : "An extra line."
}
}
If you add the German language, you will get:
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5": "This is the last line to be translated.",
"extra" : "An extra line."
},
"de":
{
"Text 1" : "eines",
"Text 2" : "Sie können dies beliebig ändern.",
"Example 3" : "drei",
"Example 4" : "Das Teil ist zum testen.",
"something 5": "Dies ist die letzte zu übersetzende Zeile.",
"extra" : "Eine zusätzliche Zeile."
}
}
If you read the JSON file and store it in the object $JSONObject, you can use $JSONObject.de."Example 4"
to show the correct sentence in German.
Challenges
Headers
I do not know if it is the correct name, but I call "Text 1", "Text 2, "Example 3", "Example 4", "Something 5" and "extra" headers. But these headers differ per JSON file, so I must read them dynamically.
The only way to extract the headers was to convert the JSON object to a CSV object and read the column headers:
$CSVObject = @($JSONObject.psobject.Properties.Value | ConvertTo-CSV -NoTypeInformation)
$Headers = $CSVObject[0].Split(",").Replace("""","")
In version v11 this has been changed to:
$Headers = ($JSONObject.en | Get-Member -type NoteProperty).Name
Then it was very easy to read all the English values that belong to a header:
$NewJSONObject = @{}
$Array = [Ordered]@{}
ForEach ($Header in $Headers)
{
$Array += @{$Header=$JSONObject.en.$Header}
}
$NewJSONObject.Add("en",$Array)
The whole code:
$JSONObject = @'
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5": "This is the last line to be translated.",
"extra" : "An extra line."
}
}
'@ | ConvertFrom-Json
$Headers = ($JSONObject.en | Get-Member -type NoteProperty).Name
$NewJSONObject = @{}
$Array = [Ordered]@{}
ForEach ($Header in $Headers)
{
$Array += @{$Header=$JSONObject.en.$Header}
}
$NewJSONObject.Add("en",$Array)
$NewJSONObject.en."Example 4"
Translation services
The default translation service is the Google Free API. You can use that API free of charge. Unfortunately, the translations are not always 100% accurate. So there are four translation services included in this script:
- Google Free API
- Google Cloud API
- DeepL
- Microsoft Translator Service
You have to sign up for the last three. Google Cloud needs to be configured via Google. DeepL can be used free of charge with a maximum of 500.000 characters. The Microsoft Translator service needs to be configured in Azure.
Code to test Google Free translation API:
Clear-Host
Add-Type -AssemblyName System.Web
$Text = "This is not a complicated sentence, but good enough to test the translation API."
$TargetLanguage = "de"
$Uri = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=$($TargetLanguage)&dt=t&q=$Text"
$Response = Invoke-RestMethod -Uri $Uri -Method Get
$Translation = $Response[0].SyncRoot | foreach { $_[0] }
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation)
$Translation
Code to test Google Cloud API:
Clear-Host
Add-Type -AssemblyName System.Web
$key = "Your API Key"
$Text = "This is not a complicated sentence, but good enough to test the translation API."
$SourceLanguage = "en"
$TargetLanguage = "de"
$url = "https://www.googleapis.com/language/translate/v2?key=$($Key)&target=$($TargetLanguage)&source=$($SourceLanguage)&q=$($Text)"
$result = Invoke-RestMethod $url
$Translation = [System.Web.HttpUtility]::HtmlDecode($result.data.translations.translatedText)
$Translation
Code to test DeepL:
Clear-Host
Add-Type -AssemblyName System.Web
$APIKey =" Your API Key"
$textToConvert = "This item is used by other items, therefore not removed."
$translateBaseURI = "https://api-free.deepl.com/v2/translate"
$TargetLang = "fr"
$headers = @{Authorization = "DeepL-Auth-Key $APIKey"}
$Body = @{target_lang = $TargetLang}
$Body += @{source_lang = "EN"}
$Body += @{split_sentences = 0}
$Body += @{text = $textToConvert}
$Response = Invoke-RestMethod -Uri "https://api-free.deepl.com/v2/translate" -Method Post -Body $Body -Headers $headers
$Translation = [System.Web.HttpUtility]::HtmlDecode([Text.Encoding]::UTF8.GetString([Text.Encoding]::GetEncoding(28591).GetBytes($Response.translations.text)))
$Translation
Code to test Microsoft Translator Service:
Clear-Host
# API Key from https://azure.microsoft.com/en-us/services/cognitive-services/translator-text-api/
Add-Type -AssemblyName System.Web
$apiKey = "Your API Key"
$location = "Your location"
$fromLang = "en"
$toLang = "de"
$headers = @{}
$headers.Add("Ocp-Apim-Subscription-Key",$apiKey)
$headers.Add("Ocp-Apim-Subscription-Region",$location)
$headers.Add("Content-Type","application/json")
$translateBaseURI = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=$($fromLang)&to=$($toLang)"
$textToConvert = "This is not a complicated sentence, but good enough to test the translation API."
$text = @{'Text' = $($textToConvert)} | ConvertTo-Json
$conversionResult = Invoke-RestMethod -Method POST -Uri $translateBaseURI -Headers $headers -Body "[$($text)]"
$Translation = [System.Web.HttpUtility]::HtmlDecode($($conversionResult.translations[0].text))
$translation
I had one issue with DeepL: the English sentence 'This item is used by other items, therefore not removed.' was translated in French to 'Cet élément est utilisé par d'autres éléments, il n'est donc pas supprimé.' Some characters were not in the proper UTF8. This was finally solved by changing the line
[System.Web.HttpUtility]::HtmlDecode($Response.translations.text)
to
[System.Web.HttpUtility]::HtmlDecode([Text.Encoding]::UTF8.GetString([Text.Encoding]::GetEncoding(28591).GetBytes($Response.translations.text)))
Source: this article on StackOverflow
Translation languages
DeepL is the most restrictive if it comes to supported languages. So I grabbed all the supported languages from their website and put them in an array. then I used:
[CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "de*"} | Select-Object -Property Name,DisplayName
to find the real language name instead of the ISO code. All that information is stored in a hashtable. That hashtable is used to fill the CheckedListBox with the real language name.
Clear-Host
$Table = @()
$SupportedLanguages = @("bg","cs","da","de","es","fr","id","blah","it","nl","sv","el","et","fi","hu","lt","pl","ro","sk","sl","uk","zz")
ForEach ($SupportedLanguage in $SupportedLanguages)
{
$Language = ([CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$SupportedLanguage*"} | Select-Object -Property Name,DisplayName)
if($Language)
{
$Record = [ordered] @{"Code" = "";
"Display Name" = "";}
$Record."Code" = $SupportedLanguage
$Record."Display Name" = ($Language[0].DisplayName).Split(" ")[0]
$Table += New-Object PSObject -Property $Record
}
else
{
Write-Host "Don't fool me. The ISO code '$SupportedLanguage' does not exists."
}
}
$Table = $Table | Sort-Object "Display Name"
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$formTesting = New-Object 'System.Windows.Forms.Form'
$btnOk = New-Object 'System.Windows.Forms.Button'
$chkListBox = New-Object 'System.Windows.Forms.CheckedListBox'
#
# formTesting
#
$formTesting.Controls.Add($btnOk)
$formTesting.Controls.Add($chkListBox)
$formTesting.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$formTesting.AutoScaleMode = 'Font'
$formTesting.ClientSize = New-Object System.Drawing.Size(284, 242)
$formTesting.Name = 'formTesting'
$formTesting.Text = 'Testing '
#
# btnOk
#
$btnOk.Location = New-Object System.Drawing.Point(197, 203)
$btnOk.Name = 'btnOk'
$btnOk.Size = New-Object System.Drawing.Size(75, 23)
$btnOk.TabIndex = 1
$btnOk.Text = '&Ok'
$btnOk.UseVisualStyleBackColor = $True
#
# chkListBox
#
$chkListBox.FormattingEnabled = $True
$chkListBox.Location = New-Object System.Drawing.Point(12, 12)
$chkListBox.Name = 'chkListBox'
$chkListBox.Size = New-Object System.Drawing.Size(120, 214)
$chkListBox.TabIndex = 0
$chkListBox.CheckOnClick = $true
ForEach ($SupportedLanguage in $Table)
{
[void]$chkListBox.Items.Add($SupportedLanguage."Display Name")
}
$btnOk.add_Click({
[void]$formTesting.Close()
[void]$formTesting.Dispose()})
[void]$formTesting.ShowDialog()
$Result = @()
ForEach ($CheckedItem in ($chkListBox.CheckedItems))
{
$Result += $Table | Where {$_."Display Name" -eq $CheckedItem} | Select-Object -Property Code
}
ForEach ($item in $Result)
{
$FullName = ($Table | Where {$_.Code -eq $($Item.Code)} | Select-Object "Display Name")."Display Name"
Write-Host "$($Item.Code) -> $FullName"
}
Proxy
You can detect a proxy server with the command:
[System.Net.WebRequest]::GetSystemWebProxy().GetProxy([uri]"http://www.google.com/").AbsoluteUri
But... if no proxy is used, the return address is the same as the address that is mentioned after GetProxy.
$CheckServer = "http://www.google.com/"
$Result = $null
$DefaultWebProxy = [System.Net.WebRequest]::DefaultWebProxy.GetProxy([uri]($CheckServer)).AbsoluteUri
$SystemWebProxy = [System.Net.WebRequest]::GetSystemWebProxy().GetProxy([uri]$CheckServer).AbsoluteUri
if($DefaultWebProxy -ne $CheckServer)
{
$Result = $DefaultWebProxy
}
elseif($SystemWebProxy -ne $CheckServer)
{
$Result = $SystemWebProxy
}
if($Result)
{
Write-Host "The proxy server '$Result' has been found and is used."
}
else
{
Write-Host "No proxy server has been found."
}
Skip during translation and test the translation
I use variables in my scripts. And variable names may not be translated. You can recognise them as there are between less than and greater than signs. An example: <VariableName>. So it is mandatory that these items are not translated. DeepL has a non-translate class, but the free Google API has not. So I made one by myself.
Also, the generated JSON file should be checked. Sometimes, characters are handled differently per country. The English sentence "The screen height of '<DetectedHeight>' is greater than the allowed height of '<AllowedHeight>'." was translated in the Ukrain language to "Висота екрана "<DetectedHeight>" більша за дозволену висоту "<AllowedHeight>"."
Maybe you see it already, but there are double quotes where the original text has single quotes.
The code:
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation)
has been changed to:
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation).Replace([char](34),"'")
And no issues anymore.
And now, the minimized version with the above-mentioned items included. If you need a minimal version, then this is a good starting point!
# =============================================================================================================================================
# Function block
# =============================================================================================================================================
Function Get-Proxy
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 21-Sept-20222
Created by: Willem-Jan Vroom
Organization:
Functionname: Get-Proxy
=============================================================================================================================================
.SYNOPSIS
This function gets the proxy.
If a proxy server is used, the returned server name is different from the server that is checked.
#>
$CheckServer = "http://www.google.com/"
$Result = $null
$ThisFunctionName = $MyInvocation.InvocationName
$DefaultWebProxy = [System.Net.WebRequest]::DefaultWebProxy.GetProxy([uri]($CheckServer)).AbsoluteUri
$SystemWebProxy = [System.Net.WebRequest]::GetSystemWebProxy().GetProxy([uri]$CheckServer).AbsoluteUri
if($DefaultWebProxy -ne $CheckServer)
{
$Result = $DefaultWebProxy
}
elseif($SystemWebProxy -ne $CheckServer)
{
$Result = $SystemWebProxy
}
if($Result)
{
Write-Host "The proxy server '$Result' has been found and is used."
}
else
{
Write-Host "No proxy server has been found."
}
Return $Result
}
Function TranslateVia-GoogleFREEApi
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: TranslateVia-GoogleFREEApi
=============================================================================================================================================
.SYNOPSIS
This translates text from the source language to the target language, using the free Google Translation Service
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $SourceLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TargetLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TextToTranslate
)
$Uri = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=$($SourceLanguage)&tl=$($TargetLanguage)&dt=t&q=$($TextToTranslate)"
# =============================================================================================================================================
# If a proxy server is used used, add the proxy details to the Invoke-Restmethod.
# =============================================================================================================================================
if ($ProxyServer)
{
$Response = Invoke-RestMethod -Uri $Uri -Method Get -Proxy $ProxyServer -UseDefaultCredentials -ProxyUseDefaultCredentials
}
else
{
$Response = Invoke-RestMethod -Uri $Uri -Method Get
}
$Translation = $Response[0].SyncRoot | foreach { $_[0] }
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation).Replace([char](34),"'")
Write-Host "[Function TranslateVia-GoogleFREEApi] The text '$TextToTranslate' is translated from $SourceLanguage to $TargetLanguage"
Write-Host "[Function TranslateVia-GoogleFREEApi] Result: $Translation`n"
Return $Translation
}
# =============================================================================================================================================
# End function block
# =============================================================================================================================================
Clear-Host
$JSONFile = "$Env:TEMP\JasonData.json"
$NewJSONFile = "$Env:TEMP\JasonData_New.json"
@'
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5" : "This is the last line to be translated.",
"extra" : "An extra line.",
"error" : "The screen height of '<DetectedHeight>' is greater than the allowed height of '<AllowedHeight>'.",
"LongVariable" : "You can <Replace> <This> with <Whatever> <You> <Like> and it <will> <not> break the <translation>. Only a <weird> translation."
}
}
'@ | Out-File -FilePath $JSONFile
$JSONObject = Get-Content -Path $JSONFile -Raw -Encoding UTF8 | ConvertFrom-Json
$ProxyServer = Get-Proxy
# =============================================================================================================================================
# Grab all the headers. These might be different for each JSON file. So that has to dynamic.
# =============================================================================================================================================
$Headers = ($JSONObject.en | Get-Member -type NoteProperty).Name
# =============================================================================================================================================
# And a new JSON object for the translations, including the English one.
# =============================================================================================================================================
$NewJSONObject = [ordered] @{}
$SelectedLanguages = @("sl","uk","de")
# =============================================================================================================================================
# First, add the English headers to the new JSON File. That is our starting point.
# =============================================================================================================================================
$Array = [Ordered] @{}
ForEach ($Header in $Headers)
{
$Array += @{$Header=$JSONObject.en.$Header}
}
$NewJSONObject.Add("en",$Array)
# =============================================================================================================================================
# And now, add all the other selected languages.
# =============================================================================================================================================
ForEach ($Language in $SelectedLanguages)
{
$Array = [Ordered]@{}
ForEach ($Header in $Headers)
{
$TextToTranslate = $($JSONObject.en.$Header).Replace("&","")
$Replacement = @()
$Original = @()
$Counter = 0
$OldText = $TextToTranslate
While ($TextToTranslate.Contains("<") -and $TextToTranslate.Contains(">"))
{
$RandomNumber = Get-Random -Minimum 11111111 -Maximum 99999999
$Replacement += $RandomNumber
$Begin = $TextToTranslate.IndexOf("<")
$End = $TextToTranslate.IndexOf(">")
$Variable = $TextToTranslate.SubString($Begin,$End-$Begin+1)
$Original += $Variable
$TextToTranslate = $TextToTranslate.Replace($Variable,$($Replacement[$Counter]))
$Counter++
}
if($Counter -gt 0)
{
Write-Host "Old line: $OldText"
Write-Host "New line: $TextToTranslate"
}
$TranslatedText = (TranslateVia-GoogleFREEApi -SourceLanguage "en" -TargetLanguage $Language -TextToTranslate $TextToTranslate)
For ($a=0;$a -lt $Counter;$a++)
{
$TranslatedText = $TranslatedText.Replace($Replacement[$a],$Original[$a])
}
Write-Host "Put in the array: $TranslatedText"
$Array += @{$Header=$TranslatedText}
}
$NewJSONObject.Add($Language,$Array)
}
$NewJSONObject | ConvertTo-Json | % { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Out-File -FilePath $NewJSONFile -Encoding utf8
Write-Host "The file '$NewJSONFile' has been written."
# =============================================================================================================================================
# Check the created JSON File.
# =============================================================================================================================================
$bolError = $False
$Message = ""
Try
{
# =============================================================================================================================================
# If the created JSON file can be read, then there is no problem.
# =============================================================================================================================================
$Null = Get-Content -Path $NewJSONFile -Encoding UTF8 | ConvertFrom-Json
Write-Host "The JSON file '$NewJSONFile' seems to be fine. No further checks needed."
}
Catch
{
# =============================================================================================================================================
# The created JSON file cannot be read. Now, create a tmp JSON file for each language and check if that one can be read successfully.
# =============================================================================================================================================
Write-Host "There seems to be an issue with the JSON file '$NewJSONFile'. Let's check each language."
ForEach ($Language in $SelectedLanguages)
{
$JSONText = $NewJSONObject.$Language
$TempFile = New-TemporaryFile
$JSONText | ConvertTo-Json | % { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Out-File -FilePath $TempFile -Encoding utf8
Try
{
$Null = Get-Content -Path $TempFile -Encoding UTF8 | ConvertFrom-Json
$ErrorText = "The language $Language has no issues."
$Message += "`n$ErrorText"
}
Catch
{
$ErrorText = "There are issues with the language $Language. Check the created JSON file manually!"
$Message += "`n$ErrorText"
}
Remove-Item -Path $TempFile -Force
}
Write-Host $Message
}
Saving settings in the registry
If you enter the authentication key and API Domain under DeepL, Google API key under Google Cloud Translation or APIM subscription key and APIM subscription region under Microsoft Cognitive Services Translator, that information is stored in the registry under HKEY_CURRENT_USER\Software\VroomSoft\AddTranslationsToJSONFile
. If you do not want the settings to be saved, start the application with the command line option -NoUserSettings
. If you want to clear the registry use the command line option -ClearUserSettings
.
Modifications in version 2.0
I made the following changes in version 2.0:
DeepL, Google Cloud Services and Microsoft Azure Cognitive Services Translator can use their API to read the supported languages. That technique has been implemented.
Reading supported languages -> DeepL
Clear-Host
# API Key from https://www.deepl.com/pro-checkout/account?productId=1200&yearly=false&trial=false
# Credit card required in order to prevent misuse of our free API, in particular to prevent fraudulent multiple registrations.
$APIKey = "Your API Key"
$translateBaseURI = "https://api-free.deepl.com/v2/languages?type=target"
$headers = @{Authorization = "DeepL-Auth-Key $APIKey"}
Try
{
$Response = @((Invoke-RestMethod -Uri $translateBaseURI -Method Post -Headers $headers).Language)
$Response = $Response | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
$Response
}
Catch
{
$_.Exception.Message
}
Reading supported languages -> Google Cloud Services
Clear-Host
$key = "Your API Key"
$url = "https://translation.googleapis.com/language/translate/v2/languages?key=$($key)"
Try
{
$result = Invoke-WebRequest -Uri $url -Method Get
$Content = $result | Select-Object -ExpandProperty Content
$Response = ((ConvertFrom-Json -InputObject $Content).data.languages).language
$Response = $Response | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
$Response
}
Catch
{
$_.Exception.Message
}
Reading supported languages -> Microsoft Azure Cognitive Services Translator
Clear-Host
$translateBaseURI = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0"
$conversionResult = Invoke-RestMethod -Method Get -Uri $translateBaseURI
$Response = ($conversionResult.translation | Get-Member -type NoteProperty).Name | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
$Response
Reading supported languages -> Google FREE API
Only Google FREE API cannot use the API to read the supported languages. I had to use their website instead:

With the use of the inspector I found the class:

Then it was relatively easy to implement as I knew the CSS:
# Source for solution: https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/find-multiple-matches
$Content = invoke-restmethod https://cloud.google.com/translate/docs/languages
$LookFor = "<code translate=""no"" dir=""ltr"">.*</code>"
$Languages = @(($Content | Select-String -AllMatches $LookFor | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value).Replace("<code translate=""no"" dir=""ltr"">","").Replace("</code>",""))
$Languages = $Languages | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
$Languages
Modifications in version 2.1
The function Check-WorkingInternetConnection has been rewritten: when the internet was reachable, it came back with an error. Test-NetConnection and Test-Connection do not work when a proxy server is used, so I had to find an alternative.
And that is $Status = (New-Object System.Net.NetworkInformation.Ping).SendPingAsync("www.google.com")
followed by [Threading.Tasks.Task]::WaitAll($Status)
. There is a working internet connection if the last command is run successfully.
Function Check-WorkingInternetConnection
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 09-July-2020 / Modified 04-Oct-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Check-WorkingInternetConnection
=============================================================================================================================================
.SYNOPSIS
Check for a working internet connection.
(New-Object System.Net.NetworkInformation.Ping).SendPingAsync("www.google.com") works also when a proxy server is used.
[Threading.Tasks.Task]::WaitAll($Status) will thrown an error if the host cannot be reached.
Test-NetConnection and Test-Connection do not work if a proxy server is used.
#>
Param
(
[String] $HostNameToCheck = "www.google.com"
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
$HostNameToCheck = $HostNameToCheck.Replace("https://","").Replace("http://","") # Remove https:// or http://
$HostNameToCheck = $HostNameToCheck.Replace("/","") # Remove a trailing / if needed.
Try
{
$Status = (New-Object System.Net.NetworkInformation.Ping).SendPingAsync($HostNameToCheck)
[Threading.Tasks.Task]::WaitAll($Status)
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Details:"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Result: $($Status.Result.Status)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Faulted: $($Status.Isfaulted)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Is Completed: $($Status.IsCompleted)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The host $HostNameToCheck can be reached. Thus there is a working internet connection."
$Result = $True
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The host $HostNameToCheck cannot be reached. Thus there is no working internet connection."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error: $($Status.Exception)"
$Result = $False
}
Return $Result
}
Modifications in version 2.2
There are three changes:
- Changed the date notation of the logfile to yyyy-MM-dd HH-mm-ss, for example, '2022-11-14 22-23-09'.
- Changed the date notation of the JSON file with the translations to yyyy-MM-dd HH-mm-ss, for example, '2022-11-14 22-23-09'.
- The function 'UserDetails' has been modified.
Background information
You can run this script in two modes:
- Silent:
Use the command line options-Silent
,-JSONFilename
to specify the JSON file with the English headers and-LanguagesToInclude
to specify the translation languages. If you use-all
then all the languages are selected and used. If you have used this application before and the license information is stored in the registry then you can add the parameter-TranslatorService
to specify which translator service you want to use. If there is no license information available in the registry then the Google Free API will be used instead. - Non-silent (default mode):
The GUI is used. However, you can still specify-ClearUserSettings
or-NoUserSettings
.
Get-Help "AddTranslationsToJSONFile v22.ps1" -Detailed
shows the following output:
NAME
C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1
SYNOPSIS
Translates the contents of a JSON File.
SYNTAX
C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1 [-DetailedLogging] [-ClearUserSettings]
[-NoUserSettings] [-Silent] [-JSONFilename <String>] [-LanguagesToInclude <String[]>] [-TranslatorService
<String>] [<CommonParameters>]
C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1 [-DetailedLogging] [-ClearUserSettings]
[-NoUserSettings] -Silent -JSONFilename <String> -LanguagesToInclude <String[]> [-TranslatorService <String>]
[<CommonParameters>]
DESCRIPTION
Consider the following JSON File with the following content:
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5": "This is the last line to be translated.",
"extra" : "An extra line."
}
}
The content of the values "one", "You can change this to whatever you like.", "three" etc. is translated to the
selected languages
using either Google Translate (FREE API), Google Cloud Translate, Microsoft Azure Cognitive Services Translator or
DeepL.
The keys "Test 1", "Test 2" etc. can be whatever you like. You are not sticked to these keys.
If the -Silent switch is used, then the translation is done via Google Translate FREE API.
This script can only be used when PowerShell FullLanguage is used. You will get an error message if that is not
the case.
PARAMETERS
-DetailedLogging [<SwitchParameter>]
-ClearUserSettings [<SwitchParameter>]
-NoUserSettings [<SwitchParameter>]
-Silent [<SwitchParameter>]
-JSONFilename <String>
-LanguagesToInclude <String[]>
-TranslatorService <String>
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (https:/go.microsoft.com/fwlink/?LinkID=113216).
-------------------------- EXAMPLE 1 --------------------------
PS C:\>Start the application and show the GUI.
."AddTranslationsToJSONFile v22.ps1"
-------------------------- EXAMPLE 2 --------------------------
PS C:\>Start the application and show the GUI with verbose logging on the screen.
."AddTranslationsToJSONFile v22.ps1" -Verbose
-------------------------- EXAMPLE 3 --------------------------
PS C:\>Start the application and show the GUI with detailed logging to a log file in %TEMP%
."AddTranslationsToJSONFile v22.ps1" -DetailedLogging
-------------------------- EXAMPLE 4 --------------------------
PS C:\>Start the application, show the GUI with detailed logging to a log file in %TEMP% and clear the settings
before starting.
."AddTranslationsToJSONFile v22.ps1" -DetailedLogging -ClearUserSettings
-------------------------- EXAMPLE 5 --------------------------
PS C:\>Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" to Dutch,
French, Spanish, Indonesian
and German.
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude
nl,fr,es,id,de
LanguagesToInclude can be any of these: bg|cs|da|de|es|fr|id|it|nl|sv|el|et|fi|hu|lt|pl|ro|sk|sl|uk
-------------------------- EXAMPLE 6 --------------------------
PS C:\>Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" in all
available languages.
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude all
-------------------------- EXAMPLE 7 --------------------------
PS C:\>Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" in all
available languages. Use DeepL
as the translation service
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude all
-TranslatorService DeepL
REMARKS
To see the examples, type: "get-help C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1
-examples".
For more information, type: "get-help C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1
-detailed".
For technical information, type: "get-help C:\tmp\AddTranslationsToJSONFile v22\AddTranslationsToJSONFile v22.ps1
-full".
The script
<#
.SYNOPSIS
Translates the contents of a JSON File.
.DESCRIPTION
Consider the following JSON File with the following content:
{
"en" :
{
"Text 1" : "one",
"Text 2" : "You can change this to whatever you like.",
"Example 3" : "three",
"Example 4" : "The part is for test.",
"something 5": "This is the last line to be translated.",
"extra" : "An extra line."
}
}
The content of the values "one", "You can change this to whatever you like.", "three" etc. is translated to the selected languages
using either Google Translate (FREE API), Google Cloud Translate, Microsoft Azure Cognitive Services Translator or DeepL.
The keys "Test 1", "Test 2" etc. can be whatever you like. You are not sticked to these keys.
If the -Silent switch is used, then the translation is done via Google Translate FREE API.
This script can only be used when PowerShell FullLanguage is used. You will get an error message if that is not the case.
.EXAMPLE
Start the application and show the GUI.
."AddTranslationsToJSONFile v22.ps1"
.EXAMPLE
Start the application and show the GUI with verbose logging on the screen.
."AddTranslationsToJSONFile v22.ps1" -Verbose
.EXAMPLE
Start the application and show the GUI with detailed logging to a log file in %TEMP%
."AddTranslationsToJSONFile v22.ps1" -DetailedLogging
.EXAMPLE
Start the application, show the GUI with detailed logging to a log file in %TEMP% and clear the settings before starting.
."AddTranslationsToJSONFile v22.ps1" -DetailedLogging -ClearUserSettings
.EXAMPLE
Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" to Dutch, French, Spanish, Indonesian
and German.
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude nl,fr,es,id,de
LanguagesToInclude can be any of these: bg|cs|da|de|es|fr|id|it|nl|sv|el|et|fi|hu|lt|pl|ro|sk|sl|uk
.EXAMPLE
Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" in all available languages.
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude all
.EXAMPLE
Start the application in silent mode and translate the JSON file "c:\path\to\jsonfile.json" in all available languages. Use DeepL
as the translation service
."AddTranslationsToJSONFile v22.ps1" -Silent -JSONFilename "c:\path\to\jsonfile.json" -LanguagesToInclude all -TranslatorService DeepL
.NOTES
Author: Willem-Jan Vroom
Website:
Twitter: @TheStingPilot
v0.1 Beta 1:
* Initial version.
v0.1 (RC1):
* Language translation service information is stored in the registry under 'HKCU:\Software\VroomSoft\AddTranslationsToJSONFile'.
* UTF8 decoding when using DeepL.
* Proxy support
* Check if the created JSON file is valid.
* Select or unselect all languages.
v1.0
* More detailed error message is the input JSON file has an incorrect layout.
* An ulimited number of variables in one sentence is allowed. Was restricted to three.
v1.1:
* Silent option includes the option to select the translation service
* Added command line option TranslatorService. You can select one of:
- Deepl
- GoogleFREEAPI
- GoogleCloudServices
- MicrosoftCognitive
There is one requirement: that the login details are in the registry. Fallback: Google FREE API.
* The stutus bar shows the language instead of the language code.
v1.2:
* The output file name is created dynamically and includes the name of the translation service.
* The text boxes with the input JSON file name and the generated JSON filename with the translations show the last part of the filename.
v1.3:
* Three languages have been added: ru, pt and zh
v2.0:
* The languages are added dynamically.
* It is no longer needed to use the radio buttons to specify the translation service.
* Improved error handing if a key is not found while reading the language files.
v2.1:
* Function 'WorkingInternetConnection' has been rewritten.
* In some cases the translate button was not enabled.
v2.2:
* Issue with -Silent option and the usage of DeepL as the translation service: there is a timeout.
Tested on two computers and this issue was on one computer.
* Changed the date notation of the logfile to yyyy-MM-dd HH-mm-ss, for example '2022-11-14 22-23-09'.
* Changed the date notation of the JSON file with the translations to yyyy-MM-dd HH-mm-ss, for example '2022-11-14 22-23-09'.
* The function 'UserDetails' has been modified.
Resources:
- https://cloud.google.com/translate/docs/basic/translating-text?hl=en-GB#powershell
- https://docs.microsoft.com/en-us/azure/cognitive-services/translator/how-to-create-translator-resource#authentication-keys-and-endpoint-url
- https://blog.kloud.com.au/2018/08/28/using-azure-cognitive-services-language-text-translation-with-powershell/
- https://www.alexandrumarin.com/translate-text-with-powershell-and-google-translate/
- https://www.deepl.com/pro-api?cta=header-pro-api/
- https://mattou07.net/posts/creating-complex-json-with-powershell/
- https://stackoverflow.com/questions/47779157/convertto-json-and-convertfrom-json-with-special-characters/47779605#47779605
- https://stackoverflow.com/questions/69090021/convert-a-string-in-powershell-in-europe-to-utf-8
#>
[CmdletBinding(DefaultParameterSetName = 'Default')]
Param
(
[Parameter(HelpMessage='Enable detailed logging to a log file.')]
[Parameter(ParameterSetName = 'Default',Mandatory=$False)]
[Parameter(ParameterSetName = 'Silent' ,Mandatory=$False)]
[Switch] $DetailedLogging,
[Parameter(HelpMessage='Clear the settings before starting.')]
[Parameter(ParameterSetName = 'Default',Mandatory=$False)]
[Switch] $ClearUserSettings,
[Parameter(HelpMessage='Do not load the user settings before starting.')]
[Parameter(ParameterSetName = 'Default',Mandatory=$False)]
[Switch] $NoUserSettings,
[Parameter(HelpMessage='Enable silent mode. The text is translated by the Google FREE API service.')]
[Parameter(ParameterSetName = 'Silent' ,Mandatory=$True)]
[Switch] $Silent,
[Parameter(HelpMessage='JSON filename with the English text.')]
[Parameter(ParameterSetName = 'Silent' ,Mandatory=$True)]
[String] $JSONFilename,
[Parameter(HelpMessage='Select all the languages you want to use for the translation.')]
[Parameter(ParameterSetName = 'Silent' ,Mandatory=$True)]
[ValidateSet("all","bg","cs","da","de","es","fr","id","it","ja","lv","nl","sv","el","et","fi","hu","lt","pl","ro","sk","sl","sv","tr","uk","pt","ru","zh")]
[String[]] $LanguagesToInclude,
[Parameter(HelpMessage='Select all the languages you want to use for the translation.')]
[Parameter(ParameterSetName = 'Silent' ,Mandatory=$False)]
[ValidateSet("Deepl","GoogleFREEAPI","GoogleCloudServices","MicrosoftCognitive")]
[String] $TranslatorService = "GoogleFREEAPI"
)
Clear-Host
# =============================================================================================================================================
# Function block
# =============================================================================================================================================
Function Add-EntryToLogFile
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-May-2020 / Modified 09-May-2022: Includes the function name
Created by: Willem-Jan Vroom
Organization:
Functionname: Add-EntryToLogFile
=============================================================================================================================================
.SYNOPSIS
This function adds a line to a log file
#>
Param
(
[Parameter(Mandatory=$True)] [string] $Entry,
[Parameter(Mandatory=$False)] [String] $FunctionName
)
Write-Verbose "[Function: $FunctionName] - $Entry"
If ($Global:gblDetailedLogging -and $Global:LogFile)
{
$Timestamp = (Get-Date -UFormat "%a %e %b %Y %X").ToString()
Add-Content $Global:LogFile -Value $($Timestamp + "[Function: $FunctionName] - $Entry") -Force -ErrorAction SilentlyContinue
}
}
Function Check-WorkingInternetConnection
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 09-July-2020 / Modified 04-Oct-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Check-WorkingInternetConnection
=============================================================================================================================================
.SYNOPSIS
Check for a working internet connection.
(New-Object System.Net.NetworkInformation.Ping).SendPingAsync("www.google.com") works also when a proxy server is used.
[Threading.Tasks.Task]::WaitAll($Status) will thrown an error if the host cannot be reached.
Test-NetConnection and Test-Connection do not work if a proxy server is used.
#>
Param
(
[Parameter(Mandatory=$False)] [String] $HostNameToCheck = "www.google.com"
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
$HostNameToCheck = $HostNameToCheck.Replace("https://","").Replace("http://","") # Remove https:// or http://
$HostNameToCheck = $HostNameToCheck.Replace("/","") # Remove a trailing / if needed.
Try
{
$Status = (New-Object System.Net.NetworkInformation.Ping).SendPingAsync($HostNameToCheck)
[Threading.Tasks.Task]::WaitAll($Status)
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Details:"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Result: $($Status.Result.Status)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Faulted: $($Status.Isfaulted)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry " - Is Completed: $($Status.IsCompleted)"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The host $HostNameToCheck can be reached. Thus there is a working internet connection."
$Result = $True
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The host $HostNameToCheck cannot be reached. Thus there is no working internet connection."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error: $($Status.Exception)"
$Result = $False
}
Return $Result
}
Function Get-Proxy
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 21-Sept-20222
Created by: Willem-Jan Vroom
Organization:
Functionname: Get-Proxy
=============================================================================================================================================
.SYNOPSIS
This function gets the proxy.
If a proxy server is used, the returned server name is different from the server that is checked.
#>
Param
(
[Parameter(Mandatory=$False)] [String] $CheckServer = "http://www.google.com/"
)
$Result = $null
$ThisFunctionName = $MyInvocation.MyCommand.Name
$DefaultWebProxy = [System.Net.WebRequest]::DefaultWebProxy.GetProxy([uri]($CheckServer)).AbsoluteUri
$SystemWebProxy = [System.Net.WebRequest]::GetSystemWebProxy().GetProxy([uri]$CheckServer).AbsoluteUri
If ($DefaultWebProxy -ne $CheckServer)
{
$Result = $DefaultWebProxy
}
ElseIf ($SystemWebProxy -ne $CheckServer)
{
$Result = $SystemWebProxy
}
If ($Result)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The proxy server '$Result' has been found and is used."
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No proxy server has been found."
}
Return $Result
}
Function Display-MessageBox
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 24-May-2021 / 24-Apr-2024 / 09-June-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Display-MessageBox
=============================================================================================================================================
.SYNOPSIS
This function displays a message box.
The return value is:
None (no result) 0
OK 1
Cancel 2
Yes 6
No. 7
#>
param
(
[Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()][String] $Text,
[Parameter(Mandatory=$True)] [ValidateNotNullOrEmpty()][String] $Title,
[Parameter(Mandatory=$False)][Switch] $GUI,
[Parameter(Mandatory=$False)][Switch] $Error,
[Parameter(Mandatory=$False)][ValidateSet('Ok','AbortRetryIgnore','OkCancel','YesNoCancel','YesNo')][String] $Button = "Ok"
)
If ($GUI)
{
If ($Error)
{
$Return = [System.Windows.Forms.MessageBox]::Show($this,$Text.Trim(),$Title,$Button,"Error")
}
else
{
$Return = [System.Windows.Forms.MessageBox]::Show($this,$Text.Trim(),$Title,$Button,"Asterisk")
}
}
else
{
Write-Host "$Text`n"
Return 0
}
Return $($Return.value__)
}
Function UserDetails
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 03-Jan-21 / Modified on 14-Jan-21 / Modified on 22-Apr-22 / Modified on 01-May-2022 / Modified on 17-May-2022 /
Modified 21-Nov-2022
Created by: Willem-Jan Vroom
Functionname: UserDetails
=============================================================================================================================================
.SYNOPSIS
This function returns 4 details of the Current Logged In Usser
1. The username of the current logged in user
2. User\Domain of the current logged in user
3. User SID fo the User\Domain
4. Account name that is using the script
Initially, the scriptAccount was found with the command
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
But that command throws up an error due to the PowerShell ConstrainedMode.
Also, the output of whoami /user depends on the language. In the German language the output is different.
The header information is in the German language, so the header should be read from the CSV file.
That can be done with PSObject.Properties.Name
C:\Users\Test>whoami /user
BENUTZERINFORMATIONEN
---------------------
Benutzername SID
==================== ==============================================
windows10wkg_02\test S-1-5-21-1753037473-1212035439-1379364385-1001
On 21-Nov-2022 the function has been changed.
There are 6 situations that should be handled:
1. Find the logged on user sid when there is one user logged on on a 'normal' Windows computer
2. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where there is no local admin.
3. Find the logged on user sid when multiple users are logged on in an RDS / Citrix environment where the users are local admin.
4. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on a 'normal' Windows computer.
This occurs during a Software Center installation performed under the SYSTEM account.
5. Find the logged on user sid when there is a SYSTEM account, and there is a user logged on on an RDS / Citrix environment.
6. Take care of the PowerShell Language Mode.
While testing I found that the MainWindowHandle is not 0 for the user that is running the explorer process. That is true for all the
above mentioned situations.
You can check while running this command with elevated rights:
get-process -IncludeUserName | Select-Object -Property Username, Id, Name,MainWindowHandle | Where {($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr")} | Format-Table
The output will be something like this:
UserName Id Name MainWindowHandle
-------- -- ---- ----------------
DEMO\user1 1380 explorer 0
DEMO\adminuser2 6556 explorer 131134
So, you have to continue with PID ID 6556.
So, I used the method of finding the PID, and use that PID as a condition for the Get-WMIObject to search for the explorer or pfwsmgr
process with that PID.
#>
# =============================================================================================================================================
# Find the current logged on user by checking the rights on the explore.exe (of pfwsmgr.exe with Ivanti Workspace Control) process.
# If the language mode is FullLanguage then use MainWindowHandle. That is needed when this script is run from SYSTEM context. I assume that
# the SYSTEM account is not effected by the PowerShell Language Mode.
# If the language mode is not FullLanguage then use a check on username and the owner of the explorer or pfwsmgr process.
# =============================================================================================================================================
if($Global:gblFullLanguage)
{
$PIDID = (get-process | Select-Object -Property Id, Name, MainWindowHandle | Where {(($_.Name -eq "explorer" -or $_.Name -eq "pfwsmgr") -and $($_.MainWindowHandle).ToInt32() -gt 0)}).Id
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer' or 'pfwsmgr' has the PID $PIDID."
$Explorer = (Get-WMIObject -Query "Select * From Win32_Process Where (ProcessId=$PIDID)")
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process with PID $PIDID has the name $($Explorer.Name)."
$UserName = $Explorer.GetOwner()
$SID = ($Explorer.GetOwnerSID()).SID
}
else
{
$Explorer = @(Get-WMIObject -Query "Select * From Win32_Process Where (Name='explorer.exe' or Name='pfwsmgr.exe')")
$EnvUSERNAME = $Env:USERNAME
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "The process 'explorer.exe' or 'pfwsmgr.exe' is running $($Explorer.Count) times."
For ($a=0; $a -le ($Explorer.Count); $a++)
{
$UserName = ($Explorer[$a]).GetOwner()
If ($($UserName.User) -eq $EnvUSERNAME)
{
$SID = (($Explorer[$a]).GetOwnerSID()).SID
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "A valid SID '$SID' has been found for user '$EnvUSERNAME'."
Break
}
}
}
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found domain: $($UserName.Domain)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found username: $($UserName.User)."
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found SID: $SID."
$UserAndDomain = "$($Username.Domain )\$($Username.User)".ToUpper()
$tmpScriptAccount = (whoami /user /FO csv | convertfrom-csv)
$TranslatedUserName = $tmpScriptAccount.PSObject.Properties.Name[0]
$ScriptAccount = $($tmpScriptAccount.$TranslatedUserName).ToUpper()
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "Found scriptaccount: $ScriptAccount"
Return $($Username.User),$UserAndDomain,$SID,$ScriptAccount
}
Function Test-RegistryKeyValue
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 30-Dec-20
Created by: (C) Aaron Jensen
https://stackoverflow.com/questions/5648931/test-if-registry-value-exists
Organization: Carbon Module
Functionname: Test-RegistryKeyValue
=============================================================================================================================================
.SYNOPSIS
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $True)][string] $Path,
[Parameter(Mandatory = $True)][string] $Name
)
If ( -not(Test-Path -Path $Path -PathType Container))
{
return $False
}
$properties = Get-ItemProperty -Path $Path
If (-not $properties)
{
return $False
}
$member = Get-Member -InputObject $properties -Name $Name
If ($member)
{
return $True
}
else
{
return $False
}
}
Function Find-Language
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 30-Dec-20
Created by: Willem-Jan Vroom
Organisation:
Functionname: Find-Language
=============================================================================================================================================
.SYNOPSIS
This function works the best, even running under system context.
Get-UiCulture returns the UICulture details from the account that is used. So when the system account is used, incorrect
details might be shown.
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $CurrentUserSID
)
$Result = "en-US"
$ThisFunctionName = $MyInvocation.MyCommand.Name
$RegKey = "REGISTRY::HKEY_USERS\$CurrentUserSID\Control Panel\Desktop"
$Value = "PreferredUILanguages"
If (Test-RegistryKeyValue -Path $RegKey -Name $Value)
{
$Result = (get-itemproperty $RegKey | Select -ExpandProperty $Value).Split()[0]
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Regkey '$RegKey' value '$Value' exists. The data is '$Result'."
Return $Result
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Regkey '$RegKey' value '$Value' does not exists. Skipping to machine settings."
}
$RegKey = "REGISTRY::HKEY_USERS\.DEFAULT\Control Panel\Desktop\MuiCached"
$Value = "MachinePreferredUILanguages"
If (Test-RegistryKeyValue -Path $RegKey -Name $Value)
{
$Result = (get-itemproperty $RegKey | Select -ExpandProperty $Value).Split()[0]
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Regkey '$RegKey' value '$Value' exists. The data is '$Result'."
Return $Result
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There was a problem reading the registry..."
Return $Result
}
Function Set-Registry
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 13-February-2021 / Modified 20-Sept-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Set-Registry
=============================================================================================================================================
.SYNOPSIS
This function sets a registry key
#>
param
(
[Parameter(Mandatory=$True) ] [String]$RegistryKey,
[Parameter(Mandatory=$True) ] [String]$ValueName,
[Parameter(Mandatory=$True) ] [String]$Value,
[Parameter(Mandatory=$False)] [Switch]$Boolean,
[Parameter(Mandatory=$False)] [Switch]$IsArray
)
# Check if the $Registrykey exists
$ThisFunctionName = $MyInvocation.MyCommand.Name
If (-not(test-path($RegistryKey)))
{
$Key = $RegistryKey.Split(":")[1]
$NewKey = $($RegistryKey.Split(":")[0]) + ":"
foreach($Item in $($Key.Split("\")))
{
$NewKey += "\$Item"
If (-not(test-path($NewKey)))
{
New-Item $NewKey -Force | Out-Null
Add-EntryToLogFile "Created the registry key: $NewKey." -FunctionName $ThisFunctionName
}
}
}
If ($Boolean)
{
If ($Value)
{
New-ItemProperty -Path $RegistryKey -Name $ValueName -PropertyType DWord -Value 1 -Force | Out-Null
Add-EntryToLogFile -Entry "Created in the hive $($RegistryKey):" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Created ValueName: $ValueName" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Type: REG_DWORD" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Value: 1" -FunctionName $ThisFunctionName
}
else
{
New-ItemProperty -Path $RegistryKey -Name $ValueName -PropertyType DWord -Value 0 -Force | Out-Null
Add-EntryToLogFile -Entry "Created in the hive $($RegistryKey):" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Created ValueName: $ValueName" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Type: REG_DWORD" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Value: 0" -FunctionName $ThisFunctionName
}
}
elseIf ($IsArray)
{
New-ItemProperty -Path $RegistryKey -Name $ValueName -PropertyType String -Value $($Value -join ",") -Force | Out-Null
Add-EntryToLogFile -Entry "Created in the hive $($RegistryKey):" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Created ValueName: $ValueName" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Type: REG_SZ" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Value: $($Value -join ",")" -FunctionName $ThisFunctionName
}
else
{
New-ItemProperty -Path $RegistryKey -Name $ValueName -PropertyType String -Value $Value -Force | Out-Null
Add-EntryToLogFile -Entry "Created in the hive $($RegistryKey):" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Created ValueName: $ValueName" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Type: REG_SZ" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " Value: $Value" -FunctionName $ThisFunctionName
}
}
Function Read-Registry
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 13-February-2021 / Modified 14-May-2021 / Modified 20-Sept-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Read-Registry
=============================================================================================================================================
.SYNOPSIS
This function reads a registry key and returns the value
#>
param
(
[Parameter(Mandatory=$True)] [String]$RegistryKey,
[Parameter(Mandatory=$True)] [String]$ValueName
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
If (Test-Path ($RegistryKey))
{
$Value = (Get-ItemProperty -Path $RegistryKey).$ValueName
If (($Value -ne $null) -and ($Value.Length -ne 0))
{
Add-EntryToLogFile -Entry "The registrykey '$RegistryKey' with valuename '$ValueName' exists." -FunctionName $ThisFunctionName
$PropertyType = (Get-Item $RegistryKey).GetValueKind($ValueName)
Add-EntryToLogFile -Entry "Hive: $RegistryKey" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " - ValueName: $ValueName" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " - Type: $PropertyType" -FunctionName $ThisFunctionName
Add-EntryToLogFile -Entry " - Value: $Value" -FunctionName $ThisFunctionName
If ($PropertyType -eq "String")
{
Return $Value
}
elseIf ($PropertyType -eq "DWord")
{
If ($Value -eq 1)
{
Return $True
}
else
{
Return $False
}
}
}
}
Return [string]::Empty
}
Function Get-FileFromButton
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: Get-FileFromButton
=============================================================================================================================================
.SYNOPSIS
You can browse to a file when clicked on the 'Browse' button.
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $InitialDirectory,
[Parameter(Mandatory = $False)] [String] $Filter
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
$File = New-Object System.Windows.Forms.OpenFileDialog
$File.InitialDirectory = $InitialDirectory
$File.Filter = $Filter
$File.Multiselect = $False
$File.CheckFileExists = $True
$File.CheckPathExists = $True
$Result = $File.ShowDialog()
If ($Result -eq [System.Windows.Forms.DialogResult]::OK)
{
$Selected = $File.FileName
}
$File.Dispose()
If ($Selected)
{
Add-EntryToLogFile -Entry "The file '$Selected' has been selected as the input JSON file." -FunctionName $ThisFunctionName
Return $Selected
}
}
Function TranslateVia-GoogleFREEApi
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: TranslateVia-GoogleFREEApi
=============================================================================================================================================
.SYNOPSIS
This translates text from the source language to the target language, using the free Google Translation Service
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $SourceLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TargetLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TextToTranslate
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
Try
{
$URL = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=$($SourceLanguage)&tl=$($TargetLanguage)&dt=t&q=$($TextToTranslate)"
# =============================================================================================================================================
# If a proxy server is used used, add the proxy details to the Invoke-Restmethod.
# =============================================================================================================================================
If ($ProxyServer)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Using $ProxyServer"
$Response = Invoke-RestMethod -Uri $URL -Method Get -Proxy $ProxyServer -UseDefaultCredentials -ProxyUseDefaultCredentials -TimeoutSec 10
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No proxy server"
$Response = Invoke-RestMethod -Uri $URL -Method Get -TimeoutSec 10
}
$Translation = $Response[0].SyncRoot | foreach { $_[0] }
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation).Replace([char](34),"'")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The text '$TextToTranslate' is translated from $SourceLanguage to $TargetLanguage"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Result: $Translation"
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There is an error while translating the text."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $($_.Exception.Message)`n"
$Translation = "ERROR: $($_.Exception.Message)"
}
Return $Translation
}
Function TranslateVia-DeepL
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: TranslateVia-DeepL
=============================================================================================================================================
.SYNOPSIS
This translates text from the source language to the target language, using DeepL.
There is a free version available. More info via https://www.deepl.com/pro/change-plan?cta=header-prices#developer
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $SourceLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TargetLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TextToTranslate,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $AKey,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $Domain
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
$Headers = @{Authorization = "DeepL-Auth-Key $AKey"}
$Body = @{target_lang = $TargetLanguage}
$Body += @{source_lang = $SourceLanguage}
$Body += @{split_sentences = 0}
$Body += @{text = $TextToTranslate}
Try
{
# =============================================================================================================================================
# If a proxy server is used used, add the proxy details to the Invoke-Restmethod.
# =============================================================================================================================================
If ($ProxyServer)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Using $ProxyServer"
$Response = Invoke-RestMethod -Uri $Domain -Method Post -Body $Body -Headers $Headers -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials -TimeoutSec 10
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No proxy server"
$Response = Invoke-RestMethod -Uri $Domain -Method Post -Body $Body -Headers $Headers -TimeoutSec 10
}
$Translation = [System.Web.HttpUtility]::HtmlDecode([Text.Encoding]::UTF8.GetString([Text.Encoding]::GetEncoding(28591).GetBytes($Response.translations.text))).Replace([char](34),"'")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The text '$TextToTranslate' is translated from $SourceLanguage to $TargetLanguage"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Result: $Translation"
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There is an error while translating the text."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $($_.Exception.Message)`n"
$Translation = "ERROR: $($_.Exception.Message)"
}
Return $Translation
}
Function TranslateVia-GoogleCloudAPI
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: TranslateVia-GoogleCloudAPI
=============================================================================================================================================
.SYNOPSIS
This translates text from the source language to the target language, using the Google Cloud API.
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $SourceLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TargetLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TextToTranslate,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $AKey
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
Try
{
$URL = "https://www.googleapis.com/language/translate/v2?key=$($AKey)&target=$($TargetLanguage)&source=$($SourceLanguage)&q=$($TextToTranslate)"
# =============================================================================================================================================
# If a proxy server is used used, add the proxy details to the Invoke-Restmethod.
# =============================================================================================================================================
If ($ProxyServer)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Using $ProxyServer"
$result = Invoke-RestMethod $URL -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials -TimeoutSec 10
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No proxy server"
$result = Invoke-RestMethod $URL -TimeoutSec 10
}
$Translation = $result.data.translations.translatedText
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation).Replace([char](34),"'")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The text '$TextToTranslate' is translated from $SourceLanguage to $TargetLanguage"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Result: $Translation"
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There is an error while translating the text."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $($_.Exception.Message)`n"
$Translation = "ERROR: $($_.Exception.Message)"
}
Return $Translation
}
Function TranslateVia-MicrosoftCognitiveServices
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Created on: 17-September-2022
Created by: Willem-Jan Vroom
Organization:
Functionname: TranslateVia-MicrosoftCognitiveServices
=============================================================================================================================================
.SYNOPSIS
This translates text from the source language to the target language, using Microsoft Azure Cognitive Services Translator.
#>
Param
(
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $SourceLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TargetLanguage,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $TextToTranslate,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $AKey,
[Parameter(Mandatory = $True)][ValidateNotNullOrEmpty()][String] $Location
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
$URL = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=$($SourceLanguage)&to=$($TargetLanguage)"
$Headers = @{}
$Headers.Add("Ocp-Apim-Subscription-Key",$Akey)
$Headers.Add("Ocp-Apim-Subscription-Region",$Location)
$Headers.Add("Content-Type","application/json")
$text = @{'Text' = $($TextToTranslate)} | ConvertTo-Json
Try
{
# =============================================================================================================================================
# If a proxy server is used used, add the proxy details to the Invoke-Restmethod.
# =============================================================================================================================================
If ($ProxyServer)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Using $ProxyServer"
$result = Invoke-RestMethod -Method POST -Uri $URL -Headers $headers -Body "[$($text)]" -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials -TimeoutSec 10
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No proxy server"
$result = Invoke-RestMethod -Method POST -Uri $URL -Headers $headers -Body "[$($text)]" -TimeoutSec 10
}
$Translation = $($Result.translations[0].text)
$Translation = [System.Web.HttpUtility]::HtmlDecode($Translation).Replace([char](34),"'")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The text '$TextToTranslate' is translated from $SourceLanguage to $TargetLanguage"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Result: $Translation"
}
Catch
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There is an error while translating the text."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Error message: $($_.Exception.Message)`n"
$Translation = "ERROR: $($_.Exception.Message)"
}
Return $Translation
}
# =============================================================================================================================================
# End function block
# =============================================================================================================================================
# =============================================================================================================================================
# Functions, used in the forms blocks
# =============================================================================================================================================
Function SelectOrUnselectAllLanguages
{
<#
.NOTES
=============================================================================================================================================
Created with: Windows PowerShell ISE
Functionname: SelectOrUnselectAllLanguages
=============================================================================================================================================
.SYNOPSIS
Selects or unselect all languages (chkLanguages)
#>
$ThisFunctionName = $MyInvocation.MyCommand.Name
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Select or unselect all languages."
For ($Counter = 0; $Counter -lt $chkLanguages.Items.Count; $Counter++)
{
If ($chkAllItems.Checked)
{
$chkLanguages.SetItemChecked($Counter, $True)
}
else
{
$chkLanguages.SetItemChecked($Counter, $False)
}
}
}
Function FilltheCheckedListBoxWithLanguages
{
Param
(
[String[]] $SupportedLanguages
)
$Global:gblTable = @()
ForEach ($SupportedLanguage in $SupportedLanguages)
{
$SupportedLanguage = $SupportedLanguage.Trim().ToLower()
If ($SupportedLanguage -ne "en")
{
$Language = [CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$SupportedLanguage*"} | Select-Object -Property Name,DisplayName
If ($Language)
{
$Record = [ordered] @{"Code" = "";
"Display Name" = "";}
$Record."Code" = $SupportedLanguage
$Record."Display Name" = ($Language[0].DisplayName).Split(" ")[0]
$Global:gblTable += New-Object PSObject -Property $Record
}
}
}
$Global:gblTable = $Global:gblTable | Sort-Object "Display Name"
$chkLanguages.Items.Clear()
ForEach ($SupportedLanguage in $Global:gblTable)
{
[void]$chkLanguages.Items.Add($SupportedLanguage."Display Name")
}
}
Function ValidateDeepL
{
# =============================================================================================================================================
# Enable the button 'DeepL' only if the text fields that contain the APIDomain and Authentication Key have been filled in.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
If ($txtAPIDomain.Text -and $txtAuthenticationKey.Text)
{
$bttnGetDeepLLanguages.Visible = $True
Add-EntryToLogFile -Entry "The button '$($bttnGetDeepLLanguages.Text)' is visible." -FunctionName $ThisFunctionName
}
else
{
$bttnGetDeepLLanguages.Visible = $False
Add-EntryToLogFile -Entry "The button '$($bttnGetDeepLLanguages.Text)' is invisible." -FunctionName $ThisFunctionName
}
}
Function ValidateMicrosoftCognitiveServices
{
# =============================================================================================================================================
# Enable the button 'Microsoft Cognitive Services' only if the text fields that contain the subscription key and region have been
# filled in.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
If ($txtAPIMSubscriptionRegion.Text -and $txtAPIMSubscriptionKey.Text)
{
$bttnGetMicrosoftLanguages.Visible = $True
Add-EntryToLogFile -Entry "The button '$($bttnGetMicrosoftLanguages.Text)' is visible." -FunctionName $ThisFunctionName
}
else
{
$bttnGetMicrosoftLanguages.Visible = $False
Add-EntryToLogFile -Entry "The button '$($bttnGetMicrosoftLanguages.Text)' is invisible." -FunctionName $ThisFunctionName
}
}
Function ValidateGoogleCloud
{
# =============================================================================================================================================
# Enable the button 'Google Cloud Translation' only if the text fieldfor the API Key has been filled in.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
If ($txtGoogleAPIKey.Text)
{
$bttnGetGoogleLanguages.Visible = $True
Add-EntryToLogFile -Entry "The button '$($bttnGetGoogleLanguages.Text)' is visible." -FunctionName $ThisFunctionName
}
else
{
$bttnGetGoogleLanguages.Visible = $False
Add-EntryToLogFile -Entry "The button '$($bttnGetGoogleLanguages.Text)' is invisible." -FunctionName $ThisFunctionName
}
}
Function CheckboxIsChanged
{
# =============================================================================================================================================
# Enable translate button only if there are languages selected and there is an language input file.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
Add-EntryToLogFile -Entry "There are $(($chkLanguages.CheckedItems).Count) languages selected." -FunctionName $ThisFunctionName
If ((($chkLanguages.CheckedItems).Count -gt 0) -and ($txtJSONFileWithEnglishText.Text))
{$bttnTranslate.Enabled = $True
Add-EntryToLogFile -Entry "The button '$($bttnTranslate.Text)' is enabled." -FunctionName $ThisFunctionName}
else
{$bttnTranslate.Enabled = $False
Add-EntryToLogFile -Entry "The button '$($bttnTranslate.Text)' is disabled." -FunctionName $ThisFunctionName}
}
Function JSONFileWithEnglishTextHasBeenSelected
{
# =============================================================================================================================================
# Specify the JSON file that contains the translations.
# =============================================================================================================================================
$txtJSONFileWithEnglishText.Enabled = $True
CheckboxIsChanged
}
Function GetAndTestJSONFile
{
# =============================================================================================================================================
# Select the 'base' JSON file, the file that contains the English text.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
$tmpText = Get-FileFromButton -InitialDirectory $strCurrentDir -Filter "All JSON Files (*.json) | *.json"
If ($tmpText)
{
Try
{
$tmpJSONObject = Get-Content -Path $tmpText -Encoding UTF8 | ConvertFrom-Json
If ($tmpJSONObject.en)
{
$txtJSONFileWithEnglishText.Text = $tmpText
$txtJSONFileWithEnglishText.SelectionStart = $txtJSONFileWithEnglishText.Text.Length
$txtJSONFileWithEnglishText.ScrollToCaret()
}
else
{
$ErrorText = "There is no 'en' entry in the JSON file '$tmpText'. So we cannot process this one."
Add-EntryToLogFile -Entry $ErrorText -FunctionName $ThisFunctionName
Display-MessageBox -Title "Error" -Text $ErrorText -GUI -Error -Button Ok
}
}
Catch
{
$ErrorMessage = "There is an error in the JSON file near:`n`n"
$ErrorText = $($_.Exception.Message)
[int]$Number = ($ErrorText -split '\((.*?)\)')[1]
$number = $Number -30
If ($Number -le 1){$Number = 1}
$ErrorMessage += $ErrorText.SubString($Number)
$ErrorMessage += "`n`nSelect another JSON file or correct the error in the file '$tmpText'."
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $ErrorMessage
$Null = Display-MessageBox -Text $ErrorMessage -GUI -Button Ok -Error -Title "Testing JSON File"
}
}
}
Function ReadAndProcessJSONFile
{
# =============================================================================================================================================
# Process the given JSON File.
# =============================================================================================================================================
Param
(
[Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()][String] $InputFile,
[Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()][String[]] $LanguagesToProcess,
[Parameter(Mandatory = $False)] [Switch] $Silent,
[Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()][ValidateSet("Deepl","GoogleFREEAPI","GoogleCloudServices","MicrosoftCognitive")][String] $TranslationService
)
$ThisFunctionName = $MyInvocation.MyCommand.Name
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Reading the file '$InputFile'."
$JSONObject = Get-Content -Path $InputFile -Encoding UTF8 -Raw | ConvertFrom-Json
# =============================================================================================================================================
# Specify the output file
# =============================================================================================================================================
$Mapping = @{
"Deepl" = "Deepl"
"GoogleFREEAPI" = "Google FREE API"
"GoogleCloudServices" = "Google Cloud Services"
"MicrosoftCognitive" = "Microsoft Azure Cognitive Services Translator"}
$TranslationserviceFullName = $Mapping.Item($TranslationService)
$tmpText = $InputFile.Replace(".json","")
$strLastPartOfFileName = " ($TranslationserviceFullName) ($((Get-Date -format "yyyy-MM-dd HH-mm-ss").ToString()))"
$OutputFile = $tmpText + $strLastPartOfFileName + ".json"
If (-not($Silent))
{
$txtJSONFileWithTheTranslations.Text = $OutputFile
$txtJSONFileWithTheTranslations.Enabled = $True
$txtJSONFileWithTheTranslations.Refresh()
$txtJSONFileWithTheTranslations.SelectionStart = $txtJSONFileWithTheTranslations.Text.Length
$txtJSONFileWithTheTranslations.ScrollToCaret()
}
# =============================================================================================================================================
# Grab all the headers. These might be different for each JSON file. So that has to dynamic.
# =============================================================================================================================================
$Headers = ($JSONObject.en | Get-Member -type NoteProperty).Name
# =============================================================================================================================================
# And a new JSON object for the translations, including the English one.
# =============================================================================================================================================
$NewJSONObject = [ordered] @{}
# =============================================================================================================================================
# First, add the English headers to the new JSON File. That is our starting point.
# =============================================================================================================================================
$Array = [ordered] @{}
ForEach ($Header in $Headers)
{
$Array += @{$Header=$JSONObject.en.$Header}
}
$NewJSONObject.Add("en",$Array)
# =============================================================================================================================================
# The second step is reading variables based on the Translation Service.
# =============================================================================================================================================
If ($TranslationService -eq "Deepl")
{
$AuthenticationKey = $txtAuthenticationKey.text
If (-not($AuthenticationKey)) {$AuthenticationKey = Read-Registry -RegistryKey $RegistryKey -ValueName "AuthenticationKey"}
$APIDomain = $txtAPIDomain.Text
If (-not($APIDomain)) {$APIDomain = Read-Registry -RegistryKey $RegistryKey -ValueName "APIDomain"}
}
If ($TranslationService -eq "GoogleCloudServices")
{
$GoogleAPIKey = $txtGoogleAPIKey.text
If (-not($GoogleAPIKey)) {$GoogleAPIKey = Read-Registry -RegistryKey $RegistryKey -ValueName "GoogleAPIKey"}
}
If ($TranslationService -eq "MicrosoftCognitive")
{
$APIMSubscriptionKey = $txtAPIMSubscriptionKey.text
If (-not($APIMSubscriptionKey)) {$APIMSubscriptionKey = Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionKey"}
$APIMSubscriptionRegion = $txtAPIMSubscriptionRegion.text
If (-not($APIMSubscriptionRegion)) {$APIMSubscriptionRegion = Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionRegion"}
}
# =============================================================================================================================================
# And now, add all the other selected languages.
# =============================================================================================================================================
$LanguageCounter = 1
$LanguagesToProcess = $LanguagesToProcess | Sort-Object
ForEach ($Language in $LanguagesToProcess)
{
$Language = $Language.Trim()
If (-not($NewJSONObject.$Language))
{
$LanguageDisplayName = ($Global:gblTable | Where {$_."Code" -eq $Language} | Select-Object -Property "Display name")."Display Name"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Processing $LanguageDisplayName language."
$Percentage = [Math]::Round(($LanguageCounter / $($LanguagesToProcess.Count) * 100),0)
$StatusText = "Processing the $LanguageDisplayName language using\b$($Mapping.Item($TranslationService))."
If ($Silent)
{
Write-Progress -Id 1 -Activity "Processing all the languages." -Status $StatusText.Replace("\b"," ") -PercentComplete $Percentage
}
else
{
$prgProgressbar.Visible = $True
$prgProgressbar.TextOverlay = $StatusText.Replace("\b","`n")
$prgProgressbar.Value = $Percentage
$prgProgressbar.Update()
$prgProgressbar.Step = (1/$($LanguagesToProcess.Count) * 100)
$bttnTranslate.Enabled = $False
$bttnExit.Enabled = $False
}
$Array = [ordered] @{}
ForEach ($Header in $Headers)
{
$TextToTranslate = $($JSONObject.en.$Header).Replace("&","")
$OldText = $TextToTranslate
$Replacement = @()
$Original = @()
$Counter = 0
While ($TextToTranslate.Contains("<") -and $TextToTranslate.Contains(">"))
{
$RandomNumber = Get-Random -Minimum 11111111 -Maximum 99999999
$Replacement += $RandomNumber
$Begin = $TextToTranslate.IndexOf("<")
$End = $TextToTranslate.IndexOf(">")
$Variable = $TextToTranslate.SubString($Begin,$End-$Begin+1)
$Original += $Variable
$TextToTranslate = $TextToTranslate.Replace($Variable,$($Replacement[$Counter]))
$Counter++
}
If ($TranslationService -eq "GoogleFREEAPI")
{
$TranslatedText = (TranslateVia-GoogleFREEApi -SourceLanguage "en" -TargetLanguage $Language -TextToTranslate $TextToTranslate)
}
If ($TranslationService -eq "Deepl")
{
$TranslatedText = (TranslateVia-Deepl -SourceLanguage "en" -TargetLanguage $Language -AKey $AuthenticationKey -Domain $APIDomain -TextToTranslate $TextToTranslate)
}
If ($TranslationService -eq "GoogleCloudServices")
{
$TranslatedText = (TranslateVia-GoogleCloudAPI -SourceLanguage "en" -TargetLanguage $Language -AKey $GoogleAPIKey -TextToTranslate $TextToTranslate)
}
If ($TranslationService -eq "MicrosoftCognitive")
{
$TranslatedText = (TranslateVia-MicrosoftCognitiveServices -SourceLanguage "en" -TargetLanguage $Language -AKey $APIMSubscriptionKey -Location $APIMSubscriptionRegion -TextToTranslate $TextToTranslate)
}
If ($Counter -gt 0)
{
For ($a = 0;$a -lt $Counter;$a++)
{
$TranslatedText = $TranslatedText.Replace($Replacement[$a],$Original[$a])
}
}
$Array += @{$Header=$TranslatedText}
}
$NewJSONObject.Add($Language,$Array)
$LanguageCounter++
}
else
{
# =============================================================================================================================================
# The language was already present in the translation. Thus skipping this one. But we have to increase the counter with one.
# =============================================================================================================================================
$LanguageCounter++
}
}
$NewJSONObject | ConvertTo-Json | % { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Out-File -FilePath $OutputFile -Encoding utf8
$Message = "The JSON file '$OutputFile' has been created."
# =============================================================================================================================================
# Check the created JSON File.
# =============================================================================================================================================
Try
{
# =============================================================================================================================================
# If the created JSON file can be read, then there is no problem.
# =============================================================================================================================================
$Null = Get-Content -Path $OutputFile -Encoding UTF8 | ConvertFrom-Json
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The JSON file '$OutputFile' seems to be fine. No further checks needed."
}
Catch
{
# =============================================================================================================================================
# The created JSON file cannot be read. Now, create a tmp JSON file for each language and check if that one can be read successfully.
# =============================================================================================================================================
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "There seems to be an issue with the JSON file '$OutputFile'. Let's check each language."
ForEach ($Language in $LanguagesToProcess)
{
$JSONText = $NewJSONObject.$Language
$TempFile = New-TemporaryFile
$JSONText | ConvertTo-Json | % { [System.Text.RegularExpressions.Regex]::Unescape($_) } | Out-File -FilePath $TempFile -Encoding utf8
Try
{
$Null = Get-Content -Path $TempFile -Encoding UTF8 | ConvertFrom-Json
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The language $Language has no issues."
}
Catch
{
$ErrorText = "There are issues with the language $Language. Check the created JSON file manually!"
$Message += "`n$ErrorText"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $ErrorText
}
Remove-Item -Path $TempFile -Force
}
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $Message
$Null = Display-MessageBox -Text $Message -GUI:(-not($Silent)) -Button Ok -Title "Creating JSON File."
If ($Silent)
{
Write-Progress -Id 1 -Completed -Activity " "
}
else
{
$prgProgressbar.Visible = $False
$bttnTranslate.Enabled = $True
$bttnExit.Enabled = $True
}
}
Function bttnTranslate
{
# =============================================================================================================================================
# The button bttnTranslate contains the name of the translation service that should be used: for example
# 'Start the translation with Google FREE API.'. The last word is 'API'. So, in this case the GoogleFREEAPI is used as the
# translation service.
# =============================================================================================================================================
$ThisFunctionName = $MyInvocation.MyCommand.Name
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The translation button '$($bttnTranslate.Text)' has been clicked."
$SelectedLanguages = @()
$TranslationService = $($bttnTranslate.Text).Split(" ")[-1].Replace(".","")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The translation service '$TranslationService' is used."
ForEach ($CheckedItem in ($chkLanguages.CheckedItems))
{
$SelectedLanguages += $Global:gblTable | Where {$_."Display Name" -eq $CheckedItem} | Select-Object -Property Code
}
If ($TranslationService -eq "Translator") {ReadAndProcessJSONFile -InputFile $($txtJSONFileWithEnglishText.Text) -LanguagesToProcess $SelectedLanguages.Code -TranslationService MicrosoftCognitive}
If ($TranslationService -eq "Services") {ReadAndProcessJSONFile -InputFile $($txtJSONFileWithEnglishText.Text) -LanguagesToProcess $SelectedLanguages.Code -TranslationService GoogleCloudServices}
If ($TranslationService -eq "API") {ReadAndProcessJSONFile -InputFile $($txtJSONFileWithEnglishText.Text) -LanguagesToProcess $SelectedLanguages.Code -TranslationService GoogleFREEAPI}
If ($TranslationService -eq "DeepL") {ReadAndProcessJSONFile -InputFile $($txtJSONFileWithEnglishText.Text) -LanguagesToProcess $SelectedLanguages.Code -TranslationService Deepl}
}
Function GetDeepLLanguages
{
$ThisFunctionName = $MyInvocation.MyCommand.Name
$URL = "https://api-free.deepl.com/v2/languages?type=target"
Add-EntryToLogFile "Reading the languages from $URL" -FunctionName $ThisFunctionName
$chkLanguages.Items.Clear()
$headers = @{Authorization = "DeepL-Auth-Key $($txtAuthenticationKey.text)"}
Try
{
If ($ProxyServer)
{
$Response = @((Invoke-RestMethod -Uri $URL -Method Post -Headers $headers -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials).Language)
}
else
{
$Response = @((Invoke-RestMethod -Uri $URL -Method Post -Headers $headers).Language)
}
$Response = $Response | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
FilltheCheckedListBoxWithLanguages -SupportedLanguages $Response
$chkAllItems.Checked = $False
$bttnTranslate.Text = $TranslationButtonBaseText + " DeepL."
}
Catch
{
$ErrorText = "There is an error reading the DeepL Translation files: $($_.Exception.Message)`nCheck your key."
Add-EntryToLogFile -Entry $ErrorText -FunctionName $ThisFunctionName
$Null = Display-MessageBox -Text $ErrorText -Title "Error" -Error -GUI
}
}
Function GetGoogleFREEAPILanguagesForWebsite
{
$ThisFunctionName = $MyInvocation.MyCommand.Name
$URL = "https://cloud.google.com/translate/docs/languages"
Add-EntryToLogFile "Reading the languages from $URL" -FunctionName $ThisFunctionName
$chkLanguages.Items.Clear()
$SL = @()
If ($ProxyServer)
{
$Content = Invoke-RestMethod -Uri $URL -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials
}
else
{
$Content = Invoke-RestMethod -Uri $URL
}
$LookFor = "<code translate=""no"" dir=""ltr"">.*</code>"
$Response = @(($Content | Select-String -AllMatches $LookFor | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value).Replace("<code translate=""no"" dir=""ltr"">","").Replace("</code>",""))
$Response = $Response | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
Return $Response
}
Function GetGoogleFREEAPILanguages
{
$frmProcessing = New-Object 'System.Windows.Forms.Form'
$txtMessage = New-Object 'System.Windows.Forms.TextBox'
$frmProcessing.Controls.Add($txtMessage)
$frmProcessing.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmProcessing.AutoScaleMode = 'Font'
$frmProcessing.BackColor = [System.Drawing.SystemColors]::ControlDark
$frmProcessing.ClientSize = New-Object System.Drawing.Size(430, 44)
$frmProcessing.FormBorderStyle = 'None'
$frmProcessing.Name = 'frmProcessing'
$frmProcessing.ShowIcon = $False
$frmProcessing.StartPosition = 'CenterParent'
$frmProcessing.Visible = $False
$frmProcessing.add_Shown({$Lang = GetGoogleFREEAPILanguagesForWebsite
FilltheCheckedListBoxWithLanguages -SupportedLanguages $Lang
$bttnTranslate.Text = $TranslationButtonBaseText + " Google FREE API."
[void]$frmProcessing.Close()
[void]$frmProcessing.Dispose()
})
#
# txtMessage
#
$txtMessage.ReadOnly = $True
$txtMessage.Location = New-Object System.Drawing.Point(12, 12)
$txtMessage.MaxLength = 50
$txtMessage.Name = 'txtMessage'
$txtMessage.Size = New-Object System.Drawing.Size(400, 20)
$txtMessage.TabIndex = 0
$txtMessage.TextAlign = 'Center'
$txtMessage.WordWrap = $False
$txtMessage.Text = "Please wait...."
[void]$frmProcessing.ShowDialog()
}
Function GetGoogleLanguages
{
$ThisFunctionName = $MyInvocation.MyCommand.Name
$URL = "https://translation.googleapis.com/language/translate/v2/languages?key=$($txtGoogleAPIKey.text)"
$chkLanguages.Items.Clear()
Add-EntryToLogFile "Reading the languages from $URL" -FunctionName $ThisFunctionName
Try
{
If ($ProxyServer)
{
$result = Invoke-WebRequest -Uri $URL -Method Get -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials
}
else
{
$result = Invoke-WebRequest -Uri $URL -Method Get
}
$Content = $result | Select-Object -ExpandProperty Content
$Response = ((ConvertFrom-Json -InputObject $Content).data.languages).language
$Response = $Response | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
FilltheCheckedListBoxWithLanguages -SupportedLanguages $Response
$chkAllItems.Checked = $False
$bttnTranslate.Text = $TranslationButtonBaseText + " Google Cloud Services."
}
Catch
{
$ErrorText = "There is an error reading the Google Cloud Translation files: $($_.Exception.Message)`nCheck your key."
Add-EntryToLogFile -Entry $ErrorText -FunctionName $ThisFunctionName
$Null = Display-MessageBox -Text $ErrorText -Title "Error" -Error -GUI
}
}
Function GetMicrosoftLanguages
{
$ThisFunctionName = $MyInvocation.MyCommand.Name
$URL = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0"
Add-EntryToLogFile "Reading the languages from $URL" -FunctionName $ThisFunctionName
$chkLanguages.Items.Clear()
Try
{
If ($ProxyServer)
{
$conversionResult = Invoke-RestMethod -Method Get -Uri $URL -Proxy $ProxyServer -ProxyUseDefaultCredentials -UseDefaultCredentials
}
else
{
$conversionResult = Invoke-RestMethod -Method Get -Uri $URL
}
$Response = ($conversionResult.translation | Get-Member -type NoteProperty).Name | ForEach {($_ ).Split("-")[0]} | Sort-Object | Select-Object -Unique
FilltheCheckedListBoxWithLanguages -SupportedLanguages $Response
$chkAllItems.Checked = $False
$bttnTranslate.Text = $TranslationButtonBaseText + " Microsoft Azure Cognitive Services Translator."
}
Catch
{
$ErrorText = "There is an error reading the Microsoft Languages: $($_.Exception.Message)."
Add-EntryToLogFile -Entry $ErrorText -FunctionName $ThisFunctionName
$Null = Display-MessageBox -Text $ErrorText -Title "Error" -Error -GUI
}
}
# =============================================================================================================================================
# End Functions, used in the forms blocks
# =============================================================================================================================================
# =============================================================================================================================================
# Form block AddTranslationsToAJSONFile
# =============================================================================================================================================
Function AddTranslationsToAJSONFile
{
$ThisFunctionName = $MyInvocation.MyCommand.Name
$frmAddTranslationsToJSON = New-Object 'System.Windows.Forms.Form'
$prgProgressbar = New-Object 'SAPIENTypes.ProgressBarOverlay'
$bttnTranslate = New-Object 'System.Windows.Forms.Button'
$bttnExit = New-Object 'System.Windows.Forms.Button'
$grpLanguages = New-Object 'System.Windows.Forms.GroupBox'
$chkAllItems = New-Object 'System.Windows.Forms.CheckBox'
$chkLanguages = New-Object 'System.Windows.Forms.CheckedListBox'
$txtJSONFileWithTheTranslations = New-Object 'System.Windows.Forms.TextBox'
$lblJSONFileWithTheTranslations = New-Object 'System.Windows.Forms.Label'
$bttnBrowse = New-Object 'System.Windows.Forms.Button'
$txtJSONFileWithEnglishText = New-Object 'System.Windows.Forms.TextBox'
$lblJSONFileWithEnglishText = New-Object 'System.Windows.Forms.Label'
$grpTranslationServices = New-Object 'System.Windows.Forms.GroupBox'
$grpGoogleFreeAPI = New-Object 'System.Windows.Forms.GroupBox'
$bttnGetGoogleFREEAPILanguages = New-Object 'System.Windows.Forms.Button'
$grpMicrosoftCognitiveTranslator = New-Object 'System.Windows.Forms.GroupBox'
$bttnGetMicrosoftLanguages = New-Object 'System.Windows.Forms.Button'
$txtAPIMSubscriptionRegion = New-Object 'System.Windows.Forms.TextBox'
$lblAPIMSubscriptionRegion = New-Object 'System.Windows.Forms.Label'
$txtAPIMSubscriptionKey = New-Object 'System.Windows.Forms.TextBox'
$lblAPIMSubscriptionKey = New-Object 'System.Windows.Forms.Label'
$grpGoogleCloudTranslation = New-Object 'System.Windows.Forms.GroupBox'
$bttnGetGoogleLanguages = New-Object 'System.Windows.Forms.Button'
$txtGoogleAPIKey = New-Object 'System.Windows.Forms.TextBox'
$lblGoogleAPIKey = New-Object 'System.Windows.Forms.Label'
$grpDeepL = New-Object 'System.Windows.Forms.GroupBox'
$bttnGetDeepLLanguages = New-Object 'System.Windows.Forms.Button'
$txtAPIDomain = New-Object 'System.Windows.Forms.TextBox'
$lblAPIDomain = New-Object 'System.Windows.Forms.Label'
$txtAuthenticationKey = New-Object 'System.Windows.Forms.TextBox'
$lblAuthenticationKey = New-Object 'System.Windows.Forms.Label'
#
# frmAddTranslationsToJSON
#
$frmAddTranslationsToJSON.Controls.Add($prgProgressbar)
$frmAddTranslationsToJSON.Controls.Add($bttnTranslate)
$frmAddTranslationsToJSON.Controls.Add($bttnExit)
$frmAddTranslationsToJSON.Controls.Add($grpTranslationService)
$frmAddTranslationsToJSON.Controls.Add($grpLanguages)
$frmAddTranslationsToJSON.Controls.Add($txtJSONFileWithTheTranslations)
$frmAddTranslationsToJSON.Controls.Add($lblJSONFileWithTheTranslations)
$frmAddTranslationsToJSON.Controls.Add($bttnBrowse)
$frmAddTranslationsToJSON.Controls.Add($txtJSONFileWithEnglishText)
$frmAddTranslationsToJSON.Controls.Add($lblJSONFileWithEnglishText)
$frmAddTranslationsToJSON.Controls.Add($grpTranslationServices)
$frmAddTranslationsToJSON.AutoScaleDimensions = New-Object System.Drawing.SizeF(6, 13)
$frmAddTranslationsToJSON.AutoScaleMode = 'Font'
$frmAddTranslationsToJSON.ClientSize = New-Object System.Drawing.Size(798, 636)
$frmAddTranslationsToJSON.FormBorderStyle = 'Fixed3D'
$frmAddTranslationsToJSON.Name = 'frmAddTranslationsToJSON'
$frmAddTranslationsToJSON.StartPosition = 'CenterParent'
#
# prgProgressbar
#
$prgProgressbar.Location = New-Object System.Drawing.Point(365, 488)
$prgProgressbar.Name = 'prgProgressbar'
$prgProgressbar.Size = New-Object System.Drawing.Size(415, 75)
$prgProgressbar.Style = 'Continuous'
$prgProgressbar.TabIndex = 11
#
# bttnTranslate
#
$bttnTranslate.Location = New-Object System.Drawing.Point(365, 576)
$bttnTranslate.Name = 'bttnTranslate'
$bttnTranslate.Size = New-Object System.Drawing.Size(200, 50)
$bttnTranslate.TabIndex = 10
$bttnTranslate.Text = '<< To be modified >>'
$bttnTranslate.UseVisualStyleBackColor = $True
#
# bttnExit
#
$bttnExit.Location = New-Object System.Drawing.Point(580, 576)
$bttnExit.Name = 'bttnExit'
$bttnExit.Size = New-Object System.Drawing.Size(200, 50)
$bttnExit.TabIndex = 9
$bttnExit.Text = 'Exit'
$bttnExit.UseVisualStyleBackColor = $True
#
# grpLanguages
#
$grpLanguages.Controls.Add($chkAllItems)
$grpLanguages.Controls.Add($chkLanguages)
$grpLanguages.BackColor = [System.Drawing.Color]::FromArgb(255, 224, 224, 224)
$grpLanguages.Location = New-Object System.Drawing.Point(577, 12)
$grpLanguages.Name = 'grpLanguages'
$grpLanguages.Size = New-Object System.Drawing.Size(209, 408)
$grpLanguages.TabIndex = 7
$grpLanguages.TabStop = $False
$grpLanguages.Text = 'Select the languages'
#
# chkAllItems
#
$chkAllItems.Location = New-Object System.Drawing.Point(6, 19)
$chkAllItems.Name = 'chkAllItems'
$chkAllItems.Size = New-Object System.Drawing.Size(197, 24)
$chkAllItems.TabIndex = 7
$chkAllItems.Text = 'Select or unselect all languages'
$chkAllItems.UseVisualStyleBackColor = $True
#
# chkLanguages
#
$chkLanguages.CheckOnClick = $True
$chkLanguages.FormattingEnabled = $True
$chkLanguages.Location = New-Object System.Drawing.Point(6, 49)
$chkLanguages.Name = 'chkLanguages'
$chkLanguages.Size = New-Object System.Drawing.Size(197, 349)
$chkLanguages.TabIndex = 6
#
# txtJSONFileWithTheTranslations
#
$txtJSONFileWithTheTranslations.Location = New-Object System.Drawing.Point(174, 452)
$txtJSONFileWithTheTranslations.Name = 'txtJSONFileWithTheTranslations'
$txtJSONFileWithTheTranslations.Size = New-Object System.Drawing.Size(527, 20)
$txtJSONFileWithTheTranslations.TabIndex = 5
#
# lblJSONFileWithTheTranslations
#
$lblJSONFileWithTheTranslations.AutoSize = $True
$lblJSONFileWithTheTranslations.Location = New-Object System.Drawing.Point(14, 452)
$lblJSONFileWithTheTranslations.Name = 'lblJSONFileWithTheTranslations'
$lblJSONFileWithTheTranslations.Size = New-Object System.Drawing.Size(153, 13)
$lblJSONFileWithTheTranslations.TabIndex = 4
$lblJSONFileWithTheTranslations.Text = 'JSON File with the translations:'
#
# bttnBrowse
#
$bttnBrowse.Location = New-Object System.Drawing.Point(705, 424)
$bttnBrowse.Name = 'bttnBrowse'
$bttnBrowse.Size = New-Object System.Drawing.Size(75, 23)
$bttnBrowse.TabIndex = 3
$bttnBrowse.Text = 'Browse'
$bttnBrowse.UseVisualStyleBackColor = $True
#
# txtJSONFileWithEnglishText
#
$txtJSONFileWithEnglishText.Location = New-Object System.Drawing.Point(174, 426)
$txtJSONFileWithEnglishText.Name = 'txtJSONFileWithEnglishText'
$txtJSONFileWithEnglishText.Size = New-Object System.Drawing.Size(525, 20)
$txtJSONFileWithEnglishText.TabIndex = 2
#
# lblJSONFileWithEnglishText
#
$lblJSONFileWithEnglishText.AutoSize = $True
$lblJSONFileWithEnglishText.Location = New-Object System.Drawing.Point(12, 429)
$lblJSONFileWithEnglishText.Name = 'lblJSONFileWithEnglishText'
$lblJSONFileWithEnglishText.Size = New-Object System.Drawing.Size(136, 13)
$lblJSONFileWithEnglishText.TabIndex = 1
$lblJSONFileWithEnglishText.Text = 'JSON File with English text:'
#
# grpTranslationServices
#
$grpTranslationServices.Controls.Add($grpGoogleFreeAPI)
$grpTranslationServices.Controls.Add($grpMicrosoftCognitiveTranslator)
$grpTranslationServices.Controls.Add($grpGoogleCloudTranslation)
$grpTranslationServices.Controls.Add($grpDeepL)
$grpTranslationServices.BackColor = [System.Drawing.Color]::FromArgb(255, 224, 224, 224)
$grpTranslationServices.Location = New-Object System.Drawing.Point(12, 12)
$grpTranslationServices.Name = 'grpTranslationServices'
$grpTranslationServices.Size = New-Object System.Drawing.Size(443, 408)
$grpTranslationServices.TabIndex = 0
$grpTranslationServices.TabStop = $False
$grpTranslationServices.Text = 'Translation services'
#
# grpGoogleFreeAPI
#
$grpGoogleFreeAPI.Controls.Add($bttnGetGoogleFREEAPILanguages)
$grpGoogleFreeAPI.BackColor = [System.Drawing.Color]::Silver
$grpGoogleFreeAPI.Location = New-Object System.Drawing.Point(6, 141)
$grpGoogleFreeAPI.Name = 'grpGoogleFreeAPI'
$grpGoogleFreeAPI.Size = New-Object System.Drawing.Size(429, 59)
$grpGoogleFreeAPI.TabIndex = 3
$grpGoogleFreeAPI.TabStop = $False
$grpGoogleFreeAPI.Text = 'Google FREE API'
#
# bttnGetGoogleFREEAPILanguages
#
$bttnGetGoogleFREEAPILanguages.Location = New-Object System.Drawing.Point(9, 20)
$bttnGetGoogleFREEAPILanguages.Name = 'bttnGetGoogleFREEAPILanguages'
$bttnGetGoogleFREEAPILanguages.Size = New-Object System.Drawing.Size(414, 25)
$bttnGetGoogleFREEAPILanguages.TabIndex = 0
$bttnGetGoogleFREEAPILanguages.Text = 'Get all languages supported by Google FREE API'
$bttnGetGoogleFREEAPILanguages.UseVisualStyleBackColor = $True
#
# grpMicrosoftCognitiveTranslator
#
$grpMicrosoftCognitiveTranslator.Controls.Add($bttnGetMicrosoftLanguages)
$grpMicrosoftCognitiveTranslator.Controls.Add($txtAPIMSubscriptionRegion)
$grpMicrosoftCognitiveTranslator.Controls.Add($lblAPIMSubscriptionRegion)
$grpMicrosoftCognitiveTranslator.Controls.Add($txtAPIMSubscriptionKey)
$grpMicrosoftCognitiveTranslator.Controls.Add($lblAPIMSubscriptionKey)
$grpMicrosoftCognitiveTranslator.BackColor = [System.Drawing.Color]::Silver
$grpMicrosoftCognitiveTranslator.Location = New-Object System.Drawing.Point(6, 295)
$grpMicrosoftCognitiveTranslator.Name = 'grpMicrosoftCognitiveTranslator'
$grpMicrosoftCognitiveTranslator.Size = New-Object System.Drawing.Size(429, 106)
$grpMicrosoftCognitiveTranslator.TabIndex = 2
$grpMicrosoftCognitiveTranslator.TabStop = $False
$grpMicrosoftCognitiveTranslator.Text = 'Microsoft Azure Cognitive Services Translator'
#
# bttnGetMicrosoftLanguages
#
$bttnGetMicrosoftLanguages.Location = New-Object System.Drawing.Point(4, 74)
$bttnGetMicrosoftLanguages.Name = 'bttnGetMicrosoftLanguages'
$bttnGetMicrosoftLanguages.Size = New-Object System.Drawing.Size(419, 25)
$bttnGetMicrosoftLanguages.TabIndex = 4
$bttnGetMicrosoftLanguages.Text = 'Get all languages supported by Microsoft Azure Cognitive Services Translator'
$bttnGetMicrosoftLanguages.UseVisualStyleBackColor = $True
#
# txtAPIMSubscriptionRegion
#
$txtAPIMSubscriptionRegion.Location = New-Object System.Drawing.Point(152, 46)
$txtAPIMSubscriptionRegion.Name = 'txtAPIMSubscriptionRegion'
$txtAPIMSubscriptionRegion.Size = New-Object System.Drawing.Size(271, 20)
$txtAPIMSubscriptionRegion.TabIndex = 3
#
# lblAPIMSubscriptionRegion
#
$lblAPIMSubscriptionRegion.AutoSize = $True
$lblAPIMSubscriptionRegion.Location = New-Object System.Drawing.Point(7, 49)
$lblAPIMSubscriptionRegion.Name = 'lblAPIMSubscriptionRegion'
$lblAPIMSubscriptionRegion.Size = New-Object System.Drawing.Size(126, 13)
$lblAPIMSubscriptionRegion.TabIndex = 2
$lblAPIMSubscriptionRegion.Text = 'APIM Subscription region'
#
# txtAPIMSubscriptionKey
#
$txtAPIMSubscriptionKey.Location = New-Object System.Drawing.Point(152, 20)
$txtAPIMSubscriptionKey.Name = 'txtAPIMSubscriptionKey'
$txtAPIMSubscriptionKey.Size = New-Object System.Drawing.Size(271, 20)
$txtAPIMSubscriptionKey.TabIndex = 1
#
# lblAPIMSubscriptionKey
#
$lblAPIMSubscriptionKey.AutoSize = $True
$lblAPIMSubscriptionKey.Location = New-Object System.Drawing.Point(7, 23)
$lblAPIMSubscriptionKey.Name = 'lblAPIMSubscriptionKey'
$lblAPIMSubscriptionKey.Size = New-Object System.Drawing.Size(117, 13)
$lblAPIMSubscriptionKey.TabIndex = 0
$lblAPIMSubscriptionKey.Text = 'APIM Subscription key:'
#
# grpGoogleCloudTranslation
#
$grpGoogleCloudTranslation.Controls.Add($bttnGetGoogleLanguages)
$grpGoogleCloudTranslation.Controls.Add($txtGoogleAPIKey)
$grpGoogleCloudTranslation.Controls.Add($lblGoogleAPIKey)
$grpGoogleCloudTranslation.BackColor = [System.Drawing.Color]::Silver
$grpGoogleCloudTranslation.Location = New-Object System.Drawing.Point(6, 206)
$grpGoogleCloudTranslation.Name = 'grpGoogleCloudTranslation'
$grpGoogleCloudTranslation.Size = New-Object System.Drawing.Size(429, 83)
$grpGoogleCloudTranslation.TabIndex = 1
$grpGoogleCloudTranslation.TabStop = $False
$grpGoogleCloudTranslation.Text = 'Google Cloud Translation'
#
# bttnGetGoogleLanguages
#
$bttnGetGoogleLanguages.Location = New-Object System.Drawing.Point(9, 50)
$bttnGetGoogleLanguages.Name = 'bttnGetGoogleLanguages'
$bttnGetGoogleLanguages.Size = New-Object System.Drawing.Size(414, 25)
$bttnGetGoogleLanguages.TabIndex = 2
$bttnGetGoogleLanguages.Text = 'Get all languages supported by Google Cloud Translation.'
$bttnGetGoogleLanguages.UseVisualStyleBackColor = $True
#
# txtGoogleAPIKey
#
$txtGoogleAPIKey.Location = New-Object System.Drawing.Point(152, 19)
$txtGoogleAPIKey.Name = 'txtGoogleAPIKey'
$txtGoogleAPIKey.Size = New-Object System.Drawing.Size(271, 20)
$txtGoogleAPIKey.TabIndex = 1
#
# lblGoogleAPIKey
#
$lblGoogleAPIKey.AutoSize = $True
$lblGoogleAPIKey.Location = New-Object System.Drawing.Point(7, 23)
$lblGoogleAPIKey.Name = 'lblGoogleAPIKey'
$lblGoogleAPIKey.Size = New-Object System.Drawing.Size(85, 13)
$lblGoogleAPIKey.TabIndex = 0
$lblGoogleAPIKey.Text = 'Google API Key:'
#
# grpDeepL
#
$grpDeepL.Controls.Add($bttnGetDeepLLanguages)
$grpDeepL.Controls.Add($txtAPIDomain)
$grpDeepL.Controls.Add($lblAPIDomain)
$grpDeepL.Controls.Add($txtAuthenticationKey)
$grpDeepL.Controls.Add($lblAuthenticationKey)
$grpDeepL.BackColor = [System.Drawing.Color]::Silver
$grpDeepL.Location = New-Object System.Drawing.Point(6, 19)
$grpDeepL.Name = 'grpDeepL'
$grpDeepL.Size = New-Object System.Drawing.Size(429, 116)
$grpDeepL.TabIndex = 0
$grpDeepL.TabStop = $False
$grpDeepL.Text = 'DeepL'
#
# bttnGetDeepLLanguages
#
$bttnGetDeepLLanguages.Location = New-Object System.Drawing.Point(9, 77)
$bttnGetDeepLLanguages.Name = 'bttnGetDeepLLanguages'
$bttnGetDeepLLanguages.Size = New-Object System.Drawing.Size(414, 25)
$bttnGetDeepLLanguages.TabIndex = 4
$bttnGetDeepLLanguages.Text = 'Get all languages supported by DeepL.'
$bttnGetDeepLLanguages.UseVisualStyleBackColor = $True
#
# txtAPIDomain
#
$txtAPIDomain.Location = New-Object System.Drawing.Point(154, 46)
$txtAPIDomain.Name = 'txtAPIDomain'
$txtAPIDomain.Size = New-Object System.Drawing.Size(269, 20)
$txtAPIDomain.TabIndex = 3
#
# lblAPIDomain
#
$lblAPIDomain.AutoSize = $True
$lblAPIDomain.Location = New-Object System.Drawing.Point(7, 49)
$lblAPIDomain.Name = 'lblAPIDomain'
$lblAPIDomain.Size = New-Object System.Drawing.Size(66, 13)
$lblAPIDomain.TabIndex = 2
$lblAPIDomain.Text = 'API Domain:'
#
# txtAuthenticationKey
#
$txtAuthenticationKey.Location = New-Object System.Drawing.Point(154, 20)
$txtAuthenticationKey.Name = 'txtAuthenticationKey'
$txtAuthenticationKey.Size = New-Object System.Drawing.Size(269, 20)
$txtAuthenticationKey.TabIndex = 1
#
# lblAuthenticationKey
#
$lblAuthenticationKey.AutoSize = $True
$lblAuthenticationKey.Location = New-Object System.Drawing.Point(7, 23)
$lblAuthenticationKey.Name = 'lblAuthenticationKey'
$lblAuthenticationKey.Size = New-Object System.Drawing.Size(99, 13)
$lblAuthenticationKey.TabIndex = 0
$lblAuthenticationKey.Text = 'Authentication Key:'
If (-not($NoUserSettings))
{
$tmpValue = Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionRegion"
If ($tmpValue) {$txtAPIMSubscriptionRegion.Text = $tmpValue}
$tmpValue = Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionKey"
If ($tmpValue) {$txtAPIMSubscriptionKey.Text = $tmpValue}
$tmpValue = Read-Registry -RegistryKey $RegistryKey -ValueName "GoogleAPIKey"
If ($tmpValue) {$txtGoogleAPIKey.Text = $tmpValue}
$tmpValue = Read-Registry -RegistryKey $RegistryKey -ValueName "APIDomain"
If ($tmpValue) {$txtAPIDomain.Text = $tmpValue}
$tmpValue = Read-Registry -RegistryKey $RegistryKey -ValueName "AuthenticationKey"
If ($tmpValue) {$txtAuthenticationKey.Text = $tmpValue}
$txtAPIMSubscriptionRegion.Refresh()
$txtAPIMSubscriptionKey.Refresh()
$txtGoogleAPIKey.Refresh()
$txtAPIDomain.Refresh()
$txtAuthenticationKey.Refresh()
}
$bttnGetDeepLLanguages.Visible = $False
$bttnGetGoogleLanguages.Visible = $False
$bttnGetMicrosoftLanguages.Visible = $False
$bttnTranslate.Text = $TranslationButtonBaseText
ValidateDeepL
ValidateMicrosoftCognitiveServices
ValidateGoogleCloud
$bttnTranslate.Enabled = $False
$txtJSONFileWithTheTranslations.Enabled = $False
$txtJSONFileWithEnglishText.Enabled = $False
$prgProgressbar.Visible = $False
$frmAddTranslationsToJSON.Text = "$ApplicationName $ApplicationVersion"
$frmAddTranslationsToJSON.TopMost = $True
$chkAllItems.Add_CheckedChanged({SelectOrUnselectAllLanguages;CheckboxIsChanged})
$txtAPIDomain.Add_TextChanged({ValidateDeepL})
$txtAuthenticationKey.Add_TextChanged({ValidateDeepL})
$txtAPIMSubscriptionKey.Add_TextChanged({ValidateMicrosoftCognitiveServices})
$txtAPIMSubscriptionRegion.Add_TextChanged({ValidateMicrosoftCognitiveServices})
$txtGoogleAPIKey.Add_TextChanged({ValidateGoogleCloud})
$txtJSONFileWithEnglishText.Add_TextChanged({JSONFileWithEnglishTextHasBeenSelected})
$chkLanguages.Add_SelectedValueChanged({CheckboxIsChanged;ValidateDeepL;ValidateMicrosoftCognitiveServices;ValidateGoogleCloud})
$bttnTranslate.add_Click({bttnTranslate})
$bttnBrowse.add_Click({GetAndTestJSONFile})
$bttnGetDeepLLanguages.Add_Click({GetDeepLLanguages;ValidateDeepL})
$bttnGetGoogleFREEAPILanguages.Add_Click({GetGoogleFREEAPILanguages})
$bttnGetGoogleLanguages.add_Click({GetGoogleLanguages;ValidateGoogleCloud})
$bttnGetMicrosoftLanguages.add_Click({GetMicrosoftLanguages;ValidateMicrosoftCognitiveServices})
$bttnExit.add_Click({Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Leaving the application. Bye!"
If (-not($NoUserSettings))
{
$ThisFunctionName = "Leaving"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Leaving the application and saving settings."
$tmpValue = $txtAPIMSubscriptionRegion.Text; If ($tmpValue) {Set-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionRegion" -Value $tmpValue}
$tmpValue = $txtAPIMSubscriptionKey.Text; If ($tmpValue) {Set-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionKey" -Value $tmpValue}
$tmpValue = $txtGoogleAPIKey.Text; If ($tmpValue) {Set-Registry -RegistryKey $RegistryKey -ValueName "GoogleAPIKey" -Value $tmpValue}
$tmpValue = $txtAPIDomain.Text; If ($tmpValue) {Set-Registry -RegistryKey $RegistryKey -ValueName "APIDomain" -Value $tmpValue}
$tmpValue = $txtAuthenticationKey.Text; If ($tmpValue) {Set-Registry -RegistryKey $RegistryKey -ValueName "AuthenticationKey" -Value $tmpValue}
}
$frmAddTranslationsToJSON.Close()
$frmAddTranslationsToJSON.Dispose()
Return
})
[void]$frmAddTranslationsToJSON.ShowDialog()
}
# =============================================================================================================================================
# End form block AddTranslationsToAJSONFile
# =============================================================================================================================================
$Global:gblDetailedLogging = $DetailedLogging
$strCurrentDir = Split-Path -parent $MyInvocation.MyCommand.Definition
$ApplicationName = "Add translations to a JSON file"
$ApplicationVersion = "v2.2"
$PowerShellLanguageMode = $ExecutionContext.SessionState.LanguageMode
$Global:gblFullLanguage = $PowerShellLanguageMode -eq "FullLanguage"
$ErrorNumber = 0
$ErrorText = ""
$MinimumWidth = 800
$MinimumHeight = 600
$RegistryKey = "HKCU:Software\VroomSoft\AddTranslationsToJSONFile"
$TranslationButtonBaseText = "Start the translation with"
# =============================================================================================================================================
# Find the logpath.
# =============================================================================================================================================
$OnlyUserName, `
$LoggedOnUserInDomainFormat, `
$UseridSID, `
$InstallAccount = UserDetails
$LogPath = $Env:TEMP
$Global:LogPath = $LogPath
# =============================================================================================================================================
# Define the results file. This file contains all the results.
# It is saved as yyyy-MM-dd HH-mm-ss, for example 2022-11-14 22-23-09
# =============================================================================================================================================
$strLastPartOfFileName = " ($((Get-Date -format "yyyy-MM-dd HH-mm-ss").ToString()))"
$PreFixLogFile = $ApplicationName -replace(" ","")
$ThisFunctionName = "[Main - Resultsfile]"
If ($Global:gblDetailedLogging)
{
$Global:LogFile = $Global:LogPath + "\"+ $PreFixLogFile + $($strLastPartOfFileName + ".log")
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logfile: $Global:LogFile"
}
If ($Message)
{
If ($bolError)
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "$Message"
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "This script will now quit."
Write-Error $Message -Category CloseError
Exit 3
}
else
{
Add-EntryToLogFile -FunctionName $($MyInvocation.MyCommand.Name) -Entry "[Warning]: $Message"
}
}
# =============================================================================================================================================
# Find all the arguments and put them in the log file
# Source: https://ss64.com/ps/psboundparameters.html
# =============================================================================================================================================
$ThisFunctionName = "[Main - Arguments]"
If ($Global:bolFullLanguage)
{
$Global:gblTableWithParameters = @()
$RecordWithParameters = [ordered] @{"Key" = "";
"Value" = ""}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** Parameters part *****"
ForEach($boundparam in $PSBoundParameters.GetEnumerator())
{
$tmpValue = $($boundparam.Value)
$Value = ""
If ($tmpValue -is [array])
{
ForEach ($object in $tmpValue)
{
If (-not($value))
{
$Value = $object
}
else
{
$Value +=",$($object)"
}
}
}
else
{
$Value = $tmpValue
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Key: $($boundparam.Key) Value: $Value"
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End Parameters part *****`r`n"
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The parameters are not written to the logfile due to PowerShell ConstrainedMode."
}
# =============================================================================================================================================
# Write the logged in user details to the log file.
# =============================================================================================================================================
$ThisFunctionName = "[Main - User Details]"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** User details part *****"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logged on user: $LoggedOnUserInDomainFormat"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logged on user (SID): $UseridSID"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Installation account: $InstallAccount"
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Language: $((Find-Language -CurrentUserSID $UseridSID).SubString(0, 2))"
If ($Global:gblDetailedLogging)
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Logfile: $Global:LogFile"
}
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "***** End User details part *****`r`n"
# =============================================================================================================================================
# Define the error number and messages
# =============================================================================================================================================
$Error01 = "There is no working internet connection. The application is quit."
$Error02 = "The Powershell Language mode '$PowerShellLanguageMode' is not supported."
$Error16 = "The file '$JSONFilename' does not exists."
# =============================================================================================================================================
# Do some error handling:
# - Check if there is a working internet connection.
# - Powershell language mode shoudl be FullLanguage.
# =============================================================================================================================================
$InternetConnection = $True
if ($Global:gblFullLanguage)
{
$InternetConnection = Check-WorkingInternetConnection -HostNameToCheck www.bing.com
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Checking internetconnection is not possible due to the PowerShell Language Mode $PowerShellLanguageMode."
}
If (-not($InternetConnection)) {$ErrorNumber += 1}
If (-not($Global:gblFullLanguage)) {$ErrorNumber += 2}
If ($JSONFilename -and -not (Test-Path $JSONFilename)) {$ErrorNumber += 16}
# =============================================================================================================================================
# Find the proxy server
# =============================================================================================================================================
If ($InternetConnection) {$ProxyServer = Get-Proxy}
# =============================================================================================================================================
# Add assembly (only FullLanguage and not silent)
# =============================================================================================================================================
If (($Global:gblFullLanguage) -and (-not $Silent))
{
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Runtime
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
$DetectedWidth = ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize).Width
$DetectedHeight = ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize).Height
$Error04 = "The detected screen width of $DetectedWidth is less than the minimum width of $MinimumWidth."
$Error08 = "The detected screen height of $DetectedHeight is less than of the minimum height of $MinimumHeight."
If ($DetectedWidth -le $MinimumWidth) {$ErrorNumber += 4}
If ($DetectedHeight -le $MinimumHeight) {$ErrorNumber += 8}
#----------------------------------------------
#region Define SAPIEN Types
#----------------------------------------------
try{
[SAPIENTypes.ProgressBarOverlay] | Out-Null
}
catch
{
If ($PSVersionTable.PSVersion.Major -ge 7)
{
$Assemblies = 'System.Windows.Forms', 'System.Drawing', 'System.Drawing.Primitives', 'System.ComponentModel.Primitives', 'System.Drawing.Common', 'System.Runtime'
}
else
{
$Assemblies = 'System.Windows.Forms', 'System.Drawing'
}
Add-Type -ReferencedAssemblies $Assemblies -TypeDefinition @"
using System;
using System.Windows.Forms;
using System.Drawing;
namespace SAPIENTypes
{
public class ProgressBarOverlay : System.Windows.Forms.ProgressBar
{
public ProgressBarOverlay() : base() { SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); }
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x000F)// WM_PAINT
{
if (Style != System.Windows.Forms.ProgressBarStyle.Marquee || !string.IsNullOrEmpty(this.Text))
{
using (Graphics g = this.CreateGraphics())
{
using (StringFormat stringFormat = new StringFormat(StringFormatFlags.NoWrap))
{
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
if (!string.IsNullOrEmpty(this.Text))
g.DrawString(this.Text, this.Font, Brushes.Black, this.ClientRectangle, stringFormat);
else
{
int percent = (int)(((double)Value / (double)Maximum) * 100);
g.DrawString(percent.ToString() + "%", this.Font, Brushes.Black, this.ClientRectangle, stringFormat);
}
}
}
}
}
}
public string TextOverlay
{
get
{
return base.Text;
}
set
{
base.Text = value;
Invalidate();
}
}
}
}
"@ -IgnoreWarnings | Out-Null
}
#endregion Define SAPIEN Types
}
# =============================================================================================================================================
# Error handling.
# =============================================================================================================================================
If (($ErrorNumber -band 1) -eq 1) {If ($ErrorText) {$ErrorText += "`n$Error01"} else {$ErrorText = $Error01}}
If (($ErrorNumber -band 2) -eq 2) {If ($ErrorText) {$ErrorText += "`n$Error02"} else {$ErrorText = $Error02}}
If (($ErrorNumber -band 4) -eq 4) {If ($ErrorText) {$ErrorText += "`n$Error04"} else {$ErrorText = $Error04}}
If (($ErrorNumber -band 8) -eq 8) {If ($ErrorText) {$ErrorText += "`n$Error08"} else {$ErrorText = $Error08}}
If (($ErrorNumber -band 16) -eq 16) {If ($ErrorText) {$ErrorText += "`n$Error16"} else {$ErrorText = $Error16}}
If ($ErrorNumber -gt 0)
{
$GUI = $True
if ($Silent -or -not $Global:gblFullLanguage) {$GUI = $False}
$DummyValue = Display-MessageBox -Text $ErrorText -GUI:$GUI -Error -Title "Error."
Exit $ErrorNumber
}
# =============================================================================================================================================
# End Error handling.
# =============================================================================================================================================
# =============================================================================================================================================
# Clear the settings if needed.
# =============================================================================================================================================
$ThisFunctionName = "[Main - Clear User Settings]"
If ($ClearUserSettings -and (Test-Path $RegistryKey))
{
Remove-Item -Path $RegistryKey -Force | Out-Null
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "The key '$RegistryKey' has been deleted."
}
# =============================================================================================================================================
# End cleaning the settings if needed.
# =============================================================================================================================================
If ($Silent)
{
# =============================================================================================================================================
# Check if the input file is a valid JSON file. If not, quit!
# =============================================================================================================================================
$ThisFunctionName = "Silent install"
Try
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "Reading '$JSONFilename'."
$tmpJSONObject = Get-Content -Path $JSONFilename -Raw -Encoding UTF8 | ConvertFrom-Json
}
Catch
{
$ErrorMessage = "There is an error near:`n`n"
$ErrorText = $($_.Exception.Message)
[int]$Number = ($ErrorText -split '\((.*?)\)')[1]
$ErrorMessage += $ErrorText.SubString($Number-20)
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry $ErrorMessage
$DummyValue = Display-MessageBox -Text $ErrorMessage -GUI:(-not $Silent) -Error -Title "Error."
Exit 1
}
# =============================================================================================================================================
# Check if the Input JSON File has an 'en' entry.
# =============================================================================================================================================
If (-not($tmpJSONObject.en))
{
$ErrorText = "There is no 'en' entry in the JSON file '$JSONFilename'. So we cannot process this one."
Add-EntryToLogFile -Entry $ErrorText -FunctionName $ThisFunctionName
Display-MessageBox -Title "Error" -Text $ErrorText
Exit 1
}
$Fallback = $False
If ($LanguagesToInclude.Contains("all"))
{
$LanguagesToInclude = @("bg","cs","da","de","es","fr","id","it","ja","lv","nl","sv","el","et","fi","hu","lt","pl","ro","sk","sl","sv","tr","uk","pt","ru","zh")
}
# =============================================================================================================================================
# Remove duplicate languages
# =============================================================================================================================================
$LanguagesToInclude = $LanguagesToInclude | Select-Object -Unique
$Global:gblTable = @()
ForEach ($SupportedLanguage in $LanguagesToInclude)
{
$Language = [CultureInfo]::GetCultures([System.Globalization.CultureTypes]::SpecificCultures) | Where {$_.Name -like "$SupportedLanguage*"} | Select-Object -Property Name,DisplayName
If ($Language)
{
$Record = [ordered] @{"Code" = "";
"Display Name" = "";}
$Record."Code" = $SupportedLanguage.Trim()
$Record."Display Name" = ($Language[0].DisplayName).Split(" ")[0]
$Global:gblTable += New-Object PSObject -Property $Record
Add-EntryToLogFile -Entry "Adding $($SupportedLanguage.Trim()) -> $(($Language[0].DisplayName).Split(" ")[0]) to the table." -FunctionName $ThisFunctionName
}
}
# =============================================================================================================================================
# Process the languages.
# =============================================================================================================================================
If ($TranslatorService -eq "Deepl")
{
If ((Read-Registry -RegistryKey $RegistryKey -ValueName "APIDomain") -and (Read-Registry -RegistryKey $RegistryKey -ValueName "AuthenticationKey"))
{
Add-EntryToLogFile -Entry "Starting the translation with DeepL." -FunctionName $ThisFunctionName
ReadAndProcessJSONFile -InputFile $JSONFilename -LanguagesToProcess $LanguagesToInclude -Silent -TranslationService Deepl
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No details for DeepL found in the registry. Falling back to Google FREE API."
$Fallback = $True
}
}
If ($TranslatorService -eq "GoogleCloudServices")
{
If (Read-Registry -RegistryKey $RegistryKey -ValueName "GoogleAPIKey")
{
Add-EntryToLogFile -Entry "Starting the translation with Google Cloud Services." -FunctionName $ThisFunctionName
ReadAndProcessJSONFile -InputFile $JSONFilename -LanguagesToProcess $LanguagesToInclude -Silent -TranslationService GoogleCloudServices
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No details for Google Cloud Services found in the registry. Falling back to Google FREE API."
$Fallback = $True
}
}
If ($TranslatorService -eq "MicrosoftCognitive")
{
If ((Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionRegion") -and (Read-Registry -RegistryKey $RegistryKey -ValueName "APIMSubscriptionKey"))
{
Add-EntryToLogFile -Entry "Starting the translation with Microsoft Cognitive Services Translator." -FunctionName $ThisFunctionName
ReadAndProcessJSONFile -InputFile $JSONFilename -LanguagesToProcess $LanguagesToInclude -Silent -TranslationService MicrosoftCognitive
}
else
{
Add-EntryToLogFile -FunctionName $ThisFunctionName -Entry "No details for Microsoft Cognitive Translator found in the registry. Falling back to Google FREE API."
$Fallback = $True
}
}
If (($TranslatorService -eq "GoogleFREEAPI") -or $Fallback)
{
Add-EntryToLogFile -Entry "Starting the translation withGoogle FREE API." -FunctionName $ThisFunctionName
ReadAndProcessJSONFile -InputFile $JSONFilename -LanguagesToProcess $LanguagesToInclude -Silent -TranslationService GoogleFREEAPI
}
}
else
{
AddTranslationsToAJSONFile
}
# =============================================================================================================================================
# End application.
# =============================================================================================================================================
After extracting the ZIP file, please 'unblock' the Powershell script and/or the batch file.
