You are not logged in.
Dear MacScripters,
I'm trying to take my Weather AppleScripts beyond English thanks to the help of some users of the software they work with WeatherCat. However, this requires being able to insert the value of a variable into the middle of a localized string. My German translator asks this way:
So what I need from you to build a correct German sentence is a placeholder for the variables you are using (in this case a placeholder for <variable time> and <variable temp>).
Something like:
/* German localized text for WC Temperature Falling */
"ISO_639-1Language_code"="en"; //DO NOT LOCALISE THIS!!!!
/* Growl notifications */
"Temperature has fallen below $vtemp;"="Die Temperatur ist unter $vtemp; gesunken";
"Outside temperature has fallen below the threshold of: $vtemp; at $vtime;"="Die Außentemperatur ist um $vtime; unter den Grenzwert von $vtemp; gesunken";
"at"="um";
"The current temperature is: $vtemp;"="Die momentane Temperatur ist: $vtemp;";
I've looked around and I don't see any way to create placeholders in this way using AppleScript. Have I not looked hard enough? Is this a feature that simply universal to the Mac development environment so I have been looking in the wrong place? Is this a deficiency in the AppleScript environment and it is simply impossible to create localized strings in this way?
Any pearls of wisdom on this matter would be greatly appreciated!! ![]()
Thanks in advance, Edouard ![]()
Offline
I doubt that placeholders in localized strings work in AppleScript.
In Cocoa placeholders are used in conjunction with the method stringWithFormat: of NSString,
which replaces the placeholder tokens (%@, %d, %f etc.) with the appropriate parameter values.
There is no equivalent in AppleScript, even in AppleScriptObjC stringWithFormat_() doesn't work with non-object parameters
Online
Thanks Stefan for the confirmation,
It is rather what I suspected, but only someone like you would know for sure.
Oh well, time to contemplate what are the possible "plan-B"s
Cheers, Edouard
Offline
You may create a resource containing :
begOfString1
endOfString1
begOfString2
endOfString2
begOfString3
endOfString3
In the script you may re-create the complete string with :
set theCompleteString to localized_begOfString1 & variableItem & localized_endOfString1
I do that in scripts building formulas for Numbers spreadsheets.
Yvan KOENIG (VALLAURIS, France) mercredi 28 mars 2012 15:52:55
Offline
Dear Yvan,
Thanks for the suggestion. I hadn't thought about trying to provide enough string segments so that translators would have multiple venues to insert appropriate text for their language. It clearly would be awkward, but perhaps it is workable so long as each sentence of phrase containing a variable is handled separately and the output paragraphs are assembled within the AppleScript itself.
The other possibility that occurred to me was to avail myself of the extensions within Satimage's Smile AppleScript extensions and implement a placeholder substitution within AppleScript using change extension. My hope was that would be reasonably efficient and cleaner. However, I haven't had any time to try to mock something one to see how this work.
So, we'll see!
Thanks again for your suggestion! ![]()
Cheers, Edouard
Offline
Placeholders can not be used, like Stefan said, but still, I think that concept is the best way. Write some simple text search and replace handler (there are probably 1000 suggestions for such handlers on this site). Variables in strings could be expressed like <<temperature>> or something similar. Thinking about text fragments for all possible grammar rules will drive you crazy.
First, you take the localized string, second, you replace the variable string.
Jürgen
Offline
Dear Jürgen and MacScripters,
juergen wrote:
Placeholders can not be used, like Stefan said, but still, I think that concept is the best way.
Yes I agree with you.
juergen wrote:
Write some simple text search and replace handler
I'm hoping to use an AppleScript extension that would be more efficient than doing it all in AppleScript, but even the text substitution could be handled complete in AppleScript.
I'm trying to clean up other things right now, but I'll try to mock this up soon and send it back to my German translator to see if it can be made practical and easy for translators to use.
Thanks again!! ![]()
Cheers, Edouard
Offline
Elegache,
printf is also an terminal command so I use it myself like when a user is asked to confirm a text like 'Are you sure you want to delete the 5 selected items?' where the number 5 is variable.
"teststring" = "A string with an integer %d and another %s";
Then in applescript I use a small handler to get the localized strings. Give up an empty array or use just the localized string command when there are no variables in the string.
Applescript:
localizedString("teststring", {10, "string value"})
on localizedString(stringKey, stringValues)
set command to "printf " & quoted form of (localized string stringKey)
repeat with p in stringValues
set command to command & space & quoted form of (contents of p as string)
end repeat
return do shell script command
end localizedString
EDIT:
The reason I use it with these placeholders is that localized string files can be easily used with Objective-C as well. You should keep that in mind if you want to translate the project slowly to Objective-C in the future and maybe Objective-C and AppleScript need the same string from the localized file.
Last edited by DJ Bazzie Wazzie (2012-03-29 04:54:16 am)
Offline
Dear DJ Bazzie Wazzie and MacScripters,
DJ Bazzie Wazzie wrote:
printf is also an terminal command so I use it . . . . .
Your point is well taken, but . . . as others have belly-ached . . sure hate to spawn a new process every time I need to translate a string. ![]()
DJ Bazzie Wazzie wrote:
The reason I use it with these placeholders is that localized string files can be easily used with Objective-C as well. You should keep that in mind if you want to translate the project slowly to Objective-C in the future and maybe Objective-C and AppleScript need the same string from the localized file.
I definitely agree on this one. Sure don't want to implement printf in AppleScript, but was hoping to find a way to allow my strings to be usable with the Xcode implementation of localized.strings. Hope to look into this soon.
Thanks for the tips! ![]()
Cheers, Edouard
Offline
Dear MacScripters,
As you all will soon discover - I'm a little slow then it comes to reading the documentation . . . ![]()
So imagine my surprise when I investigated the change verb that is supplied by the Satimage.osax . . . .
Just a little further down is:printf! ![]()
Works just as advertised and should be lightening fast compared using the UNIX command printf.
Is there some reason why folks don't avail themselves of these extensions? I realize that commercial developers can't easily ask their clients to install this. However I'm giving away my "toys" for free. Is there some other reason why AppleScript developers shy away from using these extensions that - I should be worrying about! ![]()
Thanks for all the help!! ![]()
Cheers, Edouard
Offline
elagache wrote:
Is there some reason why folks don't avail themselves of these extensions?
Two reasons, 1) every mac is installed with printf and not with satimage. 2) you don't show (normally) 100 - 1000s of localized strings within scripts – not even with applications – simultaneous, so performance of localized strings is never an issue for me. Since printf is older than do shell script command itself, I'm sure that every OS can run the command. I'm not so sure about satimage (the same addition version)
elagache wrote:
Is there some other reason why AppleScript developers shy away from using these extensions that - I should be worrying about!
This one I can only speak for my self but I never use scripting additions except for Mac OS X's default but also use those as less a possible as well.
1) They take away my 'freedom' on the mac through all systems.
2) When I want real performance I write an utility in C, C++, Objective-C or even combine all those languages.
3) Easier with version control when embedding a command line tool in the script bundle
4) Don't forget you're using a UNIX system so there is nothing wrong with using native features (like opening a shell)
5) Using shell commands makes your script much less OS or addition version depended
6) Support for third party scripting additions are unsure.
7) Using POSIX tools gives also a certain quality of your script.
I think I can name even more arguments why not using it.
Offline
Dear MacScripters,
Okay, so call me greedy, but I decided to try to write a single AppleScript handler that would be able to localize strings, then run printf. If the Satimage osax was installed, it would use that printf extension, otherwise it would create a UNIX command and do that. So I naively used a try-block and used the UNIX as the fall-back. However, I realized that this couldn't possibly work. If the Satimage osax wasn't installed - then there would be a compile-time, not run-time error.
*Gulp*, that's the trouble.
Because, even with this obvious impossibility - it works!?!? Here is my code as it appears on my Mac which has Satimage osax installed:
Applescript:
set convertedString to "Outside temperature has exceeded the threshold of: %d˚ at %s."
set variableList to {50, "2:19pm"}
localizeVarStrings(convertedString, variableList)
on localizeVarStrings(localString, variableList)
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- Routine to localize a string that includes printf formatting codes and then
-- substitute the values for the format codes.
-- uses Satimage osax when installed and UNIX printf command
-- as fall-back
--
-- Thanks to Adam Bell for nifty list to string concatenation.
-- http://macscripter.net/viewtopic.php?pid=53342#p53342
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
local convertedString, variableString, tdl, quotedVariableList, variableValueStr
-- First get translated string from localizable.strings file
set convertedString to (localized string localString)
try
-- try Satimage printf extension
set convertedString to printf convertedString parameters variableList
on error
-- Convert values for printf into shell-friendly form.
set quotedVariableList to {}
repeat with variableValue in variableList
set variableValueStr to contents of variableValue as string
set end of quotedVariableList to quoted form of variableValueStr
end repeat
-- Now make printf values into a single string
set {tdl, text item delimiters} to {text item delimiters, space}
set variableString to quotedVariableList as string
set text item delimiters to tdl
set convertedString to quoted form of convertedString
-- Finally let UNIX do the printf work.
set convertedString to do shell script ("printf " & convertedString & space & variableString)
end try
return (convertedString)
end localizeVarStrings
If I copy this script to a Mac that doesn't have Satimage osax installed, the line:
set convertedString to printf convertedString parameters variableList
looks instead like this:
set convertedString to «event SATIprtf» convertedString «class para» variableList
However, that doesn't generate a compile-time error. Now I recognize that these are raw Apple events and my understanding is that this should be reasonable. The «event SATIprtf» is unavailable on Macs without the Satimage osax installed, so the handler goes on to do the error code which uses the UNIX printf just as I want to.
However, . . . . this sure look a little weird to me. Am I doing something crazy here that only a AppleScript guru would properly understand? Can code like this be distributed without risking problems for "innocent users"?
Curious minds want to know!! ![]()
Cheers, Edouard ![]()
P.S. Here is a link to printf localized string test.scptd file complete with the localized string resources for folks to play with. According to the tests I've run, this file should work on any Mac, even if just cutting and pasting the code above will not work unless you have the Satimage osax installed.
Offline
set convertedString to «event SATIprtf» convertedString «class para» variableList
That doesn't look right -- I'd expect something more like:
Applescript:
set convertedString to «event SATIprtf» convertedString given «class para»:variableList
But the reason it won't give a compile error is because it can't find any dictionary to check those codes with, so it has no way of knowing whether it will work or not.
Offline
Dear Shane and MacScripters,
Oops,
you are correct:
Shane Stanley wrote:
set convertedString to «event SATIprtf» convertedString «class para» variableList
That doesn't look right -- I'd expect something more like:
Applescript:
set convertedString to «event SATIprtf» convertedString given «class para»:variableList
I typed in that line "by hand" since it was coming from another Mac and in my haste I forgot the given.
However, you left my key question unanswered. Can such code be used "safely" in general? It is certainly very kludgy,
but AppleScript is hardly the elegant scripting language that I suppose the originators at Apple first intended. At some point you've gotta compromise and make your scripts usable to the folks who want to use them!!
Cheers, Edouard
Offline
If you want to distribute your scripts I recommend to avoid third party Scripting Additions at all,
because they are required on any machine which uses the scripts and it's quite tricky to install them on-the-fly.
Furthermore I guess that many users (including myself) don't like to get components installed just for support of a single AppleScript
Solutions like DJ's in post #8 are preferable
Online
elagache wrote:
However, you left my key question unanswered. Can such code be used "safely" in general?
I don't see why not -- it compiles fine, and you trap the error. I can see where Stefan is coming from -- although I'm amazed at how AppleScript beggars are often such choosers -- but it seems to me that doing it as you propose covers that objection.
And unless I'm misunderstanding, your script by definition is designed to be used in app packages, so the option of adding a scripting addition is, at least technically, simple in this case.
Offline
Dear Stefan, Shane, and MacScripters,
StefanK wrote:
If you want to distribute your scripts I recommend to avoid third party Scripting Additions at all
I agree with Shane that your point is very appropriate in general. However, this isn't scripts intended for general distribution. They are instead incomplete tools provided for hobbyists who are expected be comfortable using the AppleScript Editor and dealing with surprises. These are folks with a weather station who are interested in going beyond what commercial software can do for them and are willing to learning something about scripting in order to gain those advantages.
Shane Stanley wrote:
I don't see why not -- it compiles fine, and you trap the error. I can see where Stefan is coming from -- although I'm amazed at how AppleScript beggars are often such choosers -- but it seems to me that doing it as you propose covers that objection.
I made a test script available to the community who would be using them and indeed no one has encountered any problems. Given this very limited objective, it doesn't seem like a bad idea. Anything I decide to make more polished will have to graduate from AppleScript to Objective-C. Then having the Localizable.strings already completed will be one less thing to do.
StefanK wrote:
Solutions like DJ's in post #8 are preferable
Thank you Stefan for reminding me of this post of DJ''s. When I looked at it, I realized that I had repeatedly modified test code until it had all the features I wanted - but in doing, it so had gotten very clumsy. D.J.'s solution is much more elegant and I've incorporated that instead into my handler. How easily we make the same mistake of reinventing the wheel! ![]()
Cheers, Edouard
Offline