PHP Dynamic URL in Multilengual Web - php

Hi everybody and tks in advance for your help!
I have a multilengual site made in a similar way to this example. Everything is working just fine, but now I want to make that the URL change according to the languague selected. For example, if my page is called perfil.php when I select english languague, should be profile.php, and all the links in the web should translate to english too. I was surfing another questions but the majority offers a solution through htaccess. This should work, but I need to store that configuration (or translations) into my database so the user can change it when they want to.
Any ideas?
Thank you again!

You can use constants in some files called language files and then require/include them by language selected:
english.php
const PROFILE = "profile";
spanish.php
const PROFILE = "perfil";
main file:
require $language_selected . ".php";
echo '<a href="' . PROFILE . '.php">';

This part should be a comment (but its a bit long)
The method described in the link you provided is a reasonable way to implement the choice of language, but a poor way to detect the choice.
Your browser already tells servers what language(s) it thinks they should respond in. And most webservers have a mechanism for multiplexing different language content. However the latter means hard-wiring the choice of the browser without providing an easy means for overriding the behaviour.
The approach I have used before is something like this:
$use_lang='en-GB';
if (isset($_COOKIE['userlang'])
&& is_language_supported($_COOKIE['userlang'])) {
$use_lang=$_COOKIE['userlang'];
} else if ($proposedlang=supported_lang_in($_SERVER['Accept-Language'])) {
$use_lang=$proposedlang;
}
function supported_lang_in($str)
{
$l=array();
$opts=explode(',', $str);
foreach ($opts as $v) {
list($p, $weight)=explode(';', $v);
if ($weight) {
list($dummy, $weight)=explode('=', $weight);
$weight=float($weight);
}
if (!$weight) {
$weight=1.0;
}
if (isset($l[$weight])) {
$weight-=0.001;
}
$l[$weight]=$p;
}
krsort($p); // preferred first
foreach ($p as $proposed) {
if ('*'==$proposed) {
return false;
}
if (is_language_supported($proposed)) {
return $lang;
}
}
return false;
}
Now on to the problem you asked about....
Maintaining different URLs to reference the same content then dereference the language within the content seems a very byzantine solution to the problem. Not only do you have to map the input to the URL but you need to rewrite any URLs in the output to the appropriate representation.
While having semantically meaningful URLs is a definite bonus, going to great length to tailor these dynamically is not perhaps not the best use of your time.

Related

How to design the navigation in a php tool/website?

