The keys used to localize strings aren’t defined in the sdefs.
We may just get them in the resources files available in application’s bundles.
TG_COLOR_x where x is a digit from 0 to 7 is a key in the localizable.strings files used by the system to localize some strings. It’s the one reachable by default but there are numerous other ones.
Infos about these resources are given in Standard Additions’s dictionary:
localized string v : Return the localized string for the specified key
localized string text : the key
[from table text] : the name of the strings file excluding the “.strings” suffix (default is “Localizable”)
[in bundle file] : an alias or file reference to the bundle containing the strings file (default is the current application/script bundle)
→ text : the localized string
Example with the results returned under a system running in French.
CAUTION: The keys aren’t guaranteed to survive a major version change.
(*
Simple case, the string to localize is defined in the table Localizable.strings.
There is no need to describe explicitely the table and the source bundle.
*)
tell application "Finder" to set toRemoveFromiCloudDrive_loc to localized string "A31"
--> "Pour supprimer des éléments d’iCloud Drive, déplacez-les dans votre dossier Bureau ou Documents sur ce Mac."
(*
If the string is defined in an other file we must pass the table's name (without the suffix .strings) and the bundle stroring it
*)
set FinderBundle to path to application "Finder"
--> alias "SSD 500:System:Library:CoreServices:Finder.app:"
set IconSize_loc to localized string "383.title" from table "ViewOptionsWindow" in bundle FinderBundle
--> "Taille des icônes :"
set |Finder/Reveal_loc| to localized string "Finder/Reveal" from table "ServicesMenu" in bundle FinderBundle
--> "Finder/Afficher dans le Finder"
set LastOpen_loc to localized string "116.title" from table "ArrangeByMenu" in bundle FinderBundle
--> "Date de dernière ouverture"
# Other one for the fun
set Volume_loc to localized string "tCs-xJ-UEw.title" from table "ArrangeByMenu" in bundle FinderBundle
--> "Volume"
# It seems that there is no global control upon these tables so several keys may describe the same string.
set showLibrary_loc1 to localized string "Ukt-Pm-iTw.title" from table "ViewOptionsWindow" in bundle FinderBundle
--> "Afficher le dossier Bibliothèque"
set showLibrary_loc2 to localized string "noX-Qe-gkU.title" from table "ViewOptionsWindow" in bundle FinderBundle
--> "Afficher le dossier Bibliothèque"
set showLibrary_loc3 to localized string "sld-Oo-X54.title" from table "ViewOptionsWindow" in bundle FinderBundle
--> "Afficher le dossier Bibliothèque"
I’ve use localized string for years and met changes only two or three times.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mercredi 15 mai 2019 12:08:55
I’m back about localized string because I forgot an important feature.
Sometimes, the English.lproj doesn’t contain every tables available for other countries.
You will see some examples below.
You will discover a case where I am unable to find the correct English spelling.
(*
Simple case, the string to localize is defined in the table Localizable.strings.
There is no need to describe explicitely the table and the source bundle.
*)
tell application "Finder" to set toRemoveFromiCloudDrive_loc to localized string "A31"
--> "Pour supprimer des éléments d’iCloud Drive, déplacez-les dans votre dossier Bureau ou Documents sur ce Mac."
(*
If the string is defined in an other file we must pass the table's name (without the suffix .strings) and the bundle stroring it
*)
set FinderBundle to path to application "Finder"
--> alias "SSD 500:System:Library:CoreServices:Finder.app:"
set theKey to "383.title"
set IconSize_loc to localized string theKey from table "ViewOptionsWindow" in bundle FinderBundle
if IconSize_loc = theKey then # The system run in English for which there is no table "ViewOptionsWindow"
set IconSize_loc to "Icon size:"
end if
log IconSize_loc --> "Taille des icônes :"
set |Finder/Reveal_loc| to localized string "Finder/Reveal" from table "ServicesMenu" in bundle FinderBundle
--> "Finder/Afficher dans le Finder"
set theKey to "116.title"
set LastOpen_loc to localized string theKey from table "ArrangeByMenu" in bundle FinderBundle
if LastOpen_loc = theKey then # The system run in English for which there is no table "ArrangeByMenu"
set LastOpen_loc to "Date Last Opened"
end if
log LastOpen_loc --> "Date de dernière ouverture"
# Other one for the fun
set theKey to "tCs-xJ-UEw.title"
set Volume_loc to localized string theKey from table "ArrangeByMenu" in bundle FinderBundle
if Volume_loc = theKey then # The system run in English for which there is no table "ArrangeByMenu"
set Volume_loc to "Volume"
(*
In fact I don't know which is the exact spelling.
in Russian it's "по тому" which according to Google means "on that"
in Spanish it's "Volumen" which according to Google means "Volume"
in Japanese it's "ボリューム" which according to Google means "Volume"
And I never saw this string in the View menu which contain the ArrangeBy menu
*)
end if
log Volume_loc --> "Volume"
# It seems that there is no global control upon these tables so several keys may describe the same string.
set theKey to "Ukt-Pm-iTw.title"
set showLibrary_loc1 to localized string theKey from table "ViewOptionsWindow" in bundle FinderBundle
if showLibrary_loc1 = theKey then # The system run in English for which there is no table "ViewOptionsWindow"
set showLibrary_loc1 to "Show Library Folder"
end if
log showLibrary_loc1 -->"Afficher le dossier Bibliothèque"
set theKey to "noX-Qe-gkU.title"
set showLibrary_loc2 to localized string theKey from table "ViewOptionsWindow" in bundle FinderBundle
if showLibrary_loc2 = theKey then # The system run in English for which there is no table "ViewOptionsWindow"
set showLibrary_loc2 to "Show Library Folder"
end if
log showLibrary_loc2 -->"Afficher le dossier Bibliothèque"
set theKey to "sld-Oo-X54.title"
set showLibrary_loc3 to localized string theKey from table "ViewOptionsWindow" in bundle FinderBundle
if showLibrary_loc3 = theKey then # The system run in English for which there is no table "ViewOptionsWindow"
set showLibrary_loc3 to "Show Library Folder"
end if
log showLibrary_loc3 -->"Afficher le dossier Bibliothèque"
Happily, such annoying cases are rare.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 16 mai 2019 12:38:15
Just be aware that when you see a key in a form like “sld-Oo-X54.title”, it means it has been automatically generated by Xcode when the app’s code was compiled. This means it’s pretty much guaranteed to change in future.
Thanks Shane.
What you wrote may explain why several keys may be used to describe the same string.
As I am curious, I ran my sample script upon Finder 10.12.6 and - I am lucky - the “easy to remember keys” available in Finder 10.13.6 were already available in the old version.
In practice it’s not really important. I never had to use such keys. I use localized string when I have to write GUI scripting code where the name of UI elements are always localized.
The fact that some tables are unavailable in English.lprog is more annoying.
I’m wondering were are the English strings defined in such cases.
I’m really puzzled by the key “tCs-xJ-UEw.title” in the table ArrangeByMenu.strings.
Most of the time the local string means volume but sometimes it’s really different.
For instance, the danish key is Enhed which is supposed to mean Unit.
And of course I’m always unable to find where is this string really used.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 17 mai 2019 12:08:03
Hi. The script I use is below, which I use in Catalina. If you choose labels, they are applied. If you don’t choose a label, all current labels are removed. Not sure about your question, though. You want to not choose a label, but apply a specific label?
use AppleScript version "2.3.1"
use scripting additions
use framework "Foundation"
tell application "Finder"
set theItems to the selection
end tell
set tagList to choose from list {"Red", "Orange", "Yellow", "Green", "Blue", "Gray", "Purple"} with title "Tag Selected Items" with prompt "Choose colors:" OK button name "Apply" cancel button name "Cancel" with multiple selections allowed and empty selection allowed
repeat with thisItem in theItems
set theFile to POSIX path of (thisItem as alias)
(its setTags:tagList forPath:theFile)
end repeat
on returnTagsFor:posixPath -- get the tags
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags = missing value then return {} -- because when there are none, it returns missing value
return theTags as list
end returnTagsFor:
on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
on addTags:tagList forPath:posixPath -- add to existing tags
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
-- get existing tags
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags ≠ missing value then -- add new tags
set tagList to (theTags as list) & tagList
set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
end if
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:
If I understand correctly, you want to select a file (or files) and apply a fixed-text tag to it. A quick and dirty approach is to remove or comment out the “set tagList to…” line near the beginning and replace it with a line to just set the tag to whatever you want. For example:
--set tagList to choose from list {"Red", "Orange", "Yellow", "Green", "Blue", "Gray", "Purple"} with title "Tag Selected Items" with prompt "Choose colors:" OK button name "Apply" cancel button name "Cancel" with multiple selections allowed and empty selection allowed
set tagList to {"Red"}
-- or, to remove a tag:
--set tagList to {""}
Using Shane’s code above, I am able to REMOVE a custom tag (one that is created by the user, such as “Photo”, and not just the system label names like “Green”), but I can not CREATE a custom label on a file, I am only able to add a color name from the old Finder labels to a file. Does anyone know if there is a work around to this?
It’s generally a good idea to provide an example of the code that’s failing.
This works for me – but I’m still on Mojave.
-Chris
--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2023/01/06 18:23
# dMod: 2023/01/06 18:23
# Appl: Finder
# Task: Add a Custom Tag to the Item Selected in the Finder.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Finder, @Add, @Custom, @Tag
--------------------------------------------------------
use AppleScript version "2.4" --» Yosemite or later
use framework "Foundation"
use scripting additions
--------------------------------------------------------
tell application "Finder" to set finderSelectionList to selection as alias list
if length of finderSelectionList = 0 then error "No files were selected in the Finder!"
set posixPath to POSIX path of item 1 of finderSelectionList
set tagList to {"NutterButterBar"}
its addTags:tagList forPath:posixPath
--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on addTags:tagList forPath:posixPath -- add to existing tags
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
-- get existing tags
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags ≠ missing value then -- add new tags
set tagList to (theTags as list) & tagList
set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
end if
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:
--------------------------------------------------------
Your example is 1 of 3 handlers in Shane’s code from above. I am finding that it is the following handler that is not working for some reason, but it is not completely obvious to me why this one is broken.
on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
You’re still not showing your script that’s failing – therefore we cannot examine it for problems…
This works for me on Mojave.
--------------------------------------------------------
use AppleScript version "2.4" --» Yosemite or later
use framework "Foundation"
use scripting additions
--------------------------------------------------------
tell application "Finder" to set finderSelectionList to selection as alias list
if length of finderSelectionList = 0 then error "No files were selected in the Finder!"
set posixPath to POSIX path of item 1 of finderSelectionList
set tagList to {"Nonsense"}
its setTags:tagList forPath:posixPath
--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on setTags:tagList forPath:posixPath -- set the tags, replacing any existing
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
--------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
set theTag to "Art"
tell application "Finder"
set theFiles to selection
end tell
repeat with f from 1 to (count theFiles)
set theItem to item f of theFiles as alias
set theFile to POSIX path of theItem
set theTags to (its returnTagsFor:theFile)
if theTags does not contain theTag then
set newTags to theTag
repeat with i from 1 to (count theTags)
set oldTag to item i of theTags
set end of newTags to oldTag
end repeat
(its setTags:newTags forPath:theFile)
else
set newTags to {}
repeat with i from 1 to (count theTags)
set oldTag to item i of theTags
if oldTag does not contain "Art" then
set end of newTags to oldTag
end if
end repeat
(its setTags:newTags forPath:theFile)
end if
end repeat
on returnTagsFor:theFile -- get the tags
set aURL to current application's |NSURL|'s fileURLWithPath:theFile -- make URL
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags = missing value then return {} -- because when there are none, it returns missing value
return theTags as list
end returnTagsFor:
on setTags:newTags forPath:theFile -- set the tags, replacing any existing
set aURL to current application's |NSURL|'s fileURLWithPath:theFile -- make URL
aURL's setResourceValue:newTags forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
Okay… It looks to me like you’re trying to toggle whether the given tag exists in the selected item(s) in the Finder.
It’s a good idea to provide some explanatory text to posted scripts, so people don’t have to spend time figuring out what you’re doing. You’ll get more accurate and quicker help that way.
You’re trying to use Finder-References outside the Finder.
In your first IF it looks like you’re trying to concatenate a string instead of add to a list.
Here’s how I’d go about your task:
--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2023/01/09 06:04
# dMod: 2023/01/09 06:04
# Appl: Finder
# Task:
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Finder
--------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
--------------------------------------------------------
set tagToProcess to "Art"
# Without ‘as alias list’ you get Finder-References which don't work outside the Finder.
tell application "Finder"
set finderSelectionList to selection as alias list
end tell
repeat with theItem in finderSelectionList -- No need for a counter.
set itemPath to POSIX path of theItem
set tagList to (its returnTagsFor:itemPath)
if tagList contains tagToProcess then
set tagList to (its removeListItem:tagToProcess fromList:tagList)
(its setTags:tagList forPath:itemPath) -- Change the list of tags
else if tagList does not contain tagToProcess then
(its addTags:{tagToProcess} forPath:itemPath)
end if
end repeat
--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on addTags:tagList forPath:posixPath -- add to existing tags
set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
-- get existing tags
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags ≠ missing value then -- add new tags
set tagList to (theTags as list) & tagList
set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
end if
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forPath:
--------------------------------------------------------
on removeListItem:listItemName fromList:theList
set theList to current application's NSMutableArray's arrayWithArray:theList
theList's removeObject:listItemName
return theList as list
end removeListItem:fromList:
--------------------------------------------------------
on returnTagsFor:itemPath -- Get the tags
set aURL to current application's |NSURL|'s fileURLWithPath:itemPath -- make URL
set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
if theTags = missing value then return {} -- because when there are none, it returns missing value
return theTags as list
end returnTagsFor:
--------------------------------------------------------
on setTags:newTags forPath:itemPath -- Set the tags, replacing any existing
set aURL to current application's |NSURL|'s fileURLWithPath:itemPath -- make URL
aURL's setResourceValue:newTags forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
--------------------------------------------------------
Note that if you’re serious about learning AppleScript and not using Script Debugger you’re missing a bet.
Being able to step through scripts and visualize what they’re doing is a game changer.
That works. Thank you very much Chris. It was more complicated (with the ASOBJC Handlers) than I had hopped with just edited some of Shane’s original script!