I am a coding beginner and have my PHP/HTML web project in German. Now I want to make it available in English in the easiest way. I don't want to add other languages in the future, so I want to try it in the easiest (and maybe not the most proper) way.
I have PHP files with HTML content and the selected language available in a var, i.e.:
<?php
$lang = "en";
?>
<h1>Title in German</h1>
So all the German words are inline HTML. My idea was to create something like:
<h1>[de]Title in German[/de][en]Title in English[/en]</h1>
But I have no idea how to replace it on every load in a smart way. So it is more a topic on "live replacement".
Working with constants in an external language file is of course also an option, like all the other options to make a multilingual site I found on Stackoverflow.
But maybe there is a "quick and dirty" possibility option like the one I mentioned?
Thank you for every hint!
You could try and do this will almost only HTML and CSS. You would need to add this at the top of your page:
<?php
$pageLanguage = "en";
function getLanguageStyle($showLanguage)
{
global $pageLanguage;
$display = ($showLanguage == $pageLanguage ? 'inline' : 'none');
return " span.$showLanguage { display: $display }\n";
}
echo "<style>\n".
getLanguageStyle('en').
getLanguageStyle('de').
"</style>\n";
?>
It sets up a style for each language, which you can then use like this:
<h1><span class="de">Title in German</span><span class="en">Title in English</span></h1>
The advantage here is that you don't need to mix HTML and PHP. This is not a normal way of doing this, but it will work. On very complex pages, where these styles are applied after the first render, this might not be pleasant for your visitors.
Usually translations are made that way:
You have key to translation map for each language, then you request some function that takes proper map for that language and returns translation:
function translate(string $lang, string $key) {
/*
* This usually sits in some file in dir like `/src/i18n/en.json`
* And you do then `$translations = json_decode(require "/src/i18n/{$lang}.json")`
*/
$translations = [
'en' => [
'page.title' => 'Page Title',
...
],
'de' => [
'page.title' => 'Page Title In German',
...
],
];
return $translations[$lang][$key] ?? $key;
}
<h1><?= translate($lang, 'page.title'); ?></h1>
I want to implement localization. Once I get the language code, for example, en, what would be the best way to retrieve the text? For example:
en:
welcome-text = "Hello!"
es:
welcome-text = "Hola!"
also, what would be the most efficient and the fastest way? should i store them with php variables and get the text via php variables in an array or switch statement OR should i store them as json and get them via json?
If you are not using some framework (most of them have translation functions and I really suggest you use one) I suggest you arrays as your translation files. It is a simple and fast way:
en.php
<?php return array(
'Welcome' => 'Welcome',
...
);
es.php
<?php return array(
'Welcome' => 'Holla',
...
);
lang.php
<?php
$mapping = require($_SESSION['user-lang-code'].'.php');
funciton _t($text)
{
global $mapping;
return isset($mapping[$text])?$mapping[$text]:$text;
}
Your page:
<?php
require 'lang.php';
echo _t('Welcome');
This is the code from index.php
<?php
include("header.php");
$page = isset($_GET['page']) ? trim(strtolower($_GET['page'])) : "home";
$allowedPages = array(
'home' => './home.php',
'news' => './news.php',
'contact' => './contact.php',
'faq' => './faq.php'
);
include( isset($allowedPages[$page]) ? $allowedPages[$page] : $allowedPages["home"] );
include("footer.php");
?>
At the moment working links open precreated pages (home.php, news.php, contactus.php, faq.php) from the root folder using hyperlinks like so:
<li>Home</li>
<li>News</li>
<li>Contact us</li>
<li>FAQ</li>`
But the problem is that I want pages to be created dynamically according to data in mysql database.
I have a database called aviumpages
There's a table called pages inside.
There are columns called id (INT), linklabel (VARCHAR), pagecontent (TEXT) in the table.
I already inserted linklabels like home, news, Contact Us and FAQ accordingly.
So how do I load a dynamically created page from database?
And I also have mysql_connect.php which is working.
the rewrite is non-canned for intuitive flow
include("header.php");
if(!dbconnect($params)) {error(); exit;}
$allowedPages = array(
'home' => './home.php',
'news' => './news.php',
'contact' => './contact.php',
'faq' => './faq.php'
if(!isset($_GET['page'])||!array-key-exists(trim(strtolower($_GET['page'])),$allowedPages)){
// fetch your home() data
include($allowedPages['home'])
}else{
$page = trim(strtolower($_GET['page']));
// fetch your $page() data // yeah, you can do that!
include($allowedPages[$page]);
}
include("footer.php");
HTML
Home
News
Contact us
FAQ`
~yeah, you can do that~
function trythis(){
echo "hello world";
}
$var = $_GET['var'];
$var();
filename.php?var=trythis
Instead of doing this by hand, you might be interested in CakePHP. From the looks of your question you might want to look at:
W3Schools Primer on PHP
Converting Static HTML Template to PHP
PHP for the Absolute Beginner
CakePHP integrates nicely with many templating engines, and has the integrated database connection you need to use, but before you jump into Cake, complete the Primer by hand.
I am trying to come up with an efficient way to implement language selection in my site.
I have some flags at the top right which when clicked I want all the text to change into the selected language, where the translations are stored in my database.
Should I do this with a parameter in the url like:
www.myside.com?lang=3
The only issue I have with this, is that it might things complicated as far as the way I route urls and it doesn't make the url look clean either.
Would a better way, be to have it stored in a session and the translations are only fetched from the database when the language is changed. The translations would be kept in a session array, so users don't hit the database on every page load if you know what I mean.
I was wondering if something like the following would be a good way of achieving what I want:
Session::set('langarray', array(
'id' => $languageId,
'cake' => $this->model->getLanguagesNavigation('cake', $languageId),
'login' => $this->model->getLanguagesNavigation('login', $languageId),
'register' => $this->model->getLanguagesNavigation('register', $languageId),
'share' => $this->model->getLanguagesNavigation('share', $languageId),
'galleries' => $this->model->getLanguagesNavigation('galleries', $languageId),
'decorator' => $this->model->getLanguagesNavigation('decorator', $languageId),
'find' => $this->model->getLanguagesContent('find', $languageId),
'headertext' => $this->model->getLanguagesContent('headerText', $languageId),
));
header('Location: ' . $_SERVER['HTTP_REFERER']);
and in my view:
...
public function render($viewFile, $data = NULL) {
if(!Session::get('langarray'))
{
$this->Language = new Language;
$this->Language->setLanguage(1);
}
if (is_array($data)) {
extract($data);
}
include Vs . $viewFile . '.php';
}
...
Which is simply set the language to 1 (English) if the session var hasn't been set i.e. a language hasn't been picked.
In my HTML I would just echo the corresponding element in the array to get the word:
...
<p><?PHP echo $_SESSION['langarray']['headertext'];?></p>
...
Is this a good method? Or is there a standard way of implementing languages into a site?
My old site currently uses an url method like the one I mentioned (?lang=3) and the foreign variants do quite well in the SEs. I like the idea of using subdomains, but how would I get it to display the correct content on my pages based on whatever come before the first . in the url? E.g. fr. de. etc
Maybe I'm old fashioned but I've always had a lang folder with files for each languages (lang.en.php, lang.fr.php, lang.es.php, and so on).
In each file I've got an array, like this one:
$langarray = array("login" => "...", "connect" => "...", "logout" => "...");
Eventually with real stuff in them... works better :}
And then, depending on the $_SESSION variable, I include the right file. You can even stock "en" and include lang.'.$_SESSION['lang'].'.php.
It seems slightly better not having to query SQL for that kind of thing but less easy to maintain. I think this is the type of problem where nobody's wrong.
Yes, saving the language code in the session is better than constantly passing around a parameter.
No, storing the translated text in the session doesn't make sense because then you are storing the same text over and over in memory per user. Better to implement database caching or have a PHP file to include for the translation table than to store it in the session.
Instead of making up numeric codes for languages, you really should use the standard letter abbreviations that are part of the HTML spec. Browsers send preferred languages in order of preference as a header called Accept-Language. To avoid making the user click a language choice, you could read that list from the header and iterate through it until you find the first language you support. But always good to give the user some manual way to change it.
Zend framework has some functions for dealing with languages but I've never used it.
As I mentioned in my comment above, I would recommend putting the language in the URL mainly for search engine optimization. Admittedly, it can take a bit more work to set up, but I feel the benefits outweigh the cost.
For example, I have a hotel website with English, Spanish, Chinese and French. The URL structure is like this:
/ <- Main page in English
/es/ <- Main page in Spanish
/zh/ <- Main page in Chinese
/fr/ <- Main page in French
Then for sub-pages I do similarly:
/pagename/
/es/pagename/
/zh/pagename/
/fr/pagename/
Then, this is how I redirect the other languages to the correct scripts:
# Spanish
RewriteRule ^es/(.*/)?$ $1/index.php?lang=es [NC,L]
# French
RewriteRule ^fr/(.*/)?$ $1/index.php?lang=fr [NC,L]
# Chinese
RewriteRule ^zh/(.*/)?$ $1/index.php?lang=zh [NC,L]
This works for rewriting the index.php. For other things, I specify them explicitly, usually using a "friendly" URL. For example the "thank you" page for our Contact Us page:
# Contact Us thank you page
RewriteRule ^([a-z_]+)?/?contact/thankyou$ /contact/thankyou.php?lang=$1 [L]
I also used to do the following to rewrite URLs that contained parameters, but I think doing it like this might be deprecated, not too sure (I have it in the code, but since I don't use parameters, it doesn't get triggered):
RewriteCond %{query_string} ([^=]*)=(.*)
RewriteRule ^es/(.*)$ $1/index.php?lang=es&%1=%2 [NC,L]
However, the hotel offers tours and we have a main /tours/ page and I wanted to have a friendly URL for each of the individual tours, like /tours/56/waterfall-hike (with the tour ID and a slug from the tour name), so this handles the rewriting of the tours:
# Rewrite tours
RewriteRule ^([a-z_]+)?/?tours/([0-9]+)/reserve$ /tours/tour_reserve.php?lang=$1&id=$2 [L]
RewriteRule ^([a-z_]+)?/?tours/([0-9]+)/(.*) /tours/tour_text.php?lang=$1&id=$2&urlstr=$3 [L]
# Tours thank you page
RewriteRule ^([a-z_]+)?/?tours/thankyou$ /tours/thankyou.php?lang=$1 [L]
I just need to verify with PHP that the slug string provided is correct and if not do a 301 redirect to the correct URL based on the ID. I use this to calculate it:
function getTourURL($tour_name) {
// Transliterate non-ascii characters to ascii
$str = trim(strtolower($tour_name));
$str = iconv('UTF-8', 'ASCII//TRANSLIT', $str);
// Do other search and replace
$searches = array(' ', '&', '/');
$replaces = array('-', 'and', '-');
$str = str_replace($searches, $replaces, $str);
// Make sure we don't have more than one dash together
$str = preg_replace("/(-{2,})/", "-", $str );
// Remove all invalid characters
$str = preg_replace("/[^A-Za-z0-9-]/", "", $str );
// Done!
return $str;
}
Then the only other difficult thing is switching languages without just redirecting them back to the home page for that language (yuck!). This is how I did it:
// First define the languages used:
$langs = array(
'en' => array(
'lang_code' => 'en_US',
'locale' => 'en_US.UTF-8',
'base_url' => '/',
'name' => 'English',
),
'es' => array(
'lang_code' => 'es_MX',
'locale' => 'es_MX.UTF-8',
'base_url' => '/es/',
'name' => 'Español',
),
'fr' => array(
'lang_code' => 'fr_FR',
'locale' => 'fr_FR.UTF-8',
'base_url' => '/fr/',
'name' => 'Français',
),
'zh' => array(
'lang_code' => 'zh_CN',
'locale' => 'zh_CN.UTF-8',
'base_url' => '/zh/',
'name' => '中国的',
),
);
define('LOCALE', $_GET['lang']);
// Then get the path to the current script after the language code
$path = (LOCALE == 'en') ? '' : LOCALE.'/';
$parsed_url = parse_url($_SERVER['REQUEST_URI']);
$path = ltrim(str_replace('/'.LOCALE , '', $parsed_url['path']), '/');
define('REDIRECT_SCRIPT', $path);
// Then I put all the links into an array to be displayed in the menu
foreach ($langs as $lang => $arr) {
if ($lang == LOCALE) {
continue;
}
$link = (isset($lang_override[$lang]))
? $lang_override[$lang]
: $arr['base_url'] . REDIRECT_SCRIPT;
$lang_subs[] = array(
'name' => '<div class="'.$lang.'"></div> '.$langs[$lang]['name'],
'link' => $link,
'lang' => $lang,
);
}
This probably won't work for you out of the box, but should at least give you a starting point. Try a print_r($lang_subs); to see what it contains and adapt it to your site's design.
It is possible to delay the output of the headers to the browser until the entire php script has finished executing?
The headers will be sent once the first piece of code is sent from php to the webserver.
So you can just "not echo anything" until the end of the script or use output buffering to achieve the same thing
This is the way most professional programmers would advise, the reasons you should always do it this way is that you can manage errors and error pages effectively.
If your application is already built to display output as the script is executed then i would advise you to start from scratch.
the way I usually manage output is with a small template's system, the template's system does not have to parse templates etc, it just needs to be passed a set of data and then include the required template.
you should create a class that acccepts data in the form of $template->set(key[,value = true]) and then a function that would display such as $template->display(filename), when this function executes you should extract the variables and then include the template file, after that has been done you then call exit(0) so no further code is executed.
a simple template system can be like so:
class Template
{
private $_data = array();
public function set($key,$value = true)
{
$this->_data[$key] = $value;
}
public function display($template)
{
//Check template exuists
extract($this->_data);
require_once $template;
exit(0);
}
}
then use pretty simply like so:
$template = new Template();
$template->set("title","Practical home Page");
$template->set("header","My Home Page");
$lists = array(
array(
"value" => "list item 1",
"id" => "list_item_1",
"class" => "item"
),
array(
"value" => "list item 2",
"id" => "list_item_2",
"class" => "item"
)
);
$template->set("menu",$lists);
$template->display("templates/homepage.php");
you may also would like to read the following answer I had answered previously!
PHP Looping Template Engine - From Scratch