Framework: TRANS function with parameters for escaping quotes

Created on 24 Jan 2015  ·  3Comments  ·  Source: laravel/framework

The following characters could interfere with an HTML or Javascript parser and should be escaped in string literals: <, >, ", ', \, and &. If translator write some of them in lang files, it would be a problem.
We have to ensure us against these chars. It would be great if we can use additional arguments (flags) like this:
trans('file.str1', EscApos) //EscApos - escape apostrophe
trans('file.str1', EscQuot) //EscQuot- escape double EscQuot
trans('file.str1', EscLtBt) // replace left than and bigger than with HTML entities <

Now you may say - just escape it in lang files. OK, but if I am using services of other translators (if I'm not translating my files), they may make fatal mistakes. I could tell them to escape double quotes or single quotes everytime and even to do outomatic checks, but it's more complicated - sometimes it has to escape double quote, sometimes single quote (apostrophe), it depends on context. So, I think the correct place to do escaping is when we output the string with trans() function, we will setup additional argument depending on context. Translators will not care about that.
We may use custom escaping function like this: EscQuot(trans('file.str1')) or
to override trans() function like this:
transEscQuot('file.str1')

It's not good decision if we replace quotes with html entities in lang file like this:
'str1'=>'What's up?'
because this will give use an error:


it will print

and parser will use ' literally, it's same as

I am not sure which one is the best approach.
The best will be if the framework escapes these chars automatically depending on context, I'm not sure is this possible.
You may consider my ideas for future versions of Laravel.

Most helpful comment

I didn't find the pull.

What I meant was you can send a pull. :)

All 3 comments

We're open to pull requests.

I didn't find the pull. So this is what I did to resolve my problem with quotes and apostrophes. I wrote two new functions, which extends the regular trans():
trans1() - which escapes apostrophes \'
trans2() - which escapes double quotes \"
I added them in:
\non-public\vendor\laravel\framework\src\Illuminate\Support\helpers.php

I keep a few simple rules to localize my app:

1) we always use double quotes for our lang files, like this: "key"=>"value"
2) tranlators do not escape or replace nothing, they have to translate but not to think about escaping chars. They don't know how is working your app, and they are not programmers. They only have to preserve replacements, if any exist. They work with PO or XLIFF files, not with php arrays.
3) when we convert the translated PO or XLIFF files to php arrays we escape double quotes "invalideEmail" => "Please, check your \"email\"" and replace "less than", "great than", "ampersand" and "backslash" with html entities.
4) we use our custom functions trans1() and trans2() (which extend the regular trans()). trans1() escapes single quotes, and trans2() escapes double quotes. We can use the regular trans() function too.

My code (I am not guru, but still it's working :) ):

if ( ! function_exists('trans1'))
{
function trans1($id, $arg1=null, $arg2=null, $arg3=null, $arg4=false) //($id, $number, $replacements, $locale, isCalledFromTrans2())
{
if($arg1!==null) {
if(is_numeric($arg1)) {
$number=$arg1;
}
elseif(is_array($arg1)) {
$replacements=$arg1;
}
elseif(is_string ($arg1)) {
$locale=$arg1;
}
}
if($arg2!==null) {
if(is_numeric($arg2)) {
$number=$arg2;
}
elseif(is_array($arg2)) {
$replacements=$arg2;
}
elseif(is_string ($arg2)) {
$locale=$arg2;
}
}
if($arg3!==null) {
if(is_numeric($arg3)) {
$number=$arg3;
}
elseif(is_array($arg3)) {
$replacements=$arg3;
}
elseif(is_string ($arg3)) {
$locale=$arg3;
}
}

    $translation="";

    if(isset($number) && isset($replacements) && isset($locale)) {
        $translation = app('translator')->choice($id, $number, $replacements, $locale);
    }       
    elseif(isset($number) && isset($replacements)) {
        $translation = app('translator')->choice($id, $number, $replacements);
    }
    elseif(isset($number) && isset($locale)) {
        $translation = app('translator')->choice($id, $number, [], $locale);
    }   
    elseif(isset($replacements) && isset($locale)) {
        $translation = app('translator')->get($id, $replacements, $locale);
    }   
    elseif(isset($number)) {
        $translation = app('translator')->choice($id, $number);
    }   
    elseif(isset($replacements)) {
        $translation = app('translator')->get($id, $replacements);
    }   
    elseif(isset($locale)) {
        $translation = app('translator')->get($id, [], $locale);
    }           
    else {
        $translation = app('translator')->get($id);
    }

    if($arg4===false) { //ako trans1() ne se vika ot trans2()
        $translation = str_replace("\'","'",$translation);
        $translation = str_replace("'","\'",$translation);
    }
    return $translation;
}

}

if ( ! function_exists('trans2'))
{
function trans2($id, $arg1=null, $arg2=null, $arg3=null) //($id, $number, $replacements, $locale)
{
$translation = trans1($id, $arg1, $arg2, $arg3, true);
$translation = str_replace('\"','"',$translation);
$translation = str_replace('"','\"',$translation);
return $translation;
}
}

The good thing is that you can use these functions with arguments in random order, like:
trans1('file.str', $number, $replacements) or
trans1('file.str', $replacements, $number)

I didn't find the pull.

What I meant was you can send a pull. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lzp819739483 picture lzp819739483  ·  3Comments

kerbylav picture kerbylav  ·  3Comments

ghost picture ghost  ·  3Comments

Anahkiasen picture Anahkiasen  ·  3Comments

jackmu95 picture jackmu95  ·  3Comments