I'm designing a semi-basic tool in PHP, I have more experience server side, and not in PHP.
My tool contains 10-15 pages, and I am doing the navigation between them with the $_GET parameter.
In my code I have many if statements that look like:
if(isset[param1] && !isset[param2] && .....&& !isset[paramN]){
// code
}
You will agree with me, it's ugly, right?
Is it "how we do it" in PHP? or is there some kind of design pattern / functions for navigation in a PHP website?
Edit: To be clearer, what I want to know is: Is the proper way to design the navigation is with plenty of $_GET variables?
To avoid a huge if else statement try a switch statement:
$param1 = 'something';
switch (true){
case isset($param1):
echo "PARAM 1 is set";
break;
case isset($param2):
echo "PARAM 2 is set";
break;
default:
echo "None set";
}
And to answer your edit - Yes, you can use _GET variables for navigation and it is normal.
Actually the solution to this problem is a little bit complicated, than it might seem at first glance. And you need to implement a handler for that, since you're looking a cleanest way of handling GET parameters and invoking a code fragment.
In your case, your final API, should look like this (since you were asking for the design, not the for implementation):
$nav = new Nav($_GET);
$nav->whenSet('param1', 'param2')->andNotSet('param3')->then(function(){
});
$nav->whenSet('param3')->andNotSet('param1', 'param2')->then(function(){
});
// Or a simpler and shorter way
$nav->register($existingKeys, $nonExistingKeys, function(){
});
Another option you have is to use a routing mechanism. Most PHP frameworks provide this functionality. They all support optional route fragments, so you can handle parameters only defining one route path, like this /page/? (? - means optional).
This is my suggestion add conditions in an array and than use in_array()
echo in_array($yourVar, array('abc', 'def', 'hij', 'klm', 'nop'))
? True
: false;
UPDATE:
$get = "abc";
$navigation = array(
"abc"=>"yourneed",
"def"=>"yourneed2",
"ghi"=>"yourneed3",
);
foreach($navigation as $key => $value){
if($key == $get){
echo $value;
}
}
One more solution you can define routes also.
Same as CI and YII.
(I'm not using switch but you should definitely try that, and try using break between cases)
I'm using this at the moment, it seems to avoid mass-IFfing:
if (!$_GET) {
homePageFunction();
}elseif($_GET) {
contentPagesFunction($_GET['p']);
}
I have a menuer() function that outputs rel paths to content 'things' in links like:
<a href='?p=$relPath'>$name</a>
Although I could probably use different notation to tidy it further... Untested but like this:
if (!$_GET) homePageFunction();
elseif ($_GET) contentPagesFunction($_GET['p']);

Php storing multi language strings inside an object

I'm using the following function to store user messages in two languages in javascript:
function user_messages(es_ES, en_EN)
{
this.es_ES = es_ES;
this.en_EN = it_IT;
}
var um_duplicated_input = new user_message('Contenido duplicado','Duplicated content');
It may not be the best practice but is being really handy for me to get user messages in my code by language, using the locale value. I would like to know how to achieve something as simple to declare and handle in PHP instead building new arrays all the time. Been looking at stdclass but can't get it to work properly.
Despite the help of people like Alex Blex who rather prefer to question user's legitimacy instead helping them. Here is a working approach for those who may be looking in future for something similar (which I was thinking was the main purpose of this site) It could surely be better but I don't know how to make it simpler or smarter.
class internal_message
{
public $message = array();
public function setMsg($index, $newval)
{
$this->message[$index] = $newval;
}
public function getMsg($index)
{
return $this->message[$index];
}
}
This way, you have to do a new declaration for every language, but in fact it is more safe and clear. I'm starting to feel really disappointed about this site, specially regarding topics like the english language quality of the posts: in my case, I'm Spanish, from Spain, and I dare you to speak as good Spanish as I do speak English. I also speak Deutch and Catalan. But this is not a place for languages, in fact, if somebody misspells something it will enrich your database with a content that somebody will also misspell when searching in Google.
I don't understand all this classism and attitude in recent times.
$error_message_wrong_pass = new internal_message;
$error_message_wrong_pass->setMsg("es_ES", "Password incorrecto");
$error_message_wrong_pass->setMsg("es_ES", "Wrong Password");
//To print them out
$error_message_wrong_pass->getMsg("es_ES");

Is it possible to block cookies from being set using Javascript or PHP?

A lot of you are probably aware of the new EU privacy law, but for those who are not, it basically means no site operated by a company resident in the EU can set cookies classed as 'non-essential to the operation of the website' on a visitors machine unless given express permission to do so.
So, the question becomes how to best deal with this?
Browsers obviously have the ability to block cookies from a specific website built in to them. My question is, is there a way of doing something similar using JS or PHP?
i.e. intercept any cookies that might be trying to be set (including 3rd party cookies like Analytics, or Facebook), and block them unless the user has given consent.
It's obviously possible to delete all cookies once they have been set, but although this amounts to the same thing as not allowing them to be set in the first place, I'm guessing that it's not good enough in this case because it doesn't adhere to the letter of the law.
Ideas?
I'm pretty interested in this answer too. I've accomplished what I need to accomplish in PHP, but the JavaScript component still eludes me.
Here's how I'm doing it in PHP:
$dirty = false;
foreach(headers_list() as $header) {
if($dirty) continue; // I already know it needs to be cleaned
if(preg_match('/Set-Cookie/',$header)) $dirty = true;
}
if($dirty) {
$phpversion = explode('.',phpversion());
if($phpversion[1] >= 3) {
header_remove('Set-Cookie'); // php 5.3
} else {
header('Set-Cookie:'); // php 5.2
}
}
Then I have some additional code that turns this off when the user accepts cookies.
The problem is that there are third party plugins being used in my site that manipulate cookies via javascript and short of scanning through them to determine which ones access document.cookie - they can still set cookies.
It would be convenient if they all used the same framework, so I might be able to override a setCookie function - but they don't.
It would be nice if I could just delete or disable document.cookie so it becomes inaccessible...
EDIT:
It is possible to prevent javascript access to get or set cookies.
document.__defineGetter__("cookie", function() { return '';} );
document.__defineSetter__("cookie", function() {} );
EDIT 2:
For this to work in IE:
if(!document.__defineGetter__) {
Object.defineProperty(document, 'cookie', {
get: function(){return ''},
set: function(){return true},
});
} else {
document.__defineGetter__("cookie", function() { return '';} );
document.__defineSetter__("cookie", function() {} );
}
I adapted Michaels codes from here to come up with this.
Basically it uses the defineGetter and defineSetter methods to set all the cookies on the page and then remove the user specified ones, this role could of course also be reversed if this is what you are aiming for.
I have tested this with third party cookies such as Google Analytics and it appears to work well (excluding the __utmb cookie means I am no longer picked up in Google Analytics), maybe you could use this and adapt it to your specific needs.
I've included the part about if a cookies name is not __utmb for your reference, although you could easily take these values from an array and loop through these that way.
Basically this function will include all cookies except those specified in the part that states if( cookie_name.trim() != '__utmb' ) { all_cookies = all_cookies + cookies[i] + ";"; }
You could add to this using OR or AND filters or pull from an array, database, user input or whatever you like to exclude specific ones (useful for determining between essential and non-essential cookies).
function deleteSpecificCookies() {
var cookies = document.cookie.split(";");
var all_cookies = '';
for (var i = 0; i < cookies.length; i++) {
var cookie_name = cookies[i].split("=")[0];
var cookie_value = cookies[i].split("=")[1];
if( cookie_name.trim() != '__utmb' ) { all_cookies = all_cookies + cookies[i] + ";"; }
}
if(!document.__defineGetter__) {
Object.defineProperty(document, 'cookie', {
get: function(){return all_cookies; },
set: function(){return true},
});
} else {
document.__defineGetter__("cookie", function() { return all_cookies; } );
document.__defineSetter__("cookie", function() { return true; } );
}
}
You can not disable it completely but you can override the default setting with .htaccess
Try
SetEnv session.use_cookies='0';
If it is optional for some users don't use .htaccess
if(!$isAuth)
{
ini_set('session.use_cookies', '0');
}
A little bit old but I think you deserve a answer that works:
Step 1: Don't execute the third party script code.
Step 2: Show the cookie banner.
Step 3: Wait until user accepts, now you can execute the third party script code..
Worked for me.
How about not paying attention to hoaxes?
Aside from the fact that this is old news, the text clearly says that it only applies to cookies that are not essential to the site's function. Meaning session cookies, a shopping basket, or anything that is directly related to making the site work is perfectly fine. Anything else (tracking, stats, etc.) are "not allowed" without permission.

Switching languages on a website with PHP

I'm just looking for some advice. I'm creating a website that offers (at least) 2 languages.
The way I'm setting it up is by using XML files for the language, PHP to retrieve the values in the XML nodes.
Say you have any XML file, being loaded as follows:
<?php
$lang = "en";
$xmlFile = simplexml_load_file("$lang/main.xml");
?>
Once the file contents are available, I just output each node into an HTML tag like so:
<li><?php echo $xmlFile->navigation->home; ?></li>
which in turn is equal to : <li>Home</li>
as a nav bar link.
Now, the way in which I'm switching languages is by changing the value of the "$lang" variable, through a "$_POST", like so:
if(isset($_POST['es'])){
$lang = "es";
}elseif(isset($_POST['en'])){
$lang = "en";
}
The value of the "$lang" variable is reset and the new file is loaded, loading as well all the new nodes from the new XML file, hence changing the language.
I'm just wondering if there is another way to reset the "$lang" variable using something else, other than "$_POST" or "$_GET". I don't want to use query string either.
I know I could use JavaScript or jQuery to achieve this, but I'd like to make the site not too dependable on JavaScript.
I'd appreciate any ideas or advice.
Thanks
I would go for session variable.
At the beginning of your pages you'll have:
if (!isset($_SESSION['language']))
$_SESSION['language'] = "en";
Then you'll have some links to change the language
Español
Français
Changelanguage.php simply is something like
$language = $_GET['lang'];
// DO SOME CHECK HERE TO ENSURE A CORRECT LANGUAGE HAS BEEN PASSED
// OTHERWISE REVERT TO DEFAULT
$_SESSION['language'] = $language;
header("Location:index.php"); // Or wherever you want to redirect
Have you thought about using $_SERVER["HTTP_ACCEPT_LANGUAGE"]? Something like this:
if ($_SERVER["HTTP_ACCEPT_LANGUAGE"]) {
$langs = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
for ($i = 0; $i < count($langs); $i++) {
if ($langs[$i] == "en") {
$lang = "en";
break;
}
elseif($langs[$i] == "es") {
$lang = "es";
break;
}
}
}
Of course, a switch statement might fit a bit better here, and there's more ways to say English than only en, but this should work without the user having to do a thing. If they manually change, store it in a cookie as per Ben's answer.
The most common way would be to use it as part of the url and extract it when a page loads:
http://www.your-site.com/en/somepage
Are you using a framework?
The most common way to pass a language identifier is subdomain.
http://en.wikipedia.com/
both subdomains should point to the same directory and actual language can be easily extracted from the HTTP_HOST
and for storing language files the solution is gettext

Including pages with $_GET

I want url's like index.php?showuser=512, index.php?shownews=317 for pages i get content from db... and for regular pages index.php?page=about and so on WITHOUT mod-rewrite.
Invision Power Board has urls like this. I have looked through their code but I can't figure out how they do it.
I could do it like this:
if (ctype_digit($_GET['shownews'])) include('shownews.php');
elseif (ctype_digit($_GET['showuser'])) include('showuser.php');
// regular pages
elseif ($_GET['page'] == 'about') include('about.php');
elseif ($_GET['page'] == 'help') include('help.php');
elseif ($_GET['page'] == 'login') include('login.php');
But this feels too messy.
Just curious how IPB does this. Is there a better way do to this? WITHOUT any mod-rewrite. Any one know? I doubt they do it like the above.
I can't do:
if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) include('$_GET['page']');
Then I would get links like index.php?showuser&id=512 and that I dont like. (i know its not safe just showing the princip)
I like it this way, it's not the best but i like it so please be quiet about template engines, frameworks etc. Just be kind and answer my question... I just want to know how IPB does this.
Thanks
Tomek
I don't know how IPB does this, let's get that out of the way. But, this is how I would approach this problem:
First, I recognize that there are two kinds of GET parameters: page/identifier, and just page. These would get tested separately.
Second, I recognize that all all get parameters match their filenames sans the php-suffix, so we can use this to our advantage.
One of the most important things to remember is to never let GET-parameters affect our code unsanitized. In this case, we know which types of pages we can and want to show, so we can create a white-list out of these.
So, onto the pseudo-y dispatcher code:
$pagesWithId = array("shownews", "showuser", "showwhatever");
$justPages = array("about", "help", "login");
foreach ($pagesWithId as $page) {
if (isset($_GET[$page])) {
$id = (int)$_GET[$page];
include($page.'.php');
die();
}
}
if (in_array($_GET['page'], $justPages)) {
include($_GET['page'].'.php');
die();
}
// page not found
show404OrHandleOtherwise();
For pages you just use a simple array.
if (isset($pages[$_GET['page']])) include $pages[$_GET['page']];
For shownews=317 You could make a simple conversion in your app. Depending on how you want to prioritize page or shownews etc:
if (isset($pages[$_GET['page']])) {
include $pages[$_GET['page']];
} else {
$possiblePages = array_filter(array_intersect_key($_GET, $pagesWithId), 'ctype_digit');
if (!empty($possiblePages)) {
$id = reset($possiblePages);
$pageName = key($possiblePages);
$page = $pagesWithId[$pageName];
include $page;
} else {
//no valid pages
}
}
Note: page "names" are array keys, and the value is the path, file and extension to include. More customizable.

Categories