PHP Translations using diversen/simple-php-translation - php

I'm trying to follow the README file of this translator package, but I'm not sure I'm following… Please be aware that I have VERY LITTLE knowledge of PHP.
I have a project set up something like this:
lang/
--en/language.php
--es/language.php
templates/
--blocks/
----header.php
----[…]
--sections/
----home.php
----[…]
boot.php
index.php // This is where I include my templates and boot.php
My boot.php goes something like this:
<?php
include_once(__DIR__ . '/vendor/autoload.php');
$lang = (!empty($_GET['lang'])) ? $_GET['lang'] : 'es';
use diversen\lang;
use diversen\translate\extractor;
$l = new lang();
$l->setDirsInsideDir(__DIR__ . '/lang/');
$l->setDirsInsideDir(__DIR__ . '/templates/');
$l->loadLanguage($lang);
$e = new extractor();
$e->defaultLanguage = $lang;
$e->updateLang();
// This is just a shortcut function
function __($str) {
return lang::translate($str);
}
By including boot.php in my "main template", index.php, I'd like to add all non-translated strings to their corresponding translation file, but they remain unchanged (ie. nothing is being appended to the translation files)
In my template files I'm using the shortcut function __() like so:
<?= __('Some string to translate'); ?>
And I'm seeing them rendered as NT: Some string to translate. I assume NT stands for Not Translated or something along those lines.
My apache error logs are not showing anything…

Related

Does include work like a function in php?

I have a PHP file as seen below that is a config file.
When I use return in my code and var_dump(include 'config.php');
I see an array, but when I delete return the result is
int 1
Does include work like a function in this case? And why I have to use return here?
<?php
return array(
'database'=>array(
'host'=>'localhost',
'prefix'=>'cshop_',
'database'=>'finalcshop',
'username'=>'root',
'password'=>'',
),
'site'=>array(
'path'=>'/CshopWorking',
)
);
The return value of includeis either "true"(1) or "false". If you put a return statement in the included file, the return value will be whatever you return. You can then do
$config = include config.php';
and $configwill then contain the values of the array you returned in config.php.
An include fetches PHP-code from another page and pastes it into the current page. It does not run the code, until your current page is run.
Use it like this:
config.php
$config = array(
'database'=>array(
'host'=>'localhost',
'prefix'=>'cshop_',
'database'=>'finalcshop',
'username'=>'root',
'password'=>'',
),
'site'=>array(
'path'=>'/CshopWorking',
)
);
And in your file, say index.php
include( 'config.php' );
$db = new mysqli(
$config['database']['host'],
$config['database']['username'],
$config['database']['password'],
$config['database']['database'] );
This way, you do not need to write all that stuff into every file and it is easy to change!
Here are some statements with similarities:
include - insert the file contents at that point and run it as if it were a part of the code. If the file does not exist, it will throw a warning.
require - same as include, but if the file is not found an error is thrown and the script stops
include_once - same as include, but if the file has been included before, it will not do so again. This prevents a function declared in the included file to be declared again, throwing an error.
require_once - same as include_once, but throws an eeror if the file was not found.
First off, include is not a function; it is a language construct. What that means is something you should Google for yourself.
Back to your question: what include 'foo.php does is literally insert the content of 'foo.php' into your script at that exact point.
An example to demonstrate: say you have two files, foo.php and bar.php. They look as follows:
foo.php:
<?php
echo "<br>my foo code";
include 'bar.php';
$temp = MyFunction();
bar.php:
<?php
echo "<br>my bar code";
function MyFunction()
{
echo "<br>yes I did this!";
}
This would work, because after evaluating the include statement, your foo.php looks like this (for your PHP server):
<?php
echo "<br>my foo code";
echo "<br>my bar code";
function MyFunction()
{
echo "<br>yes I did this!";
}
$temp = MyFunction();
So your output would be:
my foo code
my bar code
yes I did this!
EDIT: to clarify further, if you create variables, functions, GLOBAL defines, etc. in a file, these will ALL be available in any file in which you include that file, as if you wrote them there (because as I just explained, that is basically what PHP does).

Translating a web page using Array function

