Of course you are right.
It seems that my eyes were wide closed.
After removing the two words « file » the script requires 20 seconds for the 10 000 pass ;-(
Don’t push it, handlers as these will never been called 10000 times. If so the whole approach is wrong, you should load the data once (to spare the file system) and store it as an property like this:
property LC_TIMES : missing value
--initialze
set LC_TIMES to loadLocales()
--start the script
set _weekday to word 1 of ((current date) as text)
set _from to getLocale("nl_NL")
set _to to getLocale("en_US")
repeat 12500 times
timeLocalString(_weekday, _from, _to)
end repeat
on timeLocalString(str, _from, _to)
repeat with x from 1 to count _from's localeItems
if item x of _from's localeItems = str then return item x of _to's localeItems
end repeat
return str
end timeLocalString
on getLocale(localeName)
repeat with timeLocale in my LC_TIMES
if name of timeLocale = localeName then return timeLocale --returns reference
end repeat
end getLocale
on loadLocales()
set localeNames to every paragraph of (do shell script "ls /usr/share/locale | grep -i '.utf-8$' | awk -F. '{print $1}'")
set localeTimes to {}
repeat with localeName in localeNames
set end of localeTimes to {name:contents of localeName, localeItems:my loadTimeLocale(localeName)}
end repeat
return localeTimes
end loadLocales
on loadTimeLocale(localeName)
return every paragraph of (do shell script "cat /usr/share/locale/" & localeName & ".UTF-8/LC_TIME")
end loadTimeLocale
All:
Simple question.
Big, and amazing, response!
Quite a bit of (to me) new stuff came up, which is much appreciated.
Then I remembered there’s an ‘official’ way of doing this: use a script bundle, and add a localisation file.
Script reads localised strings from there with ‘localized string’.
Nigel’s variant is pretty fast, but that LC_TIME file was ‘just a bit of luck’, and its existence allowed a quite specific solution for a single localisation problem.
At the same time it exemplifies another method for localisation.
So, as a general method for localisation, how would it compare with the official method?
What factors would you consider to judge the usability and “quality” of both methods?
Relative speed is an obvious candidate, when the difference is big enough.
Then again, it could just be a matter of preference.
I’d consider copying the files I need from /usr/share/locale, and from iPhoto in to that script bundle, and take it from there, with maybe a slightly reworked version of NIgel Garvey’s handler (so it copes with different localization files, and different naming schemes.)
weekday of (current date) as text
my localiseur("CalInfo" & result, result)
on localiseur(str, str2)
log {str, str2}
tell application "iPhoto" to set z to localized string str
if z is str then str2
end localiseur
What I meant with byte code version of AWK (MAWK) is not that AWK itself is written in byte code but the MAWK scripts/instructions are compiled to byte code and interpreted by the virtual machine (interpreter) inside MAWK. The difference is that code can be executed noticeable faster. remember when Java updated their interpreter to a byte code interpreter; suddenly Java wasn’t so slow anymore and became one of world’s most popular languages. Also LLVM is IMO on of world’s best byte code interpreters.
@ Yvan: I see nothing wrong by my approach, neither with yours, your user has paid for iPhoto.app, and so have you, and I. But at least up to Mountain Lion, a user may strip out locales, so theoretically, the user may lack the localization file you seek. As for the files in /usr/share/locale : if the user deletes files there, he is really left in his own peril But say it should come to it, very unlikely though, that the format or anything changes along the way (say you hard code the line numbers in order to save time, then I’d also copy them into the bundle. Just to be sure, if there are values there, that can’t be found in the localization files of iPhoto.
With my approach, the script will do its job only if iPhoto is installed.
With yours, you embed Apple files in your script allowing it to work on a machine whose user don’t own iPhoto.
As far as I know, we aren’t allowed to distribute Apple files. Are we ?
Some one which bought a machine delivered with iPhoto version 8.x is not supposed to be allowed to take benefit of resources delivered by iPhoto version 9.x. Is he ?
In my scheme, the script get the string localized in the language used by the operating system.
I have some difficulties to imagine that the user removed the resources matching this one.
Of course, if Apple edit the resources with new keystrings, the result will be wrong but I choose to remain in legality.
I use this scheme for years to grab datas from the Finder, iPhoto and iWork applications and don’t remember being forced to edit a script due to changed keystrings.
Using .strings files can be used for this, but it’s really designed for strings of your own devising – for example, the text of dialogs – than for standard stuff like weekday names. For date handling in Objective-C there are specific APIs.
In AppleScriptObjC it would be something like:
set theDate to current application's NSDate's |date|() -- like current date
set df to current application's NSDateFormatter's new() -- make a formatter
df's setDateFormat_("eeee") -- set its format
df's setLocale_(current application's NSLocale's alloc()'s initWithLocaleIdentifier_("FR")) -- set its locale
df's stringFromDate_(theDate) -- get the date as string
In practice you would probably use a format string that gives you the full date as you want, and use currentLocale.
But if you were to save your script as a Cocoa-AppleScript app, rather than a standard AS applet, the above would do what you want.
I think nobody thought about that, I have to admit that I didn’t. As an excuse, I have searched for ‘locale’ in the standard addition osax and no result.
I looked too! In System Events! But at that moment, I thought that the LC_ALL setting of the shell was how Mac OsX was configured as standard, so I didn’t look that closely!
Edit
But honestly, that command uses a looong time to complete, at least by me!
Edit
I’d rather use this:
set ulc to (do shell script "defaults read -g AppleLocale")
Though it doesn’t return the 100% correct form, which System Info does, the thing is, is that it is two dialects of my language, so System Info returns nb_NO, (the other would have been ny_NO), but AppleLocale has specified no_NO as a catchall.
It raises an interesting point, too. The shell-based solutions all rely on the contents of /usr/share/locale/, which on my Mac has 230 folders. This means considerably fewer than 100 locales. But theses are presumably unix locales, and not the actual locales used at higher levels of the OS, which are presumably part of the ICU library.
If I call NSLocale’s availableLocaleIdentifiers method, which, according to the docs, returns “An array of NSString objects, each of which identifies a locale available on the system”, I get 494 locales. I’m guessing that user locale uses the same list of locales, and could therefore return a locale for which no LC_TIME file exists.
That was very badly put of me, by vanilla AS, I don’t include do shell script stuff, what I should have written was, is there a way in vanilla as to do what the code below does.
And I have found it with System Info, but that is just unusable, as it seems that System Info is doing a full System Inspection, before it cares to reply to the request
The closest I have got to vanilla is
set ulc to (do shell script "defaults read -g AppleLocale")
I am actually looking for a more precise variable as we speak, and I heading into gestalts.
Edit The code above works perfectly fine now, and how did that happen?
I think I may have looked at the wrong results pane in Script Debugger the first time