views:

74

answers:

2

Hi

How could I improve the following organizational structure of my internationalization code? This is just a PoC, I'm using the php intl extension for translation in Intl::t():

index.php

 1  <?php
 2  //FILE translate.php, your "index.php"
 3  $messages = include 'messages.php';
 4  require_once 'intl.php';
 5  Intl::setSource($messages);
 6
 7  class Foo {
 8          public function throwGreeting($name) {
 9                  throw new Exception(Intl::t('Hello %(name)s',array('name' => $name)));
10          }
11  }
12  $foo = new Foo;
13  try {
14          $foo->throwGreeting('Anonymous');
15  }
16  catch(Exception $e) {
17          echo 'The greeting is ',$e->getMessage();
18  }

intl.php

 1  <?php
 2  //FILE intl.php
 3  class Intl {
 4          private static $messages;
 5
 6          /**
 7           * from php.net
 8           */
 9          public static function t($message,$args=array()) {
10                  if(array_key_exists($message,self::$messages)) {
11                          $message = self::$messages[$message];
12                  }
13                  else {
14                          //automatically queue message for translation
15                  }
16                  $keys    = array_keys($args);
17                  $keysmap = array_flip($keys);
18                  $values  = array_values($args);
19
20                  while (preg_match('/%\(([a-zA-Z0-9_ -]+)\)/', $message, $m))
21                  {
22                          if (!isset($keysmap[$m[1]]))
23                          {
24                                  throw new Exception(Intl::t("Missing argument '%(arg)s'",array('arg' => $m[1])));
25                                  
26                          }
27                          $message = str_replace($m[0], '%' . ($keysmap[$m[1]] + 1) . '$', $message);
28                  }
29                  array_unshift($values, $message);
30                  return call_user_func_array('sprintf', $values);
31          }
32          public static function setSource($src) {
33                  self::$messages = $src;
34          }
35  }

messages.php

 1  <?php
 2  //FILE messages.php
 3  return array(
 4          'Hello %(name)s' => 'Hallo %(name)s',
 5  );
A: 

I would do like this

have a folder called language. have the po files in it with the key value.

i will use key in the php code. there by based on the selection of the language, po file is loaded. see how wordpress does it.

coder
you mean wordpress, the state-of-the-art crappy-code? No, thank you :P
Flavius
i mentioned about the approach. it all depends on how you take it. you can write crappy code in any language.
coder
+1  A: 

Well you're testing the string against a hash every time you use it. That's not gonna run fast. But having three files is basically about right for modularisation.

Better to do something like:

/* At top of file or in eg "myintlstrings.php" */
class Intl { public static function t(&$cache,$message,$vals) {
  if ($cache==null) {
    // get translated version of $message into $cache
  } if (DOING_DEBUG) {
    // check parameters are in vals hash
  } array_unshift($vals,$cache); return call_user_func_array('sprintf',$vals);
} }


/* example 1 - function context */
static $cacheForGreeting; /* use static instead of global if in function */
throw new ExceptionIntl:t($cacheForGreeting,'Hello %(name)s'),
  array('name' => $name))));

/* example 2 - global context */
global $cacheForSomethingElse; /* use global instead of static if not in function */
echo(Intl::t($cacheForSomethingElse,"And today's sales figures are:"));
martinr
Thanks. I'll chew this a little.
Flavius