-
Notifications
You must be signed in to change notification settings - Fork 6.7k
/
Copy pathconvert-resx-to-rc.ps1
200 lines (171 loc) · 8.48 KB
/
convert-resx-to-rc.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# 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
}
# Temporary file created used for resgen
$tempFile = "temporaryResourceFile.txt"
# 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)");
"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)")
}
# Store the content to be written to a buffer
$headerFileContent = ""
$rcFileContent = ""
# Iterate over all resx files in parent directory
Get-ChildItem $parentDirectory -Filter *.resx |
Foreach-Object {
# Use resgen to parse resx to txt. More details at https://docs.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator#converting-between-resource-file-types
try {
resgen $_.FullName $tempFile
}
catch {
echo "resgen failed to convert resx file"
exit 0
}
# Get language code from file name
$lang = "en"
$tokens = $_.Name -split "\."
if ($tokens.Count -eq 3) {
$lang = $tokens[1]
}
$langData = $languageHashTable[$lang]
$newLinesForRCFile = ""
$newLinesForHeaderFile = ""
$count = $initResourceID
try {
foreach ($line in (Get-Content $tempFile -Encoding unicode)) {
# Each line of the resgen text file is of the form ResourceName=ResourceValue with no spaces.
$content = $line -split "=", 2
$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_" + $content[0].ToUpper($culture) + " L`"" + $content[1].Replace("`"", "`"`"") + "`""
$newLinesForRCFile = $newLinesForRCFile + "`r`n " + $lineInRCFormat
# Resource header file needs to be updated only for one language
if (!$headerFileUpdated) {
$lineInHeaderFormat = "#define IDS_" + $content[0].ToUpper($culture) + " " + $count.ToString()
$newLinesForHeaderFile = $newLinesForHeaderFile + "`r`n" + $lineInHeaderFormat
$count++
}
}
}
catch {
echo "Failed to read temporary file."
exit 0
}
# Delete temporary text file used by resgen
Remove-Item $tempFile
# 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
}