PHP gettext stopped working - php

I am on Ubuntu running Apache. The problem (not working) occurs on my production Strato webserver.
My PHP has gettext support, but it does not translate anything, although the strings are translated in the .mo file.
This is my code:
if (function_exists('bindtextdomain')) {
$domain = 'address_db';
echo putenv('LC_MESSAGES='.$lang);
echo '<br />';
echo setlocale(LC_MESSAGES, $lang);
echo '<br />';
$path = bindtextdomain($domain, "../locale/");
echo $path;
echo '<br />';
echo file_exists($path.'/'.$lang.'/LC_MESSAGES/'.$domain.'.mo') ? 'yes' : 'no';
echo '<br />';
echo bind_textdomain_codeset($domain, "iso-8859-1");
echo '<br />';
echo textdomain($domain);
echo '<br />';
$available_languages = array(
array('de_DE', _('German')),
array('en', _('English')),
array('nl', _('Dutch')),
array('tr', _('Turkish'))
);
echo _('Cancer');
}
The output is kind of promising:
1
/home/mu/Branches/address_db/locale
yes
iso-8859-1
address_db
Cancer
So it finds the file, but it still does not translate "Cancer".
What could that be?
Update
It works on my production server, but not on my testing server. Very strange …

Gettext translations are cached, you need to restart your server for it to pickup changes to .mo files.

It looks as if setlocale is returning false, it should return the new locale name if it worked correctly.
Is the value of $lang present in the output of locale -a? A common mistake is using e.g. de_DE rather than de_DE.utf8 or de_DE.iso88591 in your case.

Related

How to create password protected archive file in PHP?

I need to be able to create an archive(zip) file with password protection using PHP. I am using Laravel 5.4 and PHP 7.1 version. I looked at this link here for ZipArchive class documentation in PHP. I also looked at here for setPassword function. But appears that creation of password protected archives is not supported. It will be a massive surprise for me if it is not possible to create password protected archive in a mature programming language such as PHP 7.1.
So I guess I must be missing something. Can someone point me to the right direction? E.g. a sample example or open source third party library or extension to achieve this will be greatly appreciated.
Easy peasy lemon squeezy (no).
Yes, creation of password protected archives is not supported (they will be created simply as non-protected archives, as you just described).
But, still it can be used to extract password protected archives.
Returning to the problem.
You always can just
<?php echo system('zip -P pass file.zip file.txt'); ?>
(this will work both on Windows and our beloved Linux)
But, if it not fits into your requirements, let's continue.
I would suggest you to use DotNetZip (Windows only), you will exactly dynamically generate AES-encrypted zip archives from PHP.
<?php
// origin: https://stackoverflow.com/a/670804/3684575
try
{
$fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip";
$zipOutput = "c:\\temp\\" . $fname;
$zipfact = new COM("Ionic.Zip.ZipFile");
$zip->Name = $zipOutput;
$dirToZip= "c:\\temp\\psh";
# Encryption: 3 => 256-bit AES.
# 2 => 128-bit AES.
# 1 => PKZIP (Weak).
# 0 => None
$zip->Encryption = 3;
$zip->Password = "AES-Encryption-Is-Secure";
$zip->AddDirectory($dirToZip);
$zip->Save();
$zip->Dispose();
if (file_exists($zipOutput))
{
header('Cache-Control: no-cache, must-revalidate');
header('Content-Type: application/x-zip');
header('Content-Disposition: attachment; filename=' . $fname);
header('Content-Length: ' . filesize($zipOutput));
readfile($zipOutput);
unlink($zipOutput);
}
else
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '</body>';
echo '</html>';
}
}
catch (Exception $e)
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '<p>Caught exception: ', $e->getMessage(), '</p>', "\n";
echo '<pre>';
echo $e->getTraceAsString(), "\n";
echo '</pre>';
echo '</body>';
echo '</html>';
}
?>
But still, this is very dirty solution and more of that, not works on Linux.
So, although PHP is a mature language, there is no adequate method (excluding custom extension or something like that) to achieve such a simple task with pure PHP.
What you also can do, is to wait until PHP 7.2 will be available for production (cuz ZipArchive::setEncryptionName is implemented (thanks to Pierre and Remi)).
But, until then you also can try to port php_zip >= 1.14.0 to PHP < 7.2, but there is currently no compiled binaries available, so you have to compile it yourself and try if it is possible at all (I believe it is).
p.s. I would try it, but have no VS2015+ on my PC right now.