I want to use the array function of PHP to translate a website. I have created PHP files with arrays in them for all the text to be translated.
<?php
//ESPANOL
$lang = array(
'work' => 'Trabajo'
'packaging' => 'Empaque'
);
And then I am calling them inside my nav.php file, and will in the content section too.
<?php include('includes/languages/es.php'); ?>
<?php echo $lang['work']; ?>
All pretty straight forward.
What I want to know is how to switch between these array files without editing the HTML, so that I don't have to link to another 'index_es.php' etc. I understand that the link would be something like this, but I don't know how this is going to work.
English
I'm guessing I need to include another file that includes the language files and then the link can choose from them but I don't know what the code would be for this.
Would it involve including a 'lang_directory' above the link and then somehow including from there??
**Also I would like to avoid using Zend/Gettext translation becuase I want to learn this inside out.
You can make another dimension containing the target language. Then pass a GET parameter to select that language. If the language isn't recognized you can fallback to English. Here's a sample.
$languages = array(
'en' => array(
'work' => 'work',
'packaging' => 'packaging'
),
'es' => array(
'work' => 'Trabajo',
'packaging' => 'Empaque'
),
);
// default language to use when the requested isn't found
$defaultLanguage = 'en';
// language requested via GET
$requested = $_GET['locale'];
// use the requested language if it exists, otherwise the default language
$language = isset($languages[$requested]) ? $requested : $defaultLanguage;
// our translations
$translation = $languages[$language];
// "work" translated based on the language
echo $translation['work'];
And the link for Español would look like this.
index.php?locale=es
I'd keep your array system, correct the links into something like index.php?lang=en and then include your file depending on the lang parameter:
if ( isset($_GET['lang']) && file_exists('includes/languages/'.$_GET['lang'].'.php') ){
include_once('includes/languages/'.$_GET['lang'].'.php');
}
And if you want to keep the language parameter in your session, do something like this:
if ( isset($_GET['lang']) && file_exists('includes/languages/'.$_GET['lang'].'.php') ){
$_SESSION['lang'] = $_GET['lang'];
}
if ( !isset($_SESSION['lang']) ){
// Default language
$_SESSION['lang'] = 'en';
}
include_once('includes/languages/'.$_SESSION['lang'].'.php');
One way to do this is by using sessions.
Make a lang.php file that will be used to change between languages.
<?php
//Start session
session_start();
//Do we get a lang variable
if (isset($_GET['lang'])) {
//Make sure we only get the lang filename
$lang = basename($_GET['lang']);
//If the file exists, then save it to session
if (file_exists('includes/languages/' . $lang . '.php'))
$_SESSION['lang'] = $lang;
}
//If the client were refered here (via hyperlink) send them back
if (isset($_SERVER['HTTP_REFERER']))
header('location: ' + $_SERVER['HTTP_REFERER']);
?>
In the header of the files you want multiple languages, insert.
<?php
//Start session
session_start();
//Default language
$lang = 'english';
//If the client have set a language, use that instead
if (isset($_SESSION['lang']))
$lang = $_SESSION['lang'];
//Load language file
include('includes/languages/' . $lang . '.php');
?>
The links to change language will then be like this:
Español|English
Out can also take the code from the lang.php file and put in a included file that will be loaded before the inclusion of language file and remove the HTTP_REFERER redirection.
The links to change language will then be like this:
Español|English

PHP strange shuffle with require_once and array of strings

I hit a strange problem with PHP and its require_once language construct.
I require file called EN-en.php. It contains the English language for my website, I wrote it like this:
....
$lang['header']['loginbox']['menu'][1] = "contacts" ;
$lang['header']['loginbox']['menu'][2] = "settings" ;
....
Then I user this code to include my file in the whole site
require_once $langFile ;
Very easy I think, $langFile is = "/var/www/webstite/langs/EN-en.php". But here's come the strange part.
When I use
echo $lang['header']['loginbox']['menu'][1];
It prints something like "Gontacts" ... I can't understand why, and it's not the only case.. Please someone can help me with this issue?.
You are probably overwriting your own values in the array.
See this simple example:
$test = "some text";
$test['menu'] = 'extra';
var_dump($test);
// produces: string(9) "eome text"
// the first character - $test[0] - gets overwritten

include custom language files inside a while loop

Sorry if the title is not enough clear, I didn't know how to write it better.
The situation is that I a have a cron job that sends mails to users. I have language files, and depending in the configuration of the user I want to send the mail in his language.
But I don't know how to do this.
Each language file have constants definitions like:
en.php define('DATE','Date'); define('TIME','Time');
es.php define('DATE','Fecha'); define('TIME','Hora');
And I need to display the correct labels depending the user language, but I'm in a while loop:
while ($row = mysql_fetch_array($res)) {
if ($row['lang'] == en) //load the english labels
}
So I think I can't use something like "include_once" in each iteration.
The problem is that you use PHP Constants for it so once they are set, you can't really change them within the script. Try to rewrite your constants and all references of them into variables.
Let's say that your language files are named like this lang.code.php and the script that will send the email is in sendemail.php. You can do something like this:
In lang.en.php
<?php
$terms['date'] = 'Date';
In lang.es.php
<?php
$terms['date'] = 'Fecha';
In sendemail.php:
<?php
function sendEmail($language = 'en')
{
include "lang.$language.php";
extract($terms);
$to = 'foo#bar.com';
$subject = 'Test';
$body = "The $date today is: " . date('r');
mail(...);
}
foreach($users as $user)
sendEmail($user->preferredLanguage);
You can then reference terms in your language files using their keys in the $terms array. Of course you'd have to create validation checks for the language files, directory traversals, etc. But that's one way to implement it.
If you can't rewrite your code then I suggest putting all of the email contents in one file and use file_get_contents() to fetch the email content via HTTP. Inside that file, you'd have a conditional which loads the language file you need.
Let's say that the file that will generate the email contents is called emailcontent.php, you can do something like this:
In lang.en.php
<?php
define('DATE', 'Date');
In lang.es.php
<?php
define('DATE, 'Fecha');
In emailcontent.php
<?php
require "lang.{$_GET['lang']}.php";
echo 'The ' . DATE . ' today is: ' . date('r');
In sendemail.php
<?php
$to = 'foo#bar.com';
$subject = 'Test';
foreach($users as $user)
{
$contents = file_get_contents('http://yourhost.com/emailcontent.php?lang=en');
mail(...);
}
Of course you need to add some security checks to prevent local file inclusion, access to emailcontent.php, etc. But this is the gist of it. However this has a big overhead in terms of latency and repeated compilation of your PHP code. If there was any other way to clear the global score for each email, then that is the better way to go. But this is the only way I can think of if you can't rewrite your code.
In this can I thing you should store the template to datebase its self, based on language you can fetch from DB
Or
Another way you have to get every variable conditional like
en.php define('DATE_EN','Date'); define('TIME','Time');
es.php define('DATE_FR','Fecha'); define('TIME','Hora');
if ($row['lang'] == en)
DATE_EN
else
DATE_FR
In your case constants will not work, since they cannot be changed during the execution.
Instead, I would recommend including all language information in one file, these can be constants each containing a different array:
langs.php
define('EN', array(
'DATE' => 'Date',
'TIME' => 'Time',
));
define('ES', array(
'DATE' => 'Fecha',
'TIME' => 'Hora',
));
Next, you can add a value to the array $row for each user, or you can use a variable like $lang which will be overwritten every while loop.
require_once 'langs.php' //or include_once
while ($row = mysql_fetch_array($res)) {
if ($row['lang'] == en) { //load the english labels
$lang = EN;
} elseif ($row['lang'] == es {
$lang = ES;
}
echo "Welcome {$row['name']}, today it's {$lang['DATE']}" //will display the corresponding $lang value
}

How do you eval() a PHP code through multiple levels?

I have this code:
$layout_template = template_get("Layout");
$output_template = template_get("Homepage");
$box = box("Test","Test","Test");
eval("\$output = \"$layout_template\";");
echo $output;
In the $template_layout variable is a call for the
variable $output_template, so then the script moves onto the $output_template variable
But it doesn't go any further, inside the $output_template is a call to the variable $box, but it doesn't go any further than one level
I would never want nested eval(), and especially not in any recursive logic. Bad news. Use PHP's Include instead. IIRC eval() creates a new execution context, with overhead whereas include() doesn't.
If you have buffers such as:
<h1><?php echo $myCMS['title']; ?></h1>
I sometimes have files like Index.tpl such as above that access an associative array like this, then you just do in your class:
<?php
class TemplateEngine {
...
public function setvar($name, $val)
{
$this->varTable[$name]=make_safe($val);
}
....
/* Get contents of file through include() into a variable */
public function render( $moreVars )
{
flush();
ob_start();
include('file.php');
$contents = ob_get_clean();
/* $contents contains an eval()-like processed string */
...
Checkout ob_start() and other output buffer controls
If you do use eval() or any kind of user data inclusion, be super safe about sanitizing inputs for bad code.
It looks like you are writing a combined widget/template system of some kind. Write your widgets (views) as classes and allow them to be used in existing template systems. Keep things generic with $myWidget->render($model) and so on.
I saw this on the PHP doc-user-comments-thingy and it seems like a bad idea:
<?php
$var = 'dynamic content';
echo eval('?>' . file_get_contents('template.phtml') . '<?');
?>
Perhaps someone can enlighten me on that one :P

Categories