Using format string parameter replacement with LanguageHandler

Continuing the discussion from Case sensitivity and LanguageHandler:

Oh, you wish to do sub-string parameter replacement.

Yes this CAN be done. But, during the creation of the strings file, you (or the translation person,)
must take into account where (order-wise) the particular language puts certain kinds of words, or terms.

In Spanish, for example, the adjectives follow the object they are modifying, instead of preceding them.

Anyway, you use format string replacement parameters.

Example of a sub-string replacement, using the String#%() instance method.
(* NOTE: I personally always stick the arguments to this method in a literal array, even though it allows a single lone argument. I just have had to modify code so many times when I forget to stick multiple arguments in an array, that I just decided to always do it.):

prompt = LanguageHandlerobject["some string %s some more string "] % [string_reference]

So in each .strings file for the key given, there must be an embedded "%s" replacement parameter, in the proper position, with regard to all the other words, for each particular locale language.

But this is not a good example, because the whole point of LanguageHandler is to replace strings for English with a locale language string. And this will be done when you create the .strings files (or hashes) anyway.

A better example would be to insert a numeric value into the correct place in the translated string:

locale_text = LanguageHandlerobject["You selected %d model entities."] % [integer_reference]
Sketchup::set_status_text( locale_text, SB_PROMPT )

which would be similar to using the global format() method:

format_template = LanguageHandlerobject["You selected %d model entities."]
locale_text = format( format_template, integer_reference )
Sketchup::set_status_text( locale_text, SB_PROMPT )

At the bottom of the documentation block for Kernel#format() it says:

For more complex formatting, Ruby supports a reference by name.
%<name> style uses format style, but %{name} style doesn’t.

These features can be used with SketchUp, but it means you must decide what the hash key names will be once, and likely never change them.

Say that the word “SketchUp” will be the same in ALL language .strings files, but may appear in differing positions (depending upon language.) Say that you wish to save some space in all the files. You could decide upon a hash key named :SKU and the replacement parameter for it would appear in each translated string, as “%{SKU}”.

But there is a limitation that a hash must be the only argument. You cannot mix it with an array or list of “unnamed” arguments. This means for the numeric replacement parameter, you’d need to make it a
%<name>” style instead of an unnamed style. So the unnamed “%d” style in the previous example’s format string, needs to get a “<name>” inserted after the “%” sign,… so I’ll use “%<num>d” as the named style within the format string:

format_template = LanguageHandlerobject[
  "You have successfully imported %<num>d model entities into %{SKU}."
# Now use the format:
locale_text = format( format_template, :num => 376, :SKU => "SketchUp" )
UI::messagebox( locale_text, MB_OK )

FYI, Ruby will collect key/value pairs into a literal hash for you, so you do not need to actual do:

locale_text = format( format_template, { :num => 376, :SKU => "SketchUp" } )

(But it also will not hurt.) In addition later Ruby versions (ie, SketchUp v14+ with Ruby 2.0+) allow “named method arguments” which are converted into the argument hash, as above. You no longer need the “=>” operator, and the colon immediately follows the name (instead of preceding it.)

locale_text = format( format_template, num: 376, SKU: "SketchUp" )

So reference list for Ruby replacement parameters in strings:

Wow! That’s great. I will need to experiment with a these new to me string formatting possibilities but they will be very useful. Thank you for all the help, Dan.

1 Like

Very interesting indeed.
Now what if we have more than one replacement to do in a single string. Like - LanguageHandlerobject[“some string #{variable} some more string #{variable} some more string.”]

(1) That was not my quote. That was the quote of the original poster.

(2) Please read the lesson entirely. I showed using multiple replacement parameters in one format template, and explained clearly (I thought) how to do it, using either %<> and %{} parameters.

But I see that the second parameter %{SKU} was beyond the scroll margin, so I edited the code example so you do not need to scroll to the right, in order to see the second replacement parameter.