gettext is not giving result from .mo file, it is showing same as I am writing in echo

I am beginner and doing first time language translate for my web application.
kindly help me , where I am doing mistake, but I am not getting the result i'm expecting. I have installed gettex, I have changed in php.ini file for to remove extention(;), i have restarted many time the server, I creating .po file from poedit and mdifying evrytime the .mo file.
I don't know where I am wrong.
Please help..!
I would like to share the out put also, as I am printing many things for checking the right thing.
in my .po file I wrote:
# Test 1
msgid "This is moon"
msgstr "This is Sun"
So it must print "This is Sun", but its printing:
gettext working fine
Locale Language::de_DE
C:\xampp\htdocs\Test_project\Locale\de_DE\LC_MESSAGES
Path is Correct!!
C:\xampp\htdocs\Test_project\Locale\de_DE\LC_MESSAGES
This is moon
[result][1]
here is my code
if (function_exists("gettext")){
echo "gettext working fine";
}else{
echo "Extra stuff must be installed";
}
echo "<br>";
$language = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
echo "Locale Language::".$language;
echo "<br>";
putenv("LANG=". $language);
setlocale(LC_ALL, $language);
// set the text domain as "messages"
$domain = "messages";
$pathToDomain = 'C:\xampp\htdocs\Test_project\Locale\de_DE\LC_MESSAGES';
echo $pathToDomain;
echo "<br>";
if ($pathToDomain != bindtextdomain($domain, $pathToDomain)) {
// Error handling.
$hi = bindtextdomain($domain, $pathToDomain);
echo "hello".$hi;
echo "<br>";
echo "Path Incorrect";
}
else{
$hi = bindtextdomain($domain, $pathToDomain);
echo "Path is Correct!!";
echo "<br>";
echo $hi;
}
bindtextdomain($domain, $pathToDomain);
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
echo "<br>";
echo gettext("This is moon");
$language = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
Will give you a locale string such as de_DE - however Windows won't accept that string, it would need to be something like deu_deu
You can test this with:
echo setlocale(LC_ALL, $language) ? "true" : "false";
There are two ways around this:
1) use setlocale(LC_ALL, 'deu_deu'); which may upset the live site
2) add putenv('LC_ALL=' . $language);
In a nutshell - when you strip your code right back, this should work on Windows:
$language = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
putenv('LANG=' . $language);
if(!defined('LC_ALL')) putenv('LC_ALL=' . $language);
setlocale(LC_ALL, $language);
$domain = 'messages';
$pathToDomain = 'C:\xampp\htdocs\Test_project\Locale';
bindtextdomain($domain, $pathToDomain);
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
echo _("This is moon");

setlocale(LC_ALL, 'it_IT'); set, but still dates in english

I have this code which through json_decode retrieves my latest tweets, their date, etc.
<?php setlocale(LC_ALL, 'it_IT'); ?>
<?php include("twitter_auth.php");
echo "<ul style='color:#6E6E6E'>";
foreach ($twitter_data as $tweet)
{
if (!empty($tweet)) {
$text = $tweet->text;
$text_in_tooltip = str_replace('"', '', $text); // replace " to avoid conflicts with title="" opening tags
$id = $tweet->id;
$time = strftime('%d %B', strtotime($tweet->created_at));
$username = $tweet->user->name;
}
echo '<li><span title="'; echo $text_in_tooltip; echo '">'; echo $text . "</span><br>
<small>'; echo $time; echo '</small> -
<small>rispondi</small> -
<small>retweet</small> -
<small>preferito</small></li>';
}
echo '</ul>';
?>
Problem is that $time outputs something like "03 February" even though there is a setlocale(LC_ALL, 'it_IT');. What's the error? How can I have dates output in italian?
System: PHP 5.4.11 and nginx (on Ubuntu Server).
EDIT: I also ran dpkg-reconfigure locales:
Generating locales...
en_US.UTF-8... up-to-date
it_IT.UTF-8... up-to-date
Generation complete.
Silly as it may sound I solved changing the line to:
<?php setlocale(LC_ALL, 'it_IT.UTF-8'); ?>

PHP header function not triggering?

I'm getting some fairly odd behavior here... I noticed that only localhost, a header statement I have worked just fine, but when copied over (SAME EXACT CODE) to my live site, the header statement no longer triggers.
I added some echos to help debug. This if statement will only trigger if the URL variable id is NOT set. So with this same exact code on localhost, I never see these debug statements. On the live site, I do... which I shouldn't. I should get redirected instead. Anyone know why a header statement would be ignored?
if((!isset($_GET['id'])) && $rows != 0) {
$result = mysql_query('SELECT videoinfo FROM videos where game_id=' . $gameid . ' LIMIT 1');
$row = mysql_fetch_array($result);
$tubeID = $row['videoinfo'];
echo '<script type="text/javascript">';
echo 'window.location = "videos.php?id=' . $tubeID . '&awayid=' . $awayid . '&homeid=' . $homeid . '&date=' . $date . '&time=' . $time . '&gameid=' . $gameid . '&play=0"';
echo '</script>';
}
EDIT 4 people have told me already that I can't have any echo calls before my header function. This code WORKS on localhost and the header function DOES trigger. Regardless, REMOVING the echo statements DOES NOT fix it.
AFAIK
Can't send header() after some echo.
You cannot output ANYTHING before you call header(), i.e. echo etc...
I don't think you can have a header after any sort of output. I just came up with that.
You need to enable output buffering. This is probably enabled on your localhost but not on your live system (or the value on the live system is too small).
This will keep your output buffered, and then the Header will work fine.
Your debug statements are making the problem worse.
header statements will not work if there is any output before they are called. In this case, your echos are killing it. Also, make sure there is no other output before this is called (white space, HTML, etc.).
at start of script, add
ob_start();
and just before calling header();, use
ob_clean();
ob_clean();
header('Location: videos.php?id=' . $tubeID . '&awayid=' . $awayid . '&homeid=' . $homeid . '&date=' . $date . '&time=' . $time . '&gameid=' . $gameid . '&play=0');
Edit
Check to ensure that your files are encoded correctly. For instance, if you are encoding in UTF-8, make sure you encode in UTF-8 without BOM (Byte Order Mark).
How to check depends on what you use to edit and save your file. For instance, I use Notepad++ so I just go to the 'Encoding' menu and select 'Encode in UTF-8 without BOM' and then save the file.
function goto_url($url) {
// must not have output anything prior to calling this function
if (!headers_sent()){
header('Location: '.$url); exit;
} else {
echo '<script type="text/javascript">';
echo 'window.location.href="'.$url.'";';
echo '</script>';
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
echo '</noscript>'; exit;
};
};
http://www.w3schools.com/php/func_http_headers_sent.asp

Test of file existence always fails

<?
$user_image = '../images/users/' . $userid . 'a.jpg';
if (file_exists($user_image))
{
echo '<img src="'.$user_image.'" alt="" />';
}
else
{
echo '<img src="../images/users/small.jpg" alt="" />';
}
?>
Hello all, this code is supposed to check for a file and if it doesnt work, display another.
For some reason it is ALWAYS displaying the placeholder and never finds the initial file even though it is there.
Is there something obviously not right here?
Thanks for reading!
the PHP is running in a different directory. try echo getcwd();
file_exists does not work with relative paths. Try something like this:
$user_image = $_SERVER{'DOCUMENT_ROOT'}.'/../images/users/' . $userid . 'a.jpg';
if (file_exists($user_image))
// blah blah
But, as Artefacto suggests, it's better to use the real path:
$user_image = '/path/to/your/files/images/users/' . $userid . 'a.jpg';
It's easier to maintain since you can use that code on different PHP scripts located on different directories without having to change anything.
If your relative path points outside of the htdocs subdirectories, then the image will not be sent by the webserver
Try using realpath and dirname instead.
<?
$user_image = '../images/users/' . $userid . 'a.jpg';
if (file_exists(realpath(dirname(__FILE__) . $user_image)))
{
echo '<img src="'.$user_image.'" alt="" />';
}
else
{
echo '<img src="../images/users/small.jpg" alt="" />';
}
?>
I mean I'm not always the smartest with php, but is your concat location correct? Because right now, won't it resolve to /images/users/userida.jpg ? is this really what you want?
I think you should check to see what realpath('../images/users/' . $userid . 'a.jpg') returns. I get the feeling it has something to do with the relative path

Categories