Having been looking at this myself this morning, I’ve found that neither Yvan’s or KniazidisR’s original scripts work on my Mojave system. Yvan’s tries to read the variable ‘byKind’, which hasn’t been set, and KniazidisR’s clicks a menu item called “Use Groups”, which doesn’t exist in that menu on my system.
Yvan’s Catalina-friendly version (post #6) does work on my machine, but uses more GUI Scripting than is strictly necessary (as I see KniazidisR’s now realised).
As chance would have it, Shane posted some handlers on the Late Night Software fora a day or two ago which do a fair job of translating strings for GUI Scripting. In particular, they work for the Finder term “Kind”. Here’s my entry into the fray. It uses Shane’s Library and two of the handlers I mentioned and uses Finder scripting to set the list view and sort column. GUI Scripting is only used for grouping. It seems to be slightly faster than Yvan’s post #6 script. Most of its bulk is the handler which translates “Kind” into the local language.
use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use script "FileManagerLib"
use scripting additions
-- Get the local string for "Kind".
property dictCache : missing value -- we cache strings dictionaries here to speed multiple look-ups a bit
set byKind to my localizedStringForEnglish:"Kind" inBundle:(path to application "Finder")
-- The above handler returns missing value for "None" and "none" for "none" in Mojave. The following line's in case "Group by:" ever needs to be cancelled.
if ((byKind is missing value) or (byKind is "none")) then set byKind to 1
set theFolder to (choose folder)
set PosixPath to POSIX path of theFolder
set theFolders to objects of PosixPath result type files list with searching subfolders without include files and include invisible items -- Requires FileManagerLib.
set end of theFolders to theFolder
repeat with aFolder in theFolders
tell application "Finder"
set thisWindow to (make new Finder window to aFolder)
tell thisWindow's list view options to set sort column to name column -- This won't take effect until the next time the window's opened.
set thisWindow's current view to list view
end tell
tell application "System Events"
tell application process "Finder"
set frontmost to true
keystroke "j" using {command down}
repeat until (subrole of window 1 is "AXSystemFloatingWindow")
delay 0.1
end repeat
tell pop up button 1 of window 1
click
repeat until menu 1 exists
delay 0.1
end repeat
click menu item byKind of menu 1
end tell
keystroke "j" using {command down}
--repeat while (subrole of window 1 is "AXSystemFloatingWindow")
-- delay 0.1
-- end repeat
end tell
end tell
tell application "Finder" to close thisWindow
end repeat
-- Handlers by Shane Stanley <https://forum.latenightsw.com/t/localizing-gui-scripts/2246>:
-- use this if you have the English name and it is in the standard Localized.strings file
on localizedStringForEnglish:enString inBundle:fileOrNSURL
set langID to current application's NSLocale's currentLocale()'s localeIdentifier()
return my localizedStringFor:enString fromTable:"" inBundle:fileOrNSURL destLang:langID sourceLang:"en"
end localizedStringForEnglish:inBundle:
-- use this if you also want to specify a particular .strings file. A destLangCode of "" means the current locale, and a stringsFileName of "" means the default Localizable.strings file
on localizedStringFor:baseString fromTable:stringsFileName inBundle:fileOrNSURL destLang:destLangCode sourceLang:sourceLangCode
if stringsFileName is "" then set stringsFileName to "Localizable"
set theBundle to current application's NSBundle's bundleWithURL:fileOrNSURL
set sourceLangString to current application's NSString's stringWithString:sourceLangCode
-- make key to search for cached values
set cacheKey to current application's NSString's stringWithFormat_("%@_%@_%@", theBundle's bundleIdentifier(), stringsFileName, sourceLangCode)
if my dictCache is missing value then set my dictCache to current application's NSMutableDictionary's dictionary()
-- get source strings values
set sourceDict to dictCache's objectForKey:cacheKey
if sourceDict = missing value then
set sourceURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:sourceLangString
if sourceURL is missing value and (sourceLangString's containsString:"_") as boolean then
-- try stripping off country-specific part
set sourceLangString to sourceLangString's substringToIndex:2
set sourceURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:sourceLangString
end if
if sourceURL is missing value then
-- try long name for localization
set sourceLangString to (current application's NSLocale's localeWithLocaleIdentifier:"en")'s localizedStringForLocaleIdentifier:sourceLangString
set sourceURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:sourceLangString
end if
if sourceURL is missing value then error "No " & sourceLangCode & " localization found"
set theData to current application's NSData's alloc()'s initWithContentsOfURL:sourceURL
if theData is missing value then error "No " & sourceLangCode & " localization found"
set sourceDict to (current application's NSPropertyListSerialization's propertyListWithData:theData options:0 format:0 |error|:(missing value))
dictCache's setObject:sourceDict forKey:cacheKey
end if
-- make key to search for cached values
set cacheKey to current application's NSString's stringWithFormat_("%@_%@_%@", theBundle's bundleIdentifier(), stringsFileName, destLangCode)
-- get dest strings values
set destDict to dictCache's objectForKey:cacheKey
if destDict = missing value then
if destLangCode is "" then
set destLangString to current application's NSLocale's currentLocale()'s localeIdentifier()
else
set destLangString to current application's NSString's stringWithString:destLangCode
end if
set localURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:destLangString
if localURL is missing value and (destLangString's containsString:"_") as boolean then
-- try stripping off country-specific part
set destLangString to destLangString's substringToIndex:2
set localURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:destLangString
end if
if localURL is missing value then
-- try long name for localization
set destLangString to (current application's NSLocale's localeWithLocaleIdentifier:"en")'s localizedStringForLocaleIdentifier:destLangString
set localURL to theBundle's URLForResource:stringsFileName withExtension:"strings" subdirectory:"" localization:destLangString
end if
if localURL is missing value then error "No " & destLangCode & " localization found"
set theData to current application's NSData's alloc()'s initWithContentsOfURL:localURL
if theData is missing value then error "No " & destLangCode & " localization found"
set destDict to (current application's NSPropertyListSerialization's propertyListWithData:theData options:0 format:0 |error|:(missing value))
dictCache's setObject:destDict forKey:cacheKey
end if
-- convert from source to dest
set destValue to destDict's objectForKey:((sourceDict's allKeysForObject:baseString)'s firstObject())
if destValue is not missing value then set destValue to destValue as text
return destValue
end localizedStringFor:fromTable:inBundle:destLang:sourceLang:
I missed the fact that the key “N224” is not reachable from the English resources in Catalina.
I edited message #16 which contain now:
if (system attribute "sys2") < 14 then
-- Here with High Sierra or older. Tested with 10.13.6
set o's kind_loc to localized string "N224" in bundle theBundle
else
-- Here with Mojave or newer -- tested with Catalina
set o's kind_loc to localized string "119.title" from table "ArrangeByMenu" in bundle theBundle
end if
Would be glad to know if it’s Ok for Mojave.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 2 janvier 2020 16:15:10
Both of those ‘localized string’ commands return “Kind” on my Mojave system. But I don’t know if that’s because both search locations are native to Mojave or because one of them wasn’t deleted during an upgrade from an earlier OS version.
The problem wasn’t with “Kind” but with “Arrange By:”
if (system attribute "sys2") < 14 then
-- Here with High Sierra or older systems
set aKey to "974.title"
set o's arrangeBy_loc to localized string aKey from table "ViewOptionsWindow" in bundle theBundle
-- In English, the resource isn't available -> "974.title". Define it here.
if o's arrangeBy_loc = aKey then set o's arrangeBy_loc to "Arrange By:"
log o's arrangeBy_loc --> "Arrange By:"
else
-- Here under Mojave or newer (tested with Catalina)
set aKey to "V026"
set arrangeBy_loc to localized string aKey in bundle theBundle --> "Grouper par :" (Catalina)
end if
Would be glad how it works under Mojave.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 2 janvier 2020 18:02:31
If I change the first line to include Mojave systems too, the result is “Group By:”, which is the correct English label for the first pop-up menu in Mojave’s View Options window and for the equivalent button in Finder window toolbars.
On my El Capitan system, that label is “Arrange By:”. Your code returns the correct string there by virtue of the ‘if o’s arrangeBy_loc = aKey …’ line.
I’m an ass, the key is not supposed to be V026 but VO26.
The message #16 is edited accordingly.
You may run this simple test:
set theBundle to path to application "Finder" --> an alias
script o
property arrangeBy_loc : ""
end
if (system attribute "sys2") < 14 then
set aKey to "974.title"
set o's arrangeBy_loc to localized string aKey from table "ViewOptionsWindow" in bundle theBundle
-- In English, the resource isn't available -> "974.title". Define it here.
if o's arrangeBy_loc = aKey then set o's arrangeBy_loc to "Arrange By:"
log o's arrangeBy_loc --> "Arrange By:"
else
set aKey to "VO26" -- with the letter "O", not the digit "0"
set o's arrangeBy_loc to localized string aKey in bundle theBundle --> "Grouper par :" (Catalina)
log o's arrangeBy_loc --> "Arrange By:"
end if
(*
table Localizable.string in en.lproj (English)
<key>VO26</key>
<string>Group By:</string>
table Localizable.string in de.lproj (German)
<key>VO26</key>
<string>Gruppieren nach:</string>
table Localizable.string in fr.lproj (French)
<key>VO26</key>
<string>Grouper par :</string>
*)
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 3 janvier 2020 04:18:29
Now the script does exactly what I want under Catalina.
That is so great.
Now I have two questions:
Where and how do you find the localized strings for the Finder-App?
like: “VO26”, “6.title” or “N224” in
If Apple decides to make some changes in future macOS versions like 10.16, 10.17, etc.
may it will be necessary to make some changes in this script (for example: localized strings).
Did I understand it right?
I ran the test and got this:
-- Don't click [Open this Scriplet in your Editor:]
tell application "Finder"
path to current application
--> error number -1708
«event ascrgdut»
--> error number -1708
path to current application
--> alias "macOS:System:Library:CoreServices:Finder.app:"
end tell
tell current application
system attribute "sys2"
--> 15
localized string "VO26" in bundle alias "macOS:System:Library:CoreServices:Finder.app:"
--> "Group By:"
Result:
error "The variable o is not defined." number -2753 from "o"
Oops I forgot the three instructions defining the script object.
message #49 is edited accordingly.
Some of these days, I will create a thread in which I will post the script which I use since I discovered that my good old friend EasyFind is unable to search in the resources files delivered by Apple.
I just wish to make some complementary tests because I found a case where it return a wrong result.
When I had access to my grand daughter Catalina macBook, I borrowed its folder “/System/Library/” so know I may also search in Catalina resources.
As I dislike wasting space, I am busy removing every files which aren’t relevant for this task.
Working upon your question was a good opportunity to check my script.
Now, I will be able to remove every code using GUI Scripting for tasks which may be achieved by plain Applescript code.
I already knew the cases wher the English resource related to a keyString is not reachable.
I already faced GUI changes introduced in 10.9, 10.10, 10.11, 10.12 and 10.13.
I assumed that change were introduced by 10.14 and 10.15 but I ignored which they are.
I would be glad if somebody is fair enough to send me a copy of the folder “/System/Library/” belonging to Mojave.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 3 janvier 2020 15:05:48
Thanks Yvan!
That sounds really great. I will look up for it.
Today I ran the Test (post #49)
English Log History:
-- Don't click [Open this Scriplet in your Editor:]
tell application "Finder"
path to current application
--> alias "macOS:System:Library:CoreServices:Finder.app:"
end tell
tell current application
system attribute "sys2"
--> 15
localized string "VO26" in bundle alias "macOS:System:Library:CoreServices:Finder.app:"
--> "Group By:"
(*Group By:*)
end tell
German Log History:
-- Don't click [Open this Scriplet in your Editor:]
tell application "Finder"
path to current application
--> alias "macOS:System:Library:CoreServices:Finder.app:"
end tell
tell current application
system attribute "sys2"
--> 15
localized string "VO26" in bundle alias "macOS:System:Library:CoreServices:Finder.app:"
--> "Gruppieren nach:"
(*Gruppieren nach:*)
end tell
I sent you an email with the “/System/Library/” folder from Mojave (10.14.6)
I again had to put things in order in my folders, and I remembered this already old topic. It offered 3 solutions: from me, from @Yvan Koenig and from @Nigel Garvey.
@Yvan Koenig’s solutions (many posts…) often work as they do here, but traditionally contain horribly redundant code, excessive GUI scripting, and verbiage.
@Nigel Garvey’s solution (post #41) works on Catalina too, and I would take it as the best option, but it uses a third party library, AsObjC (load time kills me), additional complexity in getting the localized string, and does not set the Always Open in List View flag.
My solution (post #5) also works on Catalina, but also has a number of drawbacks: nested tell blocks, non-localization, excessive GUI scripting, and does not set the Always Open in List View flag.
Therefore, in the following script, I tried to collect all the best from the topic to solve the problem:
-- script: Group selected folder's and its subfolder's contents by Kind,
-- sort by Name, set Alwais Open in List View, set Use as Defaults
-- written: by me, right now
property pathList : {}
tell application "Finder"
set kindString to localized string "N224"
set alwaysOpenInListViewString to localized string "VO15"
set useAsDefaultsString to localized string "6.title" from table "ViewOptionsWindow"
set theFolders to selection as alias list
activate
end tell
repeat with i from 1 to count theFolders
set aFolder to item i of theFolders
set pathList to pathList & aFolder
my get_All_Folders_of_Folder(aFolder)
end repeat
repeat with aFolder in the pathList
tell application "Finder"
set thisWindow to (make new Finder window to folder aFolder)
set current view of thisWindow to list view
tell thisWindow to tell its list view options to set its sort column to column id name column
end tell
tell application "System Events" to tell process "Finder"
key code 29 using {control down, command down} -- "Use Groups"
keystroke "j" using command down -- "Show View Optons"
tell window 1
set isAlwaysOpenInListView to value of checkbox alwaysOpenInListViewString
if isAlwaysOpenInListView is 0 then click checkbox alwaysOpenInListViewString
click pop up button 1
click menu item kindString of menu 1 of pop up button 1 -- "Kind"
click UI element useAsDefaultsString -- "Use As Defaults"
end tell
keystroke "j" using command down -- "Hide View Optons"
end tell
tell application "Finder" to close thisWindow
end repeat
on get_All_Folders_of_Folder(aFolder)
tell application "System Events"
set foldersList to folders of aFolder whose visible is true
if foldersList is {} then
set the end of pathList to (path of aFolder)
else
repeat with aFolder in foldersList
my get_All_Folders_of_Folder(aFolder)
end repeat
end if
end tell
end get_All_Folders_of_Folder