GUi scripting foreign language systems

Is it possible using ASObjC to query the current language ( yes ) and then translate GUI elements that are translated when operating under a foreign language?

i.e. Translating From

    tell application "System Events" to tell application process "System Settings" to return pop up button "Automatically hide and show the menu bar" of group 7 of UI element 1 of group 1 of UI element 3 of splitter group 1 of group 1 of window "Control Center"

to

tell application "System Events" to tell application process "Réglages Système" to return pop up button "Masquer/afficher automatiquement la barre des menus" of group 7 of UI element 1 of group 1 of UI element 3 of splitter group 1 of group 1 of window "Centre de contrôle"

In the same vein, I am encountering inconsistencies in reported UI element types from different devices running the same version of MacOS when exploring them in Script Debugger’s Dictionary. Not expected differences like in the above or in the following code, which changes depending on how I explore the object model.

tell application "System Events"
	tell its application process "System Settings"
		tell its window "Control Center"
			tell its UI element 1
				tell its UI element 1
					tell its UI element 3
						tell its UI element 1
							tell its UI element 1
								tell its UI element 12
									pop up button "Automatically hide and show the menu bar"
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
	end tell
end tell

tell application "System Events"
	tell its application process "System Settings"
		tell its window "Control Center"
			tell its group 1
				tell its splitter group 1
					tell its group 2
						tell its group 1
							tell its scroll area 1
								tell its group 7
									pop up button "Automatically hide and show the menu bar"
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
	end tell
end tell

…but, rather, receiving a reference to a ‘list’ UI element on one device where another returns the same UI element as a ‘group’. Has anyone else encountered this?

Should I only be referencing UI elements by UI element index to avoid this? That seems very opaque when coding but if I must.

You can try:

set ss_ to localized string "CFBundleName" from table "InfoPlist" in bundle file "System:Applications:System Settings.app"

set cc_ to localized string "CFBundleName" from table "InfoPlist" in bundle file "System:Library:ExtensionKit:Extensions:ControlCenterSettings.appex"

set ah_ to localized string "Automatically hide and show the menu bar" in bundle file "System:Library:ExtensionKit:Extensions:ControlCenterSettings.appex"

tell application "System Events" to tell application process ss_ to return pop up button ah_ of group 7 of UI element 1 of group 1 of UI element 3 of splitter group 1 of group 1 of window cc_

The localized string for System Settings is in /System/Applications/System Settings.app/Contents/Resources/InfoPlist.loctable

<key>fr</key>
<dict>
	<key>CFBundleName</key>
	<string>Réglages Système</string>

The localized string for Control Center is in /System/Library/ExtensionKit/Extensions/ControlCenterSettings.appex/Contents/Resources/InfoPlist.loctable

	<key>CFBundleName</key>
	<string>Centre de contrôle</string>

The localized string for Automatically hide and show the menu bar is in /System/Library/ExtensionKit/Extensions/ControlCenterSettings.appex/Contents/Resources/Localizable.loctable

	<key>Automatically hide and show the menu bar</key>
	<string>Masquer/afficher automatiquement la barre des menus</string>

You can open these files as text after copying them to your local folder and running plutil -convert xml1 InfoPlist.loctable in Terminal.

BTW, the code above doesn’t work for me but the below does:

tell application "System Events" to tell application process ss_ to return pop up button ah_ of group 9 of scroll area 1 of group 1 of group 2 of splitter group 1 of group 1 of window cc_

(Edit) How do you specify a code block as AppleScript or XML?

2 Likes

Hello @paulskinner :wave:

I’m not really good at scripting - but @gluebyte‘s suggestion is the way to go.

Of course you should not forget the use framework statement for Apple‘s Foundation Framework.

I also recommend that you develop the script in Script Debugger and migrate it to use Properties.

I also recommend you to use Properties instead of standard variable syntax for the placeholders.

If you do that, you’ll have more performance in your Scripts right at runtime.

Greetings from Germany :de:

Tobias

Thanks for this @gluebyte and you too @Nr.5-need_input I’ll work on this and see what I can do. I foresee a huge expansion of my codebase for System Settings though. I expect this will have to be it’s own translation library.

FWIW, For current keyboard layout, this works on Mojave:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use framework "AppKit"

set inputContext to (current application's NSTextView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, 0, 0)))'s inputContext()

set enabledLayouts to inputContext's keyboardInputSources() as list
set currentLayoutID to inputContext's selectedKeyboardInputSource() as text
set currentLayoutName to (current application's NSTextInputContext's localizedNameForInputSource:currentLayoutID) as text
set text item delimiters to linefeed

set enableLayoutText to (enabledLayouts as list) as text

return ¬
	"Current Layout Name:
" & currentLayoutName & "

" & "Current Layout ID:
" & currentLayoutID & "

Enabled Layouts: " & "
" & enableLayoutText