1

I am doing a languages page for my website, placing all texts in variables such as:

if($language=='en') {
    lang[1]="Welcome, ".$user."!";
    lang[2]="You have earned ".$pts." pts yesterday";
}
elseif($language=='fr') {
    lang[1]="Bienvenue, ".$user."!";
    lang[2]="Vous avez remporté ".$pts." pts hier";
}

I include this at the top of each page. However, the problem is that in many pages, some of the variables inside the $lang[X] variables (such as $user or $pts for instance) are only declared a few lines before their echo line or they even change a couple of times within a same page, so when the language vars are loaded via an include, they take the value of $user or $pts at that moment and not at the moment of their echo.

Is there a way to use the technique in such a way that the vars inside the $lang[X] are taken at the moment of their echo and not at the moment of their include()?

2
  • 3
    You should stop writing code that would perform program logic and echoing output in the same php file. MVC would [definitely] probably solve your problem Commented Jul 3, 2011 at 17:21
  • 2
    By the way, you have only one equal sign in your IF. Commented Jul 3, 2011 at 17:22

5 Answers 5

3

Dont use variable names use tokens and translate the strings:

function _t($index, $language, $vars = array()){
   if($language=='en') {
    lang[1]="Welcome, %user%!";
    lang[2]="You have earned %pts% pts yesterday";
   }
   elseif($language=='fr') {
    lang[1]="Bienvenue, %user%!";
    lang[2]="Vous avez remporté %pts% pts hier";
  }

  return strtr($lang[$index], $vars);
}


echo _t(1, 'en', array('%user%' => 'John D.'));

However i wouldnt just make something like this from scratch i would use something that supports traditional i18n/l10n methods, like gettext or Zend_Translate (which uses gettext but supports multiple data formats). There is standardization out there for doing this. And if you stick to one of the excepted standards of data formats for the translations and methodology for converting you will be better off in a number of ways. Not to mention it will be less work :-)

Sign up to request clarification or add additional context in comments.

6 Comments

Line #1 is missing a closing parenthesis.
@prodigitalson what is the advantage of using tokens instead of sprintf as others have mentionned? With your method, PHP has to scan the function each time (which I believe will slow performance when compared to loading all variables at once and calling them with sprintf)?
@prodigitalson could you fix the spelling and punctuation in your answer please?
@adam: you would put the function in some kind of global include, for example in the same php file where you have your translations. then you can just use include_once. in any event you should set it up so it doesnt need to include the translations more than once.
@adam: the real advantage is in using strtr instead of sprintf. It lets you passing an arbitrary number of replacements and replaces them using token strings instead iof indexes of occurence: ie you only need to know that token names, not in what order they appear, or how many times they appear. If you want to jsut use strtr in your view thats fine, but i prefer encapsulation inside a function if not a class. that way i can centralize everything.
|
2

Not possible easily. The common workaround is to use %s placeholders in the translated strings:

elseif ($language=='fr') {
   $lang[1]="Bienvenue, %s!";

And later fill them up with sprintf:

echo sprintf($lang[1], $user);

That being said, you should really consider a gettext scheme, not an numerically-indexed $lang[] array and include scripts. (This can easily become difficult to maintain...)

Comments

1

You could look into sprintf. Instead of using "Welcome, ".$user."!" you could use "Welcome, %s!".

Comments

1

Maybe you could use sprintf instead of echo and just use placeholder instead of real values:

like this:

if($language='en') {
    lang[1]="Welcome, %s!";
    lang[2]="You have earned %d pts yesterday";
}
elseif($language='fr') {
    lang[1]="Bienvenue, %s!";
    lang[2]="Vous avez remporté %d pts hier";
}

and than you can do

sprintf (lang[1], $user);

Comments

0

I'l also use a switch to increase readability a litle and let it fall back to a default language:

switch($language) {
    case 'fr':
         lang[1]="Bienvenue, %s!";
         lang[2]="Vous avez remporté %s pts hier";
         break;
    case 'en':
    default:
         lang[1]="Welcome, %s!";
         lang[2]="You have earned %s pts yesterday";
}
echo sprintf($lang[1], $user);

Some new stuff in php 5.3 about this: http://devzone.zend.com/article/4799

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.