PowerToys/tools/build/convert-resx-to-rc.ps1
Stefan Markovic e637902892
[PowerRename][ImageResizer] Tier1 Win11 Context menu (#19000)
* Test win11 tier1 context menu

* Try to test signing

* Cleanup

* Cleanup project file

* Sign dll
Add PowerToys preffix
Add assets to installer

* expect.txt

* Switch to named pipes
Unregister package on uninstall
Remove unneeded files
Cleanup

* Bring back check if package registered but use per-user method

* Fix win11 check

* expect.txt

* Check if package already registered

* Revert "Check if package already registered"

FindPackages() method needs admin privileges.

This reverts commit 5af584fed4.

* Fix PowerRename args checking

* Cleanup assets

* Tier1 context menu ImageResizer
Minor cleanups
Move logic to package.h

* [WIP] Signing and installer
Expect.txt

* Localized context menu title

* Retarget everything 10.0.18362.0 -> 10.0.19041.0

* Address PR comments
 - check if selection renamable
 - minor cleanup
 - struct initialization

* Fix ImageResizerLib project configuration

* More Windows version updates

* Remove unneeded file & try fix resource build error

* Add Microsoft.PowerToys prefix to packages

* Test

* Fix convert-resx-to-rc.ps1 script issue causing resource files compile error

Don't generate empty STRINGTABLE for resx files without data

* Avoid duplicate context menu items

* [BugReportTool] Report installed context menu packages
2022-06-30 22:10:14 +02:00

214 lines
8.9 KiB
PowerShell

# This script is used to move the resources from all the resx files in the directory (args[0]) to a .rc and .h file for use in C++ projects.
# Root directory which contains the resx files
$parentDirectory = $args[0]
# File name of the base resource.h which contains all the non-localized resource definitions
$baseHeaderFileName = $args[1]
# Target file name of the resource header file, which will be used in code - Example: resource.h
$generatedHeaderFileName = $args[2]
# File name of the base ProjectName.rc which contains all the non-localized resources
$baseRCFileName = $args[3]
# Target file name of the resource rc file, which will be used in code - Example: ProjectName.rc
$generatedRCFileName = $args[4]
# Optional argument: Initial resource id in the resource header file. By default it is 101
if ($args.Count -eq 6)
{
$initResourceID = $args[5]
}
else
{
$initResourceID = 101
}
# Flags to check if the first updated has occurred
$headerFileUpdated = $false
$rcFileUpdated = $false
# Output folder for the new resource files. It will be in ProjectDir\Generated Files so that the files are ignored by .gitignore
$generatedFilesFolder = $parentDirectory + "\Generated Files"
# Create Generated Files folder if it doesn't exist
if (!(Test-Path -Path $generatedFilesFolder))
{
$paramNewItem = @{
Path = $generatedFilesFolder
ItemType = 'Directory'
Force = $true
}
New-Item @paramNewItem
}
# Hash table to get the language codes from the code used in the file name
$languageHashTable = @{ "en" = @("ENU", "ENGLISH", "ENGLISH_US", "English (United States)");
"zh-Hans" = @("CHS", "CHINESE", "NEUTRAL", "Chinese (Simplified)");
"zh-CN" = @("CHS", "CHINESE", "NEUTRAL", "Chinese (Simplified)");
"cs" = @("CSY", "CZECH", "NEUTRAL", "Czech");
"hu" = @("HUN", "HUNGARIAN", "NEUTRAL", "Hungarian");
"pl" = @("PLK", "POLISH", "NEUTRAL", "Polish");
"ro" = @("ROM", "ROMANIAN", "NEUTRAL", "Romanian");
"sk" = @("SKY", "SLOVAK", "NEUTRAL", "Slovak");
"bg" = @("BGR", "BULGARIAN", "NEUTRAL", "Bulgarian");
"ru" = @("RUS", "RUSSIAN", "NEUTRAL", "Russian");
"ca" = @("CAT", "CATALAN", "NEUTRAL", "Catalan");
"de" = @("DEU", "GERMAN", "NEUTRAL", "German");
"es" = @("ESN", "SPANISH", "NEUTRAL", "Spanish");
"fr" = @("FRA", "FRENCH", "NEUTRAL", "French");
"it" = @("ITA", "ITALIAN", "NEUTRAL", "Italian");
"nl" = @("NLD", "DUTCH", "NEUTRAL", "Dutch");
"nb-NO" = @("NOR", "NORWEGIAN", "NORWEGIAN_BOKMAL", "Norwegian Bokmål (Norway)");
"pt-BR" = @("PTB", "PORTUGUESE", "PORTUGUESE_BRAZILIAN", "Portuguese (Brazil)");
"eu-ES" = @("EUQ", "BASQUE", "DEFAULT", "Basque (Basque)");
"tr" = @("TRK", "TURKISH", "NEUTRAL", "Turkish");
"he" = @("HEB", "HEBREW", "NEUTRAL", "Hebrew");
"ar" = @("ARA", "ARABIC", "NEUTRAL", "Arabic");
"ja" = @("JPN", "JAPANESE", "NEUTRAL", "Japanese");
"ko" = @("KOR", "KOREAN", "NEUTRAL", "Korean");
"sv" = @("SVE", "SWEDISH", "NEUTRAL", "Swedish");
"pt-PT" = @("PTG", "PORTUGUESE", "PORTUGUESE", "Portuguese (Portugal)");
"zh-Hant" = @("CHT", "CHINESE", "CHINESE_TRADITIONAL", "Chinese (Traditional)")
"zh-TW" = @("CHT", "CHINESE", "CHINESE_TRADITIONAL", "Chinese (Traditional)")
}
# Store the content to be written to a buffer
$headerFileContent = ""
$rcFileContent = ""
# Iterate over all resx files in parent directory
Get-ChildItem $parentDirectory -Recurse -Filter *.resx |
Foreach-Object {
Write-Host "Processing $($_.FullName)"
$xmlDocument = $null
try {
$xmlDocument = [xml](Get-Content $_.FullName -ErrorAction:Stop)
}
catch {
Write-Host "Failed to load $($_.FullName)"
exit 0
}
# Get language code from file name
$lang = "en"
$tokens = $_.Name -split "\."
if ($tokens.Count -eq 3) {
$lang = $tokens[1]
} else {
$d = $_.Directory.Name
If ($d.Contains('-')) { # Looks like a language directory
$lang = $d
}
}
$langData = $languageHashTable[$lang]
if ($null -eq $langData -and $lang.Contains('-')) {
# Modern Localization comes in with language + country tuples;
# we want to detect the language alone if we don't support the language-country
# version.
$lang = ($lang -split "-")[0]
$langData = $languageHashTable[$lang]
}
if ($null -eq $langData) {
Write-Warning "Unknown language $lang"
Return
}
$newLinesForRCFile = ""
$newLinesForHeaderFile = ""
$count = $initResourceID
try {
foreach ($entry in $xmlDocument.root.data) {
$culture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US')
# Each resource is named as IDS_ResxResourceName, in uppercase. Escape occurrences of double quotes in the string
$lineInRCFormat = "IDS_" + $entry.name.ToUpper($culture) + " L`"" + $entry.value.Replace("`"", "`"`"") + "`""
$newLinesForRCFile = $newLinesForRCFile + "`r`n " + $lineInRCFormat
# Resource header file needs to be updated only for one language
if (!$headerFileUpdated) {
$lineInHeaderFormat = "#define IDS_" + $entry.name.ToUpper($culture) + " " + $count.ToString()
$newLinesForHeaderFile = $newLinesForHeaderFile + "`r`n" + $lineInHeaderFormat
$count++
}
}
}
catch {
echo "Failed to read XML document."
exit 0
}
if ($newLinesForRCFile -ne "") {
# Add string table syntax
$newLinesForRCFile = "`r`nSTRINGTABLE`r`nBEGIN" + $newLinesForRCFile + "`r`nEND"
$langStart = "`r`n/////////////////////////////////////////////////////////////////////////////`r`n// " + $langData[3] + " resources`r`n`r`n"
$langStart += "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_" + $langData[0] + ")`r`nLANGUAGE LANG_" + $langData[1] + ", SUBLANG_" + $langData[2] + "`r`n"
$langEnd = "`r`n`r`n#endif // " + $langData[3] + " resources`r`n/////////////////////////////////////////////////////////////////////////////`r`n"
$newLinesForRCFile = $langStart + $newLinesForRCFile + $langEnd
}
# Initialize the rc file with an auto-generation warning and content from the base rc
if (!$rcFileUpdated) {
$rcFileContent = "// This file was auto-generated. Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.`r`n"
try {
$rcFileContent += (Get-Content $parentDirectory\$baseRCFileName -Raw)
}
catch {
echo "Failed to read base rc file."
exit 0
}
$rcFileUpdated = $true
}
# Add in the new string table to the rc file
$rcFileContent += $newLinesForRCFile
# Resource header file needs to be set only once, with an auto-generation warning, content from the base resource header followed by #define for all the resources
if (!$headerFileUpdated) {
$headerFileContent = "// This file was auto-generated. Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.`r`n"
try {
$headerFileContent += (Get-Content $parentDirectory\$baseHeaderFileName -Raw)
}
catch {
echo "Failed to read base header file."
exit 0
}
$headerFileContent += $newLinesForHeaderFile
$headerFileUpdated = $true
}
}
# Write to header file if the content has changed or if the file doesnt exist
try {
if (!(Test-Path -Path $generatedFilesFolder\$generatedHeaderFileName) -or (($headerFileContent + "`r`n") -ne (Get-Content $generatedFilesFolder\$generatedHeaderFileName -Raw))) {
Set-Content -Path $generatedFilesFolder\$generatedHeaderFileName -Value $headerFileContent
}
else {
# echo "Skipping write to generated header file"
}
}
catch {
echo "Failed to access generated header file."
exit 0
}
# Write to rc file if the content has changed or if the file doesnt exist
try {
if (!(Test-Path -Path $generatedFilesFolder\$generatedRCFileName) -or (($rcFileContent + "`r`n") -ne (Get-Content $generatedFilesFolder\$generatedRCFileName -Raw))) {
Set-Content -Path $generatedFilesFolder\$generatedRCFileName -Value $rcFileContent -Encoding unicode
}
else {
# echo "Skipping write to generated rc file"
}
}
catch {
echo "Failed to access generated rc file."
exit 0
}