Translate multiple languages in php - php

I am working on a small parser that should accept input in a number of languages. I am going to have maybe 50 strings that will serve as keywords/anchors in parsing the input. In PHP, what would be the best way to organize these translated keywords?
One possible solution that comes to my mind is to use an associative array. Like this:
$lang = array('us' => array('totalDebt' => 'Total Debt', 'color' => 'Color'),
'gb' => array('totalDebt' => 'Total Debt', 'color' => 'Colour'))
which I could then access using the following:
$langCode = 'en';
$debtPos = strpos($lang[$langCode]['totalDebt']);
Are there any better, proven methods for dealing with a bunch of short strings translated into a bunch of languages?

For a complete translation solution, you can look on a solution like gettext.
you solution is good enough (fast, cheap on resources) for small dictionaries.
I didn't understand what you tried to do using the strpos() function.
Don't forget to use some kind of fallback if the term you want to translate doesn't exists in the language, usually the fallback is to the English.

Generally people use l10n (or something similar) in their application because it allows for additional languages by adding a localization file which means the programmers do not have to change code. But if it is a simple script, then full on localization would be overkill.

I have seen your solution used in other OS projects, however the $lang array is usually constructed in different files. For example:
<?php // lang.us.php
$LANG['us'] = array(
'totalDebt' => 'Total Debt',
'color' => 'Color',
);
and so on for lang.gb.php, lang.de.php, etc.

As Peter said, you've got the right idea, but separate your languages into different files. It means that PHP won't have to store the array of every single word in every single language. Because you only are going to be loading one language at a time, you can skip the $lang['us'] level of nesting too.
You could even "extend" languages:
<?php // lang.en-gb.php
$lang = array(
'color' => "Colour",
'totalDebt' => "Total Debt",
...
);
?>
<?php // lang.en-us.php
include('lang.en-gb.php');
$lang['color'] = "Color";
// don't need to redefine "totalDebt"
?>
You might even consider creating a basic class which handles all this for you: detect the locale, choose the correct file, have "error" handling, if a term isn't defined in a particular language, etc.

You probably don't want 'totaldebt' => 'Total Debt' as that will ultimately obfuscate your code, and is slower than just storing 'Total Debt' as the hash key. The gettext way of doing things is to just wrap the strings in a function.
so rather than:
echo "Color";
You do:
echo t("Color");
the t() function will look at the globally defined language, and make the substitution if possible. At some point, you may want to use gettext and doing it this way will be compatible.

Related

Using eval on mysql data, is my code vulnerable, if so what is a better alternative

I am using the information_schema.columns table to grab some information.
I just want to know if this is a bad idea and whether there is a better alternative.
if($column['DATA_TYPE'] === 'enem'){
$options = eval(str_replace('enem(', 'array(', $column['COLUMN_TYPE']));
}
I chose to use eval and a single str_replace as i thought it was the fastest method of creating the array.
Here is an example of what $column could look like
$column = array(
['COLUMN_NAME'] => 'status',
['COLUMN_TYPE'] => "enum('failed','success','pending','other')",
['DATA_TYPE'] => 'enum',
);
I think your second solution is much more clear and the difference in speed and memory performances will be minor. (You could also use RegExp)
Here is a link which can help you:
How can I get enum possible values in a MySQL database?
Here is one not eval alternative, probably not as quick as the eval but still fast
if($column['DATA_TYPE'] === 'enem'){
$enums = str_replace(array('enum(', ')'), '', $column['COLUMN_TYPE']);
$options = explode(',', $enums);
}
More checks might need to be done but it works for
enum('failed','success','pending','other')
The only real reason not to use eval() in this case is because you want your code to run on for example HHVM by Facebook, which does not support eval afaik. I see no security problems in your particular case, however.
However, if you simply change your code slightly, you could use json_decode:
$options = json_decode('['.substr($column['COLUMN_TYPE'], 5, -1).']);
It's hard to tell which is faster without doing a small benchmark. I suspect this is faster, because str_replace has to search the entire string.

PHP ↔ JavaScript communication : constants VS strings

I am developping a web-application which makes a heavy use of AJAX. The server often answer by an array in order to concatenate different parts of the response.
I wonder what is the best solution to handle the keys in those arrays among the following two (the JSON encoding and decoding aren't shown):
Strings
This solution is easy to read, especially in JavaScript, but is really brittle and hard to maintain.
PHP :
<?php
return array(
'key_name_1' => 'foo',
'key_name_2' => 'bar'
);
?>
JavaScript :
var result = ajax(...);
alert(result.key_name_1);
Constants
This is a solid solution, which allow for short and numeric keys, but it's heavy and hard to read (use Reflection to automatize the generation of JavaScript constants is not an acceptable solution in my case, and doesn't solve all the drawbacks anyway).
PHP :
<?php
class Answer
{
const CONSTANT_1 = 1;
const CONSTANT_2 = 2;
}
return array(
Answer::CONSTANT_1 => 'foo',
Answer::CONSTANT_2 => 'bar'
);
?>
JavaScript :
Answer.CONSTANT_1 = <?php echo Answer::CONSTANT_1; ?>
Answer.CONSTANT_2 = <?php echo Answer::CONSTANT_2; ?>
var result = ajax(...);
alert(result[Answer.CONSTANT_1]);
According to you, what is the best choice?
I think the string solution is brittle, since any change in key name
must also be perform in the code which use them.
This conclusion is incorrect and will lead to unmaintainable code.
Consider the following PHP data structures:
array(
MyClass::FIELD1 => "my field1 value",
MyClass::FIELD2 => "my field2",
MyClass::FIELD3 => "field 3 is awesome",
);
class MyClass {
const FIELD1 = "field1";
const FIELD2 = "field2";
const FIELD3 = "field3";
}
Assume that we want to use a new field in place of field1 (as in the suggested use case) - we'll call it newfield:
class MyClass {
const FIELD1 = "newfield";
....
}
Now the code is in an inconsistent state. The name of the variable no longer has any correlation to it's value. The FIELD1 constant is essentially lying about the field it represents.
Imagine a new programmer examining this code a year later. She knows newfield exists and wants to access it. But instead of simply typing in result.newfield she has to enter result[Answer.FIELD1]. And every time she wants to access newfield she has the mental overhead of remembering and applying this mapping. But this is a large application with hundreds of fields and most are misdirected in this way. This is brittle and unmaintainable code.
Constants should only be used for values that are constant in nature. The canonical example being storing mathematical constants like pi:
class MyMathClass {
const PI = 3.141592;
}
Constants are one of the worst programming tools available for maintaining a volatile data structure (field names changing on a regular basis).
Once you echo it out JavaScript it will not really be a constant anyway. I would personally use strings if it's going to make your code more readable down the line. Why would this make it brittle and hard to maintain? You could always define a constant string if you need it to be both constant and readable. It's hard to tell without more information if you will be better-served with numbers or words as your keys.

inline JSON syntax in PHP

PHP would be a lot cooler if you could write things like this:
$array = [2, 3, 5];
$object = { "name" : "Harry", "age" : 23, "cats" : ["fluffy", "mittens", "whiskers"]};
but, I just spent a lot of time looking for an extension (even an experimental alpha or anything) adding json syntax to PHP but found nothing.
Does anything like this exist?
If not, considering the existence of json_decode() and facebook's XHP, would it be difficult to write an extension to do this?
I have no experience writing PHP extensions, although I did a lot of C in college.
You could just wrap your datastructure in json_decode and be done with it:
$array = json_decode('[2, 3, 5]');
$object = json_decode('{
"name" : "Harry",
"age" : 23,
"cats" : [
"fluffy", "mittens", "whiskers"
]
}');
Yes, it doesn't do typechecking until the statement is executed, and you'll have a bit of a problem handling multiple quotes, but you could always use a HEREDOC for that.
Different syntax for PHP arrays has been proposed and rejected many times before.
Unfortunate, I know, because I hate the ugly syntax too.
Update: All the below has become somewhat moot with PHP 5.4; we now have [..] array syntax.
Yes, PHP's array syntax is overly verbose and ugly and I too wish it would be more terse.
No, it would probably not be a good idea to attempt to change that for existing versions of PHP, since it's a feature that would need to be baked into the parser. That means your PHP applications would only run on custom compiled versions of PHP, which makes your app much less portable and thereby negate one of the good things about PHP.
You may want to attempt something like a compiler, which compiles your custom array syntax into normal syntax before running the code. If you went that far though, using an entirely different language to begin with may be the better choice.
Try to lobby for a Javascript-like syntax for PHP 6.x. Until then, just write array(). :)
If you want to write something that isn't PHP, then use something that isn't PHP. Otherwise, use array().
$array = array(2, 3, 5);
$object = array('name' => 'Harry', 'age' => 23, 'cats' => array('fluffy', 'mittens', 'whiskers'));
A mixture of associative and numerically indexed arrays usually gets you pretty close:
$object = array("name" => "Harry", "age" => 23, "cats" => array("fluffy", "mittens", "whiskers"));
In my opinion (especially because of the existence json_encode) it's not meaningfully different to write straight JSON over something like the above.
php doesn't handle json - whiwch is why it gives you the tools to encode/decode.
I you are desperate to 'write' in that manner just stick quotes around it:
$object = '{ "name" : "Harry", "age" : 23, "cats" : ["fluffy", "mittens", "whiskers"]}';
As far as php is concerned a 'json object' is nothing more than a string...
As people have said above, different languages have different syntax - if you don't like PHP's syntax, you might consider considering other languages.
JSON stands for "javascript object notation" - maybe what you want is server-side javascript. There's a huge array of server-side javascript options out there - jsgi/jack (narwhal), ringojs, flusspferd, node.js, v8cgi, etc. etc. http://wiki.commonjs.org/
If php would be a lot cooler and would just let you write things like this, it would be JavaScript, I guess;) but serious:
My approach for that problem is to load json files (Get data from JSON file with PHP) and just decode them.
Maybe you could also use a build tool like Grunt/Gulp and stringyfie and inject seperate json-files in your php code. (https://florian.ec/articles/buliding-symfony2-with-gulp/)

Why are configuration arrays acceptable parameters in PHP and Javascript?

In most other Object Oriented languages. it would be sacrilege to have each function receive a single associative array of Objects rather than enumerating each in the method signature. Why though, is it acceptable and commonly used in most popular frameworks for both of these languages to do this?
Is there some justification beyond wishing to have concise method signatures?
I do see a benefit in this -- that the API could remain unchanged as new, optional parameters are added. But Javascript and PHP already allow for optional parameters in their method signatures. If anything, it seems like Java or another OO language would benefit from this more... and yet I rarely see this pattern there.
What gives?
In my opinion, a lot of these functions are climbing in the number of arguments they accept, over 10 is not uncommon. Even if you do optional parameters, you still have to send them in order.
Consider a function like:
function myFunc(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13){
//...
}
Say you want to use arguments 3 and 11 only. Here is your code:
myFunc(null, null, null, 'hello', null, null, null, null, null, null, null, 'world');
Wouldn't you rather just:
myFunc({
a3 : 'hello',
a11 : 'world'
});
?
There are a couple of reasons for this.
The first is that not all argument lists have a natural order. If there is a use-case to only supply the 1st and 6th argument, now you have to fill in four default placeholders. Jage illustrates this well.
The second is that it's very hard to remember the order the arguments must occur in. If you take a series of numbers as your arguments, it's unlikely to know which number means what. Take imagecopyresampled($dest, $src, 0, 10, 0, 20, 100, 50, 30, 80) as an example. In this case, the configuration array acts like Python's named arguments.
The major reason is that those particular languages simply do not support having multiple calling conventions for the same function name. I.E. you can't do the following:
public function someFunc(SomeClass $some);
public function someFunc(AnotherClass $another);
public function someFunc(SomeClass $some, AnotherClass $another);
So you must find another way to create simpler ways to pass your variables around, in PHP we end up with someFunc(array('some'=>$some, 'another'=>$another)) because it is the only convenient way. In JavaScript we end up using objects, which isn't as bad: someFunc({some: something, another: anotherthing})
Ruby follows this methodology as well, and has even devised a more succinct syntax meant specifically for using hashes as initializers, as of Ruby 1.9:
# old syntax
myFunc(:user => 'john', :password => 'password');
# new syntax
myFunc(user: 'john', password: 'password');
The problem being addressed is that, within these languages, you cannot overload functions based on argument type. This results in complex classes with a single constructor that can have a huge and unwieldy argument list. Using hash-like objects to supply parameters allows for a sort of pseudo-overloading by parameter name rather than by type.
My only real problem with this practice is it becomes difficult to document your arguments:
PHPDoc for variable-length arrays of arguments
One of the most important reason why you don't see this in other OO languages is that you are probably referring to compiled languages like C++ or Java.
The compiler is responsible to determine, at compilation time not during execution, which method you want to call and this is normally done based on the signature, so basically it has to be done this way. This is also how method overload is done in these languages.
First of all such technique is very simple for the coders.
They do not need to remember order of all of the parameters of the all functions in your application. The code becomes more readable and more robust.
Any future development, improvements or refactoring will be no so hard to provide. The code becomes more maintainable.
But there is some pitfalls. For example, not every IDE will give you a simple code completing with such functions and their parameters.
In my opinion there 2 reasons why this has evolved:
Array's are very easy to create and manipulate, even with mixed types.
PHP/JS programmers have often a non academic background and are less indoctrinated from languanges like Java and C++.

Should I use Hypens, Underscore or camelCase in php arrays?

I just started using php arrays (and php in general)
I have a code like the following:
languages.php:
<?php
$lang = array(
"tagline" => "I build websites...",
"get-in-touch" => "Get in Touch!",
"about-h2" => "About me"
"about-hp" => "Hi! My name is..."
);
?>
index.php:
<div id="about">
<h2><?php echo $lang['about-h2']; ?></h2>
<p><?php echo $lang['about-p']; ?></p>
</div>
I'm using hypens (about-h2) but I'm not sure if this will cause me problems in the future. Any suggestions?
Between camel case and underscores it's personal taste. I'd recommend using whatever convention you use for regular variable names, so you're not left thinking "was this one underscores or camel case...?" and your successor isn't left thinking about all the ways they could torture you for mixing styles. Choose one and stick to it across the board.
That's why hyphens is a very bad idea - also, rarely, you'll want to use something like extract which takes an array and converts its members into regular variables:
$array = array("hello" => "hi", "what-up" => "yup");
extract($array);
echo $hello; // hi
echo $what-up; // FAIL
Personally, I prefer camel case, because it's fewer characters.
I'm actually surprised no one said this yet. I find it actually pretty bad that everyone brings up variable naming standards when we are talking about array keys, not variables.
Functionally wise, you will not have any problems using hyphens, underscores, camelCase in your array keys. You can even use spaces, new lines or null bytes if you want! It will not impact your code's functionality^.
Array keys are either int or string. When you use a string as a key, it is treated as any other string in your code.
That being said, if you are building a standardized data structure, you are better off using the same standard you are using for your variables names.
^ Unless you are planning to typecast to a (stdClass) or use extract(), in which case you should use keys which convert to valid variable names in order to avoid using ->{"My Key Is"} instead of ->myKeyIs. In which case, make sure your keys conform to [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.
You can use what ever feels most compfortable, however, I would not recommend using hypehens.
The common approach is to use camelCase and that is what a lot of standards in frameworks ask for.
I recommend using this.
$thisIsMyVariable
$this-is-not-how-i-would-do-it
Also, you can find that using hyphens could make your variables appear like subtracting. So you have to then use
$object->{”Property-Here”}
Its just not nice. :(
Edit, sorry I just saw that you asked about the question in Array, not variables. Either way, my answer still applies.
I would append all into one word. If not appending it all together, I would either shorten it or use _.
In the long run, whatever you decide to choose just be consistent.
Many folks, including Zend, tell programmers to use camel case, but personally I used underscores as word separators for variable names, array keys, class names and function names. Also, all lowercase, except for class names, where I will use capitals.
For example:
class News
{
private $title;
private $summary;
private $content;
function get_title()
{
return $this->title;
}
}
$news = new News;
The first result in Google for "php code standards" says:
use '_' as the word separator.
don't use '-' as the word separator
But, you can pretty much do whatever you want if you don't already have standards to follow. Just be consistent in what you do.
When looking at your code: Maybe you can even avoid some work with arrays and keys if you use something like gettext http://de2.php.net/manual/en/intro.gettext.php for your internationalization efforts from the very beginning.
This will finally result in
<h2><?php _("About me..."); ?></h2>
or
<?php
$foo = _("About me...");
...
?>
I strongly recommend using underscore to separate words in a variable especially where the language is case sensitive.
For non case sensitive languages like vb, camelCase or CamelCase is best.

Categories