Success

User tests: Successful: Unsuccessful:

avatar ghost
ghost
22 Mar 2013

Tracker item: http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=30370

This is - in my opinion - a really cool and exciting code change.

It makes it possible to add a comma separated list of language keys in the JText::_() method, and it will treat it as a sprintf string.

If your language file has this:

MY_STRING="I love %s and %s!"
FOO="apples"
BAR="pears"

And you do JText::_('MY_STRING,FOO,BAR');
Then the result will be:
I love apples and pears!

Why?

So why is this interesting? Why not use JText::sprintf()?

Well, a lot of strings ar automatically passed through the JText::_() method and you have no option to choose the JText::sprintf() method. The main example (as I can see it) is the strings in XML files.

So instead of this:

JFIELD_ACCESS_LABEL="Access"
JFIELD_CATEGORY_DESC="Category"
JFIELD_LANGUAGE_DESC="Language "
JFIELD_PUBLISHED_DESC="Status"
JOPTION_SELECT_ACCESS="- Select Access -"
JOPTION_SELECT_CATEGORY="- Select Category -"
JOPTION_SELECT_LANGUAGE="- Select Language -"
JOPTION_SELECT_PUBLISHED="- Select Status -"

with an xml like:

<field name="t1" type="text" label="JFIELD_ACCESS_LABEL" description="JOPTION_SELECT_ACCESS" />
<field name="t2" type="text" label="JFIELD_CATEGORY_DESC" description="JOPTION_SELECT_CATEGORY" />
<field name="t3" type="text" label="JFIELD_LANGUAGE_DESC" description="JOPTION_SELECT_LANGUAGE" />
<field name="t4" type="text" label="JOPTION_SELECT_PUBLISHED" description="JOPTION_SELECT_PUBLISHED" />

You can simply have:

JFIELD_ACCESS_LABEL="Access"
JFIELD_CATEGORY_DESC="Category"
JFIELD_LANGUAGE_DESC="Language "
JFIELD_PUBLISHED_DESC="Status"
JOPTION_SELECT="- Select %s -"

with an xml like:

<field name="t1" type="text" label="JFIELD_ACCESS_LABEL" description="JOPTION_SELECT,JFIELD_ACCESS_LABEL" />
<field name="t2" type="text" label="JFIELD_CATEGORY_DESC" description="JOPTION_SELECT,JFIELD_CATEGORY_DESC" />
<field name="t3" type="text" label="JFIELD_LANGUAGE_DESC" description="JOPTION_SELECT,JFIELD_LANGUAGE_DESC" />
<field name="t4" type="text" label="JOPTION_SELECT_PUBLISHED" description="JOPTION_SELECT,JOPTION_SELECT_PUBLISHED" />

PS: just using text fields as an example. The important thing here is the description (popup) of the options

As you can see, I don't need a separate language string for every single object type you can select.
This opens up great possibilities for devs too to be able to use (semi-)dynamic language strings in the XML files.

Other examples

Dynamic option names

Use it to number options (or any other form of dynamic option names) without needing loads of separate language sting where only the number (or type) differs.

<field name="myoption" type="list" default="2" label="Options">
    <option value="1">MY_OPTION,1</option>
    <option value="2">MY_OPTION,2</option>
    <option value="3">MY_OPTION,3</option>
    <option value="4">MY_OPTION,4</option>
    <option value="5">MY_OPTION,5</option>
</field>

All your language file needs is:

MY_OPTION="My option: %s"
Concatenate strings

You can push multiple strings and concatenate them (or whatever you want) by using:

description="%s %s %s,MY_STRING_ONE,MY_STRING_TWO,MY_STRING_THREE"

Or even:

description="<h2>%s</h2> %s <em>%s</em>,MY_STRING_ONE,MY_STRING_TWO,MY_STRING_THREE"

Note: You should only use this if you know that the order of the strings is not reliant on the language.
If it is, use a language string for the first part too.

Testing instructions

Use above examples and test it by pasting the fields into an extensions xml file and see the descriptions in the extensions settings.
To test the JOPTION_SELECT example, you will need to add that language string to your lang file too, of course. Easiest is to add it to the language override file.

Backward compatibility

The sprintf thing is triggered on stings that contain a comma and everything behind the comma is all uppercase.
So this should not affect any usage of the JText::_() method and xml values used.
All language keys do not contain comma's. So this should not get triggered on anything currently passed to the JText::_() method.

avatar nonumber nonumber - open - 22 Mar 2013
avatar nicksavov
nicksavov - comment - 23 Mar 2013

Thanks for coding this, Peter!

For anyone interested, here's the tracker item on JoomlaCode:
http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=30370

avatar jmcameron
jmcameron - comment - 23 Mar 2013

The only minor issue with using this approach instead of JText::sprintf() is that this approach enforces a particular left-to-right order. With sprintf(), the replacement codes can be moved as necessary for right-to-left languages.

avatar nonumber
nonumber - comment - 23 Mar 2013

@jmcameron Thanks, never thought of that. But how can you tell JText::sprintf to order them the other way round? This doesn't seem to be built in behavior for any of the JText methods.
Or do you mean you can do that via an if structure in your own code?

avatar nonumber
nonumber - comment - 23 Mar 2013

Yeah, but that is no different than using the method I built into the JText::_().

You can do:

<field ... label="STRING,ONE,TWO,THREE" />

With:

STRING="Counting down: %3$s, %2$s, %1$s"
ONE="1"
TWO="2"
THREE="3"

Result:
Counting down: 3, 2, 1

avatar jmcameron
jmcameron - comment - 23 Mar 2013

@nonumber To explain further, here a made-up example. Suppose you want to print a warning that an ID is wrong:

JText::sprintf('WRONG_ID', id);

The translation item in the .ini file might look like this in a LTR language (like English):

WRONG_ID="Wrong ID: %d"

But in a RTL language, it could be changed in the translation .ini file:

WRONG_ID="%d :ID Bad"

Where "ID Bad" would be in some other RTL languge.

Notice that the original JText::sprintf call would not change, but the message could be handled in a RTL or LTR manner by changing the position of the %d replacement item in the translation files.

However, if you use the new JText::_() approach, you cannot change the location of the ID in the output.

avatar jmcameron
jmcameron - comment - 23 Mar 2013

Sorry, I just reread the original proposal above and maybe it will be able to handle the RTL issues. It looks like the plan is to extend JText::_() to work identically to JText::sprintf() if it has extra arguments. If that is the case, then you can ignore my comments.

avatar nonumber
nonumber - comment - 23 Mar 2013

Yes, I'll ignore your replies :)

But please test the patch, so we can get this into core (hopefully into
3.1)...

avatar ot2sen
ot2sen - comment - 27 Mar 2013

Interesting suggestion Peter.

Do you have more in use examples? The XML example does give a good idea of the concept of the dynamic added though. But it also raises an eyebrow whether this could get close to behave as concatenating strings and bring on difficualty to those helping localising the strings.

Mixing strings and making them more dynamic, may be a fine extra option for the source language, but I have some concern it may end up becoming more difficult to localise the dynamic source if used for mixing more complex strings, and give some issues with languages using different terms/words/forms when in different context.

avatar nonumber
nonumber - comment - 27 Mar 2013

I don't see how that discussion is any more relevant to this than the ability to use JText::_sprintf() in an extensions PHP code.

avatar nonumber
nonumber - comment - 9 Apr 2013

PS: This also works and is pretty cool:

<field name="myoption" type="list" default="2" label="Options">
    <option value="1">MY_OPTION,1</option>
    <option value="2">MY_OPTION,2</option>
    <option value="3">MY_OPTION,3</option>
    <option value="4">MY_OPTION,4</option>
    <option value="5">MY_OPTION,5</option>
</field>

So you can have dynamic option names, without needing loads of separate language sting where only the number (or type) differs.
All your language file needs is:

MY_OPTION="My option: %s"
avatar nonumber
nonumber - comment - 15 Apr 2013

Just thought of another use:

You can push multiple strings and concatenate them (or whatever you want) by using:
description="%s %s %s,MY_STRING_ONE,MY_STRING_TWO,MY_STRING_THREE"
Or even:
description="<h2>%s</h2> %s <em>%s</em>,MY_STRING_ONE,MY_STRING_TWO,MY_STRING_THREE"

I committed a change to make this possible.

avatar nonumber
nonumber - comment - 15 Apr 2013

Added examples to description...

avatar mahagr
mahagr - comment - 17 Apr 2013

+1 for the last changes ;) I hate to have translations like the last example inside the language files.

avatar nonumber
nonumber - comment - 17 Apr 2013

Thanks, but please test it instead of +1-ing it.

avatar wilsonge
wilsonge - comment - 21 Apr 2013

OK just so I can cover the bases here as a certified idiot. I can definately see the usefulness BUT all your examples use the XML file. Would it not be easier to use JText::sprintf() on the XML file rather than JText? I would have thought that would involve less code as well!

avatar nonumber
nonumber - comment - 22 Apr 2013

No, that would involve a lot more code, as you would need to add pretty much the same checks/code I added to one file now, to all possible field type files.

Also, adding the sprintf ability to the main JText method opens up more possibilities than just for xml files. You can use this in any field/value that is passed through the JText method.

avatar nicksavov
nicksavov - comment - 25 Apr 2013

Hi Johnny,

Please test the implementation of the patch, as it cannot be added without good testing.

Cheers

avatar nonumber
nonumber - comment - 25 Apr 2013

@johnnydement The discussion about whether or not you think it is a good idea to use the sprintf functionality is useless here.
That is already possible inside php code. All that this PR does is extend that possibility to the XML files and other areas were you cannot directly call onto te sprintf metod.
So this (the splitting of strings into chunks) is noting new to Joomla.

Like Nick says: please test this PR to get it committed.

avatar cheesegrits
cheesegrits - comment - 1 May 2013

@nonumber - can you find me on Skype ('cheesegrits', Hugh Messenger, Huntsville, AL)? I'm trying to test this for you, having problems getting the patch applied. I really like this idea, and have immediate uses I could put it to with Fabrik (the extension I co-author).

avatar cheesegrits
cheesegrits - comment - 1 May 2013

Tested. Works. Posted test result on tracker.

Definite +1 for getting this adopted.

avatar mahagr
mahagr - comment - 9 May 2013

Also made a quick test on this and I already have a few places where I really could use this feature -- starting from manifest description as I want to display current version number in it without changing the translation.

avatar nonumber
nonumber - comment - 9 May 2013

@mahagr Thanks. Indeed, great example :)
Can you please test if it works ok and report back with a 'successful test' on the tracker?
http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=30370

avatar mahagr
mahagr - comment - 9 May 2013

I really hate using tracker... Done.

avatar mbabker
mbabker - comment - 9 May 2013

Don't we all...

On Thu, May 9, 2013 at 11:10 AM, Matias Griese notifications@github.comwrote:

I really hate using tracker... Done.


Reply to this email directly or view it on GitHub#880 (comment)
.

avatar nonumber
nonumber - comment - 9 May 2013

+1 on the hating of the tracker :P

avatar elkuku
elkuku - comment - 9 May 2013

... yes we do ;)

avatar cheesegrits
cheesegrits - comment - 9 May 2013

Well, maybe in a masochistic kind of way .... no, not even then.

On Thu, May 9, 2013 at 11:55 AM, Nikolai Plath notifications@github.comwrote:

... yes we do ;)


Reply to this email directly or view it on GitHub#880 (comment)
.

avatar nonumber
nonumber - comment - 20 May 2013

So does this have enough tests now to go forward?

avatar piotr-cz
piotr-cz - comment - 29 Aug 2013

Hi, can pls you add PR description to docs.joomla.org? I think most developers still use it as a reference

avatar tompap
tompap - comment - 29 Aug 2013

Hello, Just discover a major backward incompatiblity
If the text given to the JText::_ function is not a DEFINE but a classical text. This will returns a partial part of the text

Example: echo JText::_("THIS IS A TEXT,THIS PART WILL NOT BE RETURNED')
result: THIS IS A TEXT

So the test that is just checking if first part of the text contains only uppercase is not enough. You should check that: $firstpart != JText::_($firstpart) to be sure it's a language define)

avatar nonumber
nonumber - comment - 29 Aug 2013

You are not supposed to put stuff in the JText::_() if it is not a language string.
language strings are uppercase and have no spaces or comma's.
'THIS IS A TEXT,THIS PART WILL NOT BE RETURNED' is NOT a valid language string.

If your extension is doing that, then it is doing it wrong. Use language strings and ini files.

avatar tompap
tompap - comment - 29 Aug 2013

I think my example was not clearly understood
MY SUPER TEXT, WITH A COMMA is not a key in my example, is a simple text.(already in the correct language)
I don't want MY SUPER TEXT, WITH A COMMA to be replaced by another text
I want JText to return it without any modification as this text is not a key.

So maybe your next question is why are you given this sentence to JText if this is not a text to translate ? Need of JText is unecessary at all.

It's just because in the code I don't know if the value to pass to JText::_() will be a KEY or a Text because this is a user entry.
Let's take an example. You have a "object with a name" in your component.
Some users of your component are using only 1 language to then will put the final string in the field.
But now another user is using several languages and just one 1 object to be translated automatically depending on visitor's language. Then they enter a KEY in the field and then add the KEY translation in the language files.
So in the code a call to JText in done all cases. if the value is a KEY it's translated, if it's a text the text is simply returns.

This is no more possible with this code.

avatar cheesegrits
cheesegrits - comment - 29 Aug 2013

I don't see anything in the API docs that says you are ONLY supposed to use language INI keys. It might be implied in the examples, and is how most folk use it, but I don't see any specific restriction in the docs. I have several uses of JText::() where I'm not using FOOBAR style INI keys, but rather leveraging JText to allow admins to provide for translation of arbitrary, user supplied strings.

-- hugh

avatar tompap
tompap - comment - 29 Aug 2013

"You are not supposed to put stuff in the JText::_() if it is not a language string.
language strings are uppercase and have no spaces or comma's."

===> Just wondering why in this case, there is the following code in the new JText implementation
" if (strtoupper($test) === $test) "

This is not needed, if it's always language strings constants ?

Add a Comment

Login with GitHub to post a comment