Localizing using printf and ternary operator

Hello all,

I'm having trouble to make this work using this example. I'm trying to locale the template I'm working on to support various language.
At 1 point the only way to support Asian language i.e Korean, Japanese is using the format below:

Published %1$s %2$s %3$s.

%1$s : if ($count_users > 1) ('by %s','domain') not ''
%2$s : if function_exists('time_since') ('%s ago','domain) not get_the_time(__('F jS, Y','domain')),
%3$s : ('in %s','domain') if function_exists('the_nice_category') the_nice_category(', ') not get_the_category_list(', ')


This is my current 'not working' codes. I was hoping to follow the format above which I fail to do so.
Is there any way to include string format (%s) in argument?

$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf( __('Published %1$s %2$s %3$s.','domain'),

($count_users > 1) ? __('by','domain') . ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>' : (''),            

function_exists('time_since') ? time_since(abs(strtotime($post->post_date_gmt . " GMT"))) . __(' ago','domain') : get_the_time(__('F jS, Y','domain')),

function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')

);

Thank you in advance.
daniazAsked:
Who is Participating?
 
Richard QuadlingSenior Software DeveloperCommented:
<?php
$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf
      (
      __('Published %1$s %2$s %3$s.','domain'), // Initial format for Published

      // This is to generate the first parameter.
      (
            ($count_users > 1)
                  ?
                        printf
                              (
                              __('by %s','domain'),
                              ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>'
                              )
                  :
                        ('')
      ),
      
      // This is for the second parameter
      (
            function_exists('time_since')
                  ?
                        printf
                              (
                              __('%s ago','domain'),
                              time_since(abs(strtotime($post->post_date_gmt . " GMT")))
                              )
                  :
                        get_the_time(__('F jS, Y','domain'))
      ),
      
      // This is for the third parameter
      (
      printf
            (
            __('in %s','domain'),
            function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')
            )
      )
      
      // End of main printf statement
      );
?>
0
 
Richard QuadlingSenior Software DeveloperCommented:
Traditional if/then/else

if ($one == 1)
 {
 echo "$one equals 1";
 }
else
 {
 echo "$one does not equal 1";
 }

if $one is 1 then then output will be

1 equals 1

If $one is 2 then the output will be

2 does not equal 1

This can also be expressed as ...

echo ($one == 1) ? "$one equals 1" : "$one does not equal 1";

The output is the same.

Something to watch out for.

Personally, I always put () around ternary code. Just to make it clear.

echo (($one == 1) ? "$one equals 1" : "$one does not equal 1");



So how does this help you. I'm not too sure what your code is trying to do.


printf("Published %1\$s %2\$s %3\$s.", ...);

I think you need to put a \ in to use argument swapping in the printf functions.
0
 
daniazAuthor Commented:
Hi,

There's no need for \

My above code actually already working (but not what I'm hoping for) and the real output is:
Published by Authorname April 5th, 2006 in Categoryname.
from
printf( __('Published %1$s %2$s %3$s.','domain'),

I've already done the traditional ifelse but it is possible to support various language when it comes to localize that sentence.

before:
if (function_exists('time_since')) {
printf(__('%s ago.','domain'), time_since(abs(strtotime($post->post_date_gmt . " GMT")), time()));
} else {
the_time(__('F jS, Y.','k2_domain'));
}
 
after:
function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')

My intention was to use string(%s) inside argument (refer to my first post):
function_exists('the_nice_category') ? ('%s ago','domain'), the_nice_category(', ') : get_the_category_list(', ')

I think this is hard to understand, before this I have no problem using the traditional way of ifelse but someone using Asian language bumps in and told me it's possible to locale that sentence and gave me that format example (refer to my first post).

Thanks
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
daniazAuthor Commented:
Just notice wrong example above cannot edit :(

before:
if (function_exists('time_since')) {
printf(__('%s ago.','domain'), time_since(abs(strtotime($post->post_date_gmt . " GMT")), time()));
} else {
the_time(__('F jS, Y.','k2_domain'));
}
 
after:

function_exists('time_since') ? time_since(abs(strtotime($post->post_date_gmt . " GMT"))) . __(' ago','domain') : get_the_time(__('F jS, Y','domain')),
0
 
Richard QuadlingSenior Software DeveloperCommented:
I think I'm missing something. I don't understand the issue.

Can you supply a complete script?

The __ is confusing me. I'm not sure what they are doing? I've not seen this before except as the leading characters on __construct, __destruct, __call, __set, __get, etc.

Is the format string constant? Is it ALWAYS 'Published %1$s %2$s %3$s.' ?

If so, why do you need argument swapping? (I think the format is NOT static, but just confirming).





BTW. The \$s bit. The example is using in the manual (http://www.php.net/manual/en/function.sprintf.php) uses "" so $s needs to become \$s. Sorry about that! Doh!

I'll raise a doc bug on this.
0
 
daniazAuthor Commented:
Yeah it's a bit confusing to write this in words, my apology. This a WordPress theme I'm currently working on. The new code was suppose to support localization.

"The __ is confusing me."
That's a keyword (function name) use for translation. If u use poEdit you'll know. It can be _e or anything depends on how it is set.

This is the original code without locale:

<span class="chronodata">Published <?php /* If there is more than one author, show author's name */ $count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1"); if ($count_users > 1) { ?> by <?php the_author_posts_link(); } ?>
<?php /* If 'Dunstan's Time Since' plugin is installed use it; else use default. */ if (function_exists('time_since')) { echo time_since(abs(strtotime($post->post_date_gmt . " GMT")), time()); gt; ?> ago<?php } else { the_time('F jS, Y') ?><?php } ?>
in <?php /* If 'Nice Categories' plugin is installed, use it; if not, use default */ if (function_exists('the_nice_category')) { the_nice_category(', '); } else { the_category(', '); }?></span>

So basically the standard output would be (depends on activated plugin):
Published by Authorname April 5th, 2006 in Categoryname.

Previously I use printf with elseif combination, it support most of the translation language out there but then come this Korean guy about the problem if I break it into phrases. He suggest the printf( __('Published %1$s %2$s %3$s.','domain'), .

An example how I use this in the template (working code):
<p><?php printf(__('You are currently browsing the %1$s weblog archives for the year %2$s.','k2_domain'), '<a href="'.get_settings('siteurl').'">'.get_bloginfo('name').'</a>', get_the_time('Y')) ?></p>
                  
This is the code when I use the traditional ifelse.

<span class="chronodata">
<?php /* If there is more than one author, show author's name */ $count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1"); if ($count_users > 1) {

      printf(__('Published by %s','domain'), '<a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>');
      } else {
      echo __('Published ','domain');
      }
?>

<?php /* If 'Dunstan's Time Since' plugin is installed use it; else use default. */
if (function_exists('time_since')) {
      printf(__('%s ago','domain'), time_since(abs(strtotime($post->post_date_gmt . " GMT")), time()));
      } else {
      the_time(__('F jS, Y','domain'));
      }
?>
                   
<?php /* If 'Nice Categories' plugin is installed, use it; if not, use default */
if (function_exists('the_nice_category')) {

      $category = the_nice_category(', ');
      } else {
      $category = get_the_category_list(', '); }

      printf(__('in %s.','domain'), $category );

?>

</span>


Take note that I'm a PHP newbie. I hope that I learn from this experience :)

Thanks.
0
 
Richard QuadlingSenior Software DeveloperCommented:
The __ function name is NOT a PHP function. So it must be a user defined function. Having said that the code looks like it should work.

The __ function is the issue. I am not sure how this works.

That happens if you ...

echo __('You are currently browsing the %1$s weblog archives for the year %2$s.','k2_domain');

This SHOULD output a printf format string. You will need to make sure that whatever includes you have are working as __ is not a PHP function.

If you can, I would STRONGLY recommend using a proper name for the function simply to remove the ambiguity.

Another issue is that you are swapping in and out of PHP. You are sometimes doing this inside an if statement. Makes if VERY difficult to read.

A much better way is to build the string to send to the browser bit at a time and then output the whole lot in 1 go.

e.g.
<?php
// Your includes...

$s_output = ''; // Empty output.

...

$s_output .= "Some output\n";
...
$s_output .= "Some more output\n";
...

echo $s_output; // Send the output to the client.
?>

You can then add debug echo statements and these will occur BEFORE the actual output.
0
 
daniazAuthor Commented:
Well the __ is definately user defined and also if i'm not mistaken global WordPress define (for localization)

This the project that I'm working on with 2 other.

The entire file is at getk2.com/svn/theloop.php

thanks :)
0
 
Richard QuadlingSenior Software DeveloperCommented:
The code looks fine. I cannot see where you are using ...

test ? True : False;

anywhere in this code. This is what the PHP Manual says on the Ternary Operator ...

----------------------------------------------------------
Ternary Operator
Another conditional operator is the "?:" (or ternary) operator.

Example 6.3. Assigning a default value
copy to clipboard
<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// The above is identical to this if/else statement
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}

?>
The expression (expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to TRUE, and expr3 if expr1 evaluates to FALSE.

Note:
Please note that the ternary operator is a statement, and that it doesn't evaluate to a variable, but to the result of a statement. This is important to know if you want to return a variable by reference. The statement return $var == 42 ? $a : $b; in a return-by-reference function will therefore not work and a warning is issued in later PHP versions.
----------------------------------------------------------

Can you ...


// Prepare Loop
echo __('Archive for %s','k2_domain');


What is the output?

What is the output of the whole page anyway?

Can you then create the output you REALLY are exepecting and place this on the site also.

I suspect that the __ function is not working as expected.
0
 
Richard QuadlingSenior Software DeveloperCommented:
Right. The function __ is defined in wp-l10n.php. And it returns a string.

So this string needs to look like a printf format. That is what I need to know.

This will identify if the error is in the wp-l10n.php code, your code, or the translated string.
0
 
Richard QuadlingSenior Software DeveloperCommented:
By "translated string" I mean the "translated printf format".

0
 
daniazAuthor Commented:
I've revert the code few days ago since it's bringing me lot's of problem.
I've already posted the use of ternary code in my FIRST post here before I revert the code to original code.

The code:
$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf( __('Published %1$s %2$s %3$s.','domain'),

($count_users > 1) ? __('by','domain') . ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>' : (''),            

function_exists('time_since') ? time_since(abs(strtotime($post->post_date_gmt . " GMT"))) . __(' ago','domain') : get_the_time(__('F jS, Y','domain')),

function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')

);

The output is still the same from the previous examples.

There's nothing wrong with the current code and the previous code I've submitted here. The whole theloop.php is fine. You can view the overall working code in the root of the domain - getk2.com.

What's inside the <span class="chronodata">...</span> is what i want to change.
From the ternary code above is it possible to do something like this inside the code above:

('by %s','domain'), ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>'

You can test it yourself, grab a copy of WordPress and a copy of the entire template code in getk2.com/svn/ using any subversion client.

Oh and just imagine that __ is echo. There's nothing wrong with that fyi. It's a gettext stuff use for internalization and localization.
0
 
daniazAuthor Commented:
"echo __('Archive for %s','k2_domain');"

the output (depends on which statement it's in). It can be:
<?php printf( __('Archive for %s','k2_domain'), get_the_time( __('Y','k2_domain'))) ?>
Archive for 2006

Here's a bug ticket for that.
url: getk2.com/bugs/view.php?id=235



0
 
Richard QuadlingSenior Software DeveloperCommented:
No. I was expecting the output of

echo __('Archive for %s', 'k2_domain');

to be something like ...

Archive for %s

or whatever the translation should be.




0
 
daniazAuthor Commented:
Exactly,

if you only do something like:
echo __('Archive for %s', 'k2_domain');

it will return a plain "Archive for %s" (without " ") since there's not argument for the string(%s).
0
 
Richard QuadlingSenior Software DeveloperCommented:
Can you somehow incorporate this code and supply the output please.

What I am trying to determine is where does the problem lie. The code LOOKS valid. I can see no reason why ternary operators are not working. I suspect that there is another issue which is being missed.

Hopefully the following code will report all the values being worked upon. Each of the tests in the ternaries will be evaluated and reported as true/false. If the functions does exist, then the lines where they are called will fail (only my debug calls these functions unchecked).



error_reporting(E_ALL);
echo "Start of debug<br />\n";

// Build the database request.
$s_count_users_SQL = <<< END_SQL
SELECT
      COUNT(*) AS usercount
FROM
      {$wpdb->usermeta}
WHERE
      `meta_key` = '{$table_prefix}user_level' AND
      `meta_value` > 1
END_SQL;

// What is the request.
echo "$s_count_users_SQL<br />\n";

// Get the number of users.
$i_count_users = $wpdb->get_var($s_count_users_SQL);

// What is the db results
echo "Number of users is $i_count_users<br />\n";


// Output the various parts indivually.
echo '($i_count_users > 1) returns ' . (($i_count_users > 1) ? 'True' : 'False') . "<br />\n";
echo "If True then __('by','domain') . ' <a href=\"' . get_author_link(0, \$authordata->ID, \$authordata->user_nicename) .'\">' . get_the_author() . '</a>' returns " . __('by','domain') . ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>' . "<br />\n";

echo "function_exists('time_since') returns " . (function_exists('time_since') ? 'True' : 'False') . "<br />\n";
echo "If True then time_since(abs(strtotime(\$post->post_date_gmt . ' GMT'))) . __(' ago','domain') returns " . time_since(abs(strtotime($post->post_date_gmt . " GMT"))) . __(' ago','domain') . "<br />\n";
echo "If False then get_the_time(__('F jS, Y','domain')) returns " . get_the_time(__('F jS, Y','domain')) . "<br />\n";


echo "function_exists('the_nice_category') returns " . (function_exists('the_nice_category') ? 'True' : 'False') . "<br />\n";
echo "If True then the_nice_category(', ') returns " . the_nice_category(', ') . "<br />\n";
echo "If False then get_the_category_list(', ') returns " . get_the_category_list(', ') . "<br />\n";

// Output the combined results.
printf(
      __('Published %1$s %2$s %3$s.','domain'),
      (($i_count_users > 1)
            ?
            __('by','domain') . ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>'
            :
            ''),
      (function_exists('time_since')
            ?
            time_since(abs(strtotime($post->post_date_gmt . ' GMT'))) . __(' ago','domain')
            :
            get_the_time(__('F jS, Y','domain'))),
      (function_exists('the_nice_category')
            ?
            the_nice_category(', ')
            :
            get_the_category_list(', '))
      );
echo "End of debug<br />\n";
0
 
Richard QuadlingSenior Software DeveloperCommented:
>Comment from daniaz
>Date: 04/05/2006 01:16PM GMT
>
>Exactly,
>
>if you only do something like:
>echo __('Archive for %s', 'k2_domain');
>
>it will return a plain "Archive for %s" (without " ") since there's not argument for the string(%s).

Surely the k2_domain is acting as a translator? Making the text different in some way?

0
 
daniazAuthor Commented:
RQuadling, I think you misunderstood this whole situation. As I said before the code is working fine (every piece of code that I posted here). But it is not what I want (actually that korean guy want).

In order to please that korean guy, the formatted string should be:
Published %1$s %2$s %3$s.
where:
%1$s : if ($count_users > 1) ('by %s','domain') not ''
%2$s : if function_exists('time_since') ('%s ago','domain) not get_the_time(__('F jS, Y','domain')),
%3$s : ('in %s','domain') if function_exists('the_nice_category') the_nice_category(', ') not get_the_category_list(', ')

The real problem lies here:
by %s, %s ago, in %s

is there any way to use argument data inside argument data. Refer to my comment -> Date: 04/05/2006 05:54AM PDT

I'm thinking something like this (not working code):

$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf( __('Published %1$s %2$s %3$s.','domain'),

($count_users > 1) ? __('by %s','domain'), ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>' : (''),            

function_exists('time_since') ? __('%s ago','domain'), time_since(abs(strtotime($post->post_date_gmt . " GMT"))) .  : get_the_time(__('F jS, Y','domain')),

__('in %s','domain'), function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')

);

The problem is, u can't use something like this in there:
__('in %s','domain'), function_exists('the_nice_category') ?

If there's any way beside ternary operator or using ifelse.

Thanks for helping me on this mate :)

0
 
Richard QuadlingSenior Software DeveloperCommented:
The code is causing too much noise.

I can't work out what you are trying to get to.

Are you trying to build a sub-printf statement to supply as a parameter to the main printf?

Something like ...

<?php
$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf
      (
      __('Published %1$s %2$s %3$s.','domain'), // Initial format for Published

      // This is to generate the first parameter.
      (
            ($count_users > 1)
                  ?
                        printf
                              (
                              __('by %s','domain'),
                              ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>'
                              )
                  :
                        ('')
      ),
      
      // This is for the second parameter
      (
            function_exists('time_since')
                  ?
                        printf
                              (
                              __('%s ago','domain'),
                              time_since(abs(strtotime($post->post_date_gmt . " GMT")))
                              )
                  :
                        get_the_time(__('F jS, Y','domain'))
      ),
      
      // This is for the third parameter
      printf
            (
            __('in %s','domain'),
            function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')
            )
      );
?>

Hopefully the indenting will add to the code and explain the dependence between each line of code.
0
 
daniazAuthor Commented:
Thanks man. That would do the trick. *bow*

Sorry about the 'noise'. The original code was indent (like u did), in order to get the example I have to copy paste from SVN diff (which is compress).

This is an updated code from the above. Instead of using printf(), it should be using sprintf() to return the formatted string.

<?php
$count_users = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->usermeta WHERE `meta_key` = '" . $table_prefix . "user_level' AND `meta_value` > 1");

printf
     (
    __('Published %1$s %2$s %3$s.','domain'), // Initial format for Published

     // This is to generate the first parameter.
     (
          ($count_users > 1)
               ?
                    sprintf
                         (
                         __('by %s','domain'),
                         ' <a href="' . get_author_link(0, $authordata->ID, $authordata->user_nicename) .'">' . get_the_author() . '</a>'
                         )
               :
                    ('')
     ),
     
     // This is for the second parameter
     (
          function_exists('time_since')
               ?
                    sprintf
                         (
                         __('%s ago','domain'),
                         time_since(abs(strtotime($post->post_date_gmt . " GMT")))
                         )
               :
                    get_the_time(__('F jS, Y','domain'))
     ),
     
     // This is for the third parameter
     (
     sprintf
          (
          __('in %s','domain'),
          function_exists('the_nice_category') ? the_nice_category(', ') : get_the_category_list(', ')
          )
     )
     
     // End of main printf statement
     );
?>

Thanks a lot :)
0
 
Richard QuadlingSenior Software DeveloperCommented:
Yes. I forgot about sprintf.

Good luck with the project and thanks for the points.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.