Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 121 additions & 43 deletions bucket/attribute-changer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,142 @@
"description": "A Windows Explorer shell extension that allows users to easily change file and folder properties with a right-click.",
"license": "Freeware",
"notes": [
"BRAZILIAN PORTUGUESE is unavailable due to the developer removing support for the language.",
"",
"IMPORTANT FOR NON-ENGLISH SPEAKERS!!!",
"If you want this application translated to your native language, please run the following command:",
"change-ac-language.ps1 <language_id>",
"Launch argumentless to see the list of available languages and their corresponding IDs.",
"",
"1 = CZECH 5 = HUNGARIAN 9 = POLISH 13 = ENGLISH",
"2 = DANISH 6 = ITALIAN 10 = SPANISH",
"3 = FRENCH 7 = KOREAN 11 = SWEDISH",
"4 = GERMAN 8 = DUTCH 12 = TURKISH",
"",
"Ex. If you want the Attribute Changer interface language to Czech, you would run:",
"change-ac-language.ps1 1"
"Scoop persists the selected language, but the language IDs could be changed at any time by the developer.",
"If this happens, you can always run the command above to set the language again."
Comment thread
SiriosDev marked this conversation as resolved.
],
"url": "https://www.petges.lu/pubfiles/ac-11_40b.exe",
"hash": "md5:16bf84bb8e68853a05a000140e4ee6b4",
"innosetup": true,
"architecture": {
"64bit": {
"pre_install": [
"if (!(is_admin)) { error \"$app requires admin rights to $cmd\"; break }",
"Get-ChildItem \"$dir\\*,1*\" -Include '*.exe', '*.dll' | Remove-Item",
"Get-ChildItem \"$dir\\*,2*\" -Include '*.exe', '*.dll' | Rename-Item -NewName { $_ -replace '\\,2', '' }",
"Start-Process 'regsvr32' -ArgumentList @(\"$dir\\acshell.dll\", '/s') -Verb 'RunAs' -Wait; Stop-Process -Name 'explorer' -ErrorAction 'SilentlyContinue' -Force",
"Start-Sleep -Seconds 2"
]
},
"32bit": {
"pre_install": [
"if (!(is_admin)) { error \"$app requires admin rights to $cmd\"; break }",
"Get-ChildItem \"$dir\\*,2*\" -Include '*.exe', '*.dll' | Remove-Item",
"Get-ChildItem \"$dir\\*,1*\" -Include '*.exe', '*.dll' | Rename-Item -NewName { $_ -replace '\\,1', '' }",
"Start-Process 'regsvr32' -ArgumentList @(\"$dir\\acshell.dll\", '/s') -Verb 'RunAs' -Wait; Stop-Process -Name 'explorer' -ErrorAction 'SilentlyContinue' -Force",
"Start-Sleep -Seconds 2"
]
}
},
"pre_install": "if (!(is_admin)) { error \"$app requires admin rights to $cmd\"; break }",
"installer": {
"script": [
"# Innosetup flag doesn't work correctly with this installer, due to the way the devoloper structured langs in the installer",
"# Using a custom installer script to work around it.",
"Expand-InnoArchive -Path \"$dir\\$fname\"",
"Invoke-ExternalCommand -FilePath (Get-HelperPath -Helper Innounp) -ArgumentList '-x', \"$dir\\$fname\", \"-d$dir\", 'install_script.iss' -LogPath \"$dir\\innounp-iss.log\" | Out-Null",
"$installScript = Get-Content -Path \"$dir\\install_script.iss\" -Raw",
"",
"",
"# Copying common and architecture-specific files according to the install script",
"$patternArc = 'Source: \"(?<Source>\\{app\\}\\\\(?!messages,)(?!ac,)(?!template)[^\"]*?)\"; DestDir: \"(?<DestDir>\\{app\\}[^\"]*?)?\"(?:; DestName: \"(?<DestName>[^\"]*?)\")?(?:; Tasks: [^\"]*?)?; Check: \"(?<Check>[^\"]*?)\";'",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"$matchesArc = [regex]::Matches($installScript, $patternArc)",
"foreach ($match in $matchesArc) {",
" $source = $match.Groups['Source'].Value -replace '{app}', $dir",
" $destDir = $match.Groups['DestDir'].Value -replace '{app}', $dir",
" $destName = $match.Groups['DestName'].Value",
" $check = $match.Groups['Check'].Value",
" $is64bit = $check -eq 'Is64BitInstallMode'",
" $is32bit = $check -eq 'Not Is64BitInstallMode'",
" $isArchitectureIncompatible = if ($architecture -eq '64bit') {",
" -not $is64bit -and $is32bit",
" } else {",
" -not $is32bit -and $is64bit",
" }",
" if ($isArchitectureIncompatible) {",
" Remove-Item -Path $source -Force",
" continue",
" }",
" if (-not $destDir) { $destDir = $source }",
" if (-not $destName) { $destName = Split-Path -Path $source -Leaf }",
" $destPath = Join-Path -Path $destDir -ChildPath $destName",
" if ($source -ne $destPath) {",
" Move-Item -Path $source -Destination $destPath",
" }",
"}",
"",
"",
"# Copying and renaming template.ini to the messages,english.ini file according to the install script",
"$patternTemplate = 'Source: \"(?<Source>\\{app\\}\\\\template[^\"]*?)\"; DestDir: \"(?<DestDir>\\{app\\}[^\"]*?)\"(?:; DestName: \"(?<DestName>[^\"]*?)\")?;'",
"$matchesTemplate = [regex]::Matches($installScript, $patternTemplate)",
"foreach ($match in $matchesTemplate) {",
" $source = $match.Groups['Source'].Value -replace '{app}', $dir",
" $destDir = $match.Groups['DestDir'].Value -replace '{app}', $dir",
" $destName = 'messages,english.ini'",
" if (-not $destDir) { $destDir = $source }",
" $destPath = Join-Path -Path $destDir -ChildPath $destName",
" if ($source -ne $destPath) {",
" Move-Item -Path $source -Destination $destPath",
" }",
"}",
"",
"",
"# Copying messages files according to the install script",
"$patternMes = 'Source: \"(?<Source>\\{app\\}\\\\messages,[^\"]*?)\"; DestDir: \"(?<DestDir>\\{app\\}[^\"]*?)\"(?:; DestName: \"(?<DestName>[^\"]*?)\")?; Languages: \"(?<Lang>[^\"]*?)\";'",
"$matchesMes = [regex]::Matches($installScript, $patternMes)",
"foreach ($match in $matchesMes) {",
" $source = $match.Groups['Source'].Value -replace '{app}', $dir",
" $destDir = $match.Groups['DestDir'].Value -replace '{app}', $dir",
" $lang = $match.Groups['Lang'].Value",
" $destName = 'messages,' + $lang + '.ini'",
" if (-not $destDir) { $destDir = $source }",
" $destPath = Join-Path -Path $destDir -ChildPath $destName",
" if ($source -ne $destPath) {",
" Move-Item -Path $source -Destination $destPath",
" }",
Comment thread
SiriosDev marked this conversation as resolved.
"}",
"",
"",
"# Copying ac files according to the install script",
"$patternAc = 'Source: \"(?<Source>\\{app\\}\\\\ac,[^\"]*?)\"; DestDir: \"(?<DestDir>\\{app\\}[^\"]*?)\"(?:; DestName: \"(?<DestName>[^\"]*?)\")?; Languages: \"(?<Lang>[^\"]*?)\";'",
"$matchesAc = [regex]::Matches($installScript, $patternAc)",
"$langs = @()",
"foreach ($match in $matchesAc) {",
" $source = $match.Groups['Source'].Value -replace '{app}', $dir",
" $destDir = $match.Groups['DestDir'].Value -replace '{app}', $dir",
" $lang = $match.Groups['Lang'].Value",
" $destName = 'ac,' + $lang + '.pdf'",
" $langs += $lang",
" if (-not $destDir) { $destDir = $source }",
" $destPath = Join-Path -Path $destDir -ChildPath $destName",
" if ($source -ne $destPath) {",
" Move-Item -Path $source -Destination $destPath",
" }",
"}",
"",
"",
"# Removing the installer files after installation",
"Remove-Item -Path \"$dir\\$fname\" -Force",
"Remove-Item -Path \"$dir\\install_script.iss\" -Force",
"",
"",
"# Creating the change-ac-language.ps1 script to allow users to change the language after installation",
"$value = @\"",
"if (!(`$args.Count -eq 1)) { Write-Host 'INVALID USAGE! Please run ``scoop info attribute-changer`` for help on proper command usage.'; exit }",
"`$ac_language = `$args[0].toString()",
"`$langs = @(\"$($langs -join '\", \"')\")",
Comment thread
SiriosDev marked this conversation as resolved.
"if (!(`$args.Count -eq 1))",
"{",
" Write-Host 'INVALID USAGE! Add a language as argument following this scheme: ';",
" for (`$i = 0; `$i -lt `$langs.Count; `$i++) {",
" Write-Host \"`$(`$i + 1) = `$(`$langs[`$i])\"",
" }",
" exit",
"}",
"`$index = [int]`$args[0] - 1",
"if (`$index -lt 0 -or `$index -ge `$langs.Count) { `$index = `$langs.IndexOf('english'); if (`$index -lt 0) { `$index = 0 } }",
"`$ac_language = `$langs[`$index]",
"Copy-Item \"$dir\\messages,`$ac_language.ini\" \"$dir\\messages.ini\" -Force",
"Copy-Item \"$dir\\ac,`$ac_language.pdf\" \"$dir\\ac.pdf\" -Force",
"Set-Content \"$dir\\langCode\" (`$index + 1) -Encoding utf8 -Force",
Comment on lines +121 to +126
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Persist the language key, not the transient numeric slot.

The new layout finally gives you stable identifiers (english, german, ...), but langCode still stores a 1-based position. If the vendor reorders languages in a future installer, Line 141 will silently reapply the wrong language on upgrade even though the extracted filenames are unchanged. Persist the language name and only translate numeric IDs at the CLI boundary.

Proposed fix
-`$index = [int]`$args[0] - 1
-if (`$index -lt 0 -or `$index -ge `$langs.Count) { `$index = `$langs.IndexOf('english'); if (`$index -lt 0) { `$index = 0 } }
-`$ac_language = `$langs[`$index]
+`$selection = `$args[0].Trim().ToLowerInvariant()
+if (`$selection -match '^\d+$') {
+    `$index = [int]`$selection - 1
+    if (`$index -lt 0 -or `$index -ge `$langs.Count) { `$index = `$langs.IndexOf('english'); if (`$index -lt 0) { `$index = 0 } }
+    `$ac_language = `$langs[`$index]
+} else {
+    `$ac_language = if (`$langs -contains `$selection) { `$selection } else { if (`$langs -contains 'english') { 'english' } else { `$langs[0] } }
+}
 Copy-Item \"$dir\\messages,`$ac_language.ini\" \"$dir\\messages.ini\" -Force
 Copy-Item \"$dir\\ac,`$ac_language.pdf\" \"$dir\\ac.pdf\" -Force
-Set-Content \"$dir\\langCode\" (`$index + 1) -Encoding utf8 -Force
+Set-Content \"$dir\\langCode\" `$ac_language -Encoding utf8 -Force
 ...
 if (!(Test-Path \"$persist_dir\\langCode\")) {
    $defaultIdx = $langs.IndexOf('english'); if ($defaultIdx -lt 0) { $defaultIdx = 0 }
-   Set-Content \"$dir\\langCode\" ($defaultIdx + 1) -Encoding utf8
+   Set-Content \"$dir\\langCode\" $langs[$defaultIdx] -Encoding utf8
 }

Also applies to: 133-145

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bucket/attribute-changer.json` around lines 123 - 128, Persist the language
identifier string instead of the transient numeric slot: write the selected
$ac_language (e.g., "english", "german") into the langCode file rather than
($index + 1), so future reorders of $langs don't break upgrades; update the
logic around $index / $ac_language (the Copy-Item lines that use $ac_language
and the Set-Content that writes langCode) to store the name, and move any
conversion between numeric CLI IDs and $ac_language to the CLI boundary where
arguments are parsed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll wait for a maintainer's opinion on this

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SiriosDev, that's completely fair — happy to wait for a maintainer's input. For context when they review: the concern is that storing a 1-based position in langCode ties persistence to the current ordering of $langs. If the vendor reorders languages in a future installer, post_install would silently apply the wrong language on upgrade even though the extracted filenames (messages,german.ini, etc.) would still be valid. Persisting the language name (e.g., "german") instead would make upgrades resilient to reordering. The tradeoff is a slightly more complex CLI boundary in change-ac-language.ps1, as shown in the proposed fix above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but if the developer were to change the language name tomorrow—for example, by switching to langcodes—the worst-case scenario would be a fallback, which would still require the user to change the language manually, but with the added inconvenience of having to type out an entire string instead of just a number.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SiriosDev, that's a fair point — if the developer renames language identifiers entirely, both approaches result in the same fallback outcome and require manual re-selection. One clarification on the UX concern though: the proposed fix actually preserves numeric input at the CLI boundary (the -match '^\d+$' branch handles it), so users would still type numbers like change-ac-language.ps1 2. The langCode file is only an internal detail that users never interact with directly.

In summary, the real tradeoff is between failure modes:

  • Numeric index stored: vendor reorders → wrong language applied silently on upgrade (harder to detect)
  • Name stored: vendor renames → fallback to English on upgrade (obvious, user is effectively notified by getting English)

Both are defensible. Since you're waiting for a maintainer's opinion anyway, I'll leave it there — it's ultimately a judgment call on which failure mode is preferable.

Comment thread
SiriosDev marked this conversation as resolved.
"\"@",
"Set-Content \"$dir\\change-ac-language.ps1\" $value -Encoding 'utf8' -Force"
"Set-Content \"$dir\\change-ac-language.ps1\" $value -Encoding 'utf8' -Force",
"",
"",
"if (!(Test-Path \"$persist_dir\\langCode\")) {",
" $defaultIdx = $langs.IndexOf('english'); if ($defaultIdx -lt 0) { $defaultIdx = 0 }",
" Set-Content \"$dir\\langCode\" ($defaultIdx + 1) -Encoding utf8",
"}"
Comment thread
SiriosDev marked this conversation as resolved.
]
},
"post_install": [
"if (!(is_admin)) { error \"$app requires admin rights to $cmd\"; break }",
"& \"$dir\\change-ac-language.ps1\" (Get-Content \"$dir\\langCode\" -Raw)",
"Start-Process 'regsvr32' -ArgumentList @(\"$dir\\acshell.dll\", '/s') -Verb 'RunAs' -Wait; Stop-Process -Name 'explorer' -ErrorAction 'SilentlyContinue' -Force",
"Start-Sleep -Seconds 2"
],
"persist": "langCode",
"bin": [
"acmain.exe",
"change-ac-language.ps1"
Expand All @@ -63,16 +151,6 @@
"Attribute Changer"
]
],
"post_install": [
"$documents = (Get-ChildItem $dir -Filter '*.pdf').Length; $subtract = $documents - 5",
"Copy-Item \"$dir\\template.ini\" \"$dir\\messages,$documents.ini\"; Copy-Item \"$dir\\template.ini\" \"$dir\\messages.ini\"; Copy-Item \"$dir\\ac,$(($documents - $subtract) - 2).pdf\" \"$dir\\ac.pdf\"",
"Remove-Item \"$dir\\ac,$(($documents - $subtract) - 2).pdf\"; Copy-Item \"$dir\\messages,$(($documents - $subtract) - 2).ini\" \"$dir\\messages.ini\" -Force",
"$Value = $documents - $subtract",
"for ($count = 0; $count -le ($documents - 3); $count++) {",
" $OriginalValue = $Value + $count; $NewValue = $OriginalValue - 1; Rename-Item \"$dir\\ac,$OriginalValue.pdf\" \"ac,$NewValue.pdf\" -ErrorAction 'SilentlyContinue'",
"}",
"Copy-Item \"$dir\\ac.pdf\" \"$dir\\ac,$documents.pdf\""
],
"pre_uninstall": [
"if (!(is_admin)) { error \"$app requires admin rights to $cmd\"; break }",
"Start-Process 'regsvr32' -ArgumentList @('/u', \"$dir\\acshell.dll\", '/s') -Verb 'RunAs' -Wait; Stop-Process -Name 'explorer' -Force",
Expand Down
Loading