I'm trying to find the best way of structuring a multi-language site navigation,.
I'm aware of the language class in CI but it seems to be more for defining random words and lines of text that are used commonly throughout the site. It appears that creating lang files for each language and then defining translations of all the links seems like the standard approach?
In past on non-codeigniter projects I’ve setup one class like this
class Link{
var $name = array();
var $url;
var $links = array();
function add_link($links){
$this->links[] = $links;
}
}
$all_sections = array();
$section = new Link();
$section->name['en'] = "Home";
$section->name['fr']] = "Uberdurky";
$section->url = "/";
$sub_section = new Link();
$sub_section->name['en'] = "About Acme Ltd";
$sub_section->name['fr'] = "Fabuka Acme Ltd";
$sub_section->url = "/about/";
$section->add_link($sub_section);
Then I have a function to loop through and output the nav, which just looks at the current name[Lang] as defined by session or URL
This to me seems simpler and less overhead - with the benefit that both the nav structure and translations are defined in one place. But I’m new to CI so I might be misunderstanding the standard approach… ? I've googled quite a bit and haven't seen a solution here in detail.
The important thing is that it works for you. There are a lot of benefits to using separate language files:
Clean separation
Only load what you need
Easy to keep track of which languages are available
Ability to let others easily translate the files
I don't see anything wrong with the way you're doing it, but if you want to optimize - don't bother defining all the different language lines. You don't need the French version defined if the language is English. Use only the ones you need, you shouldn't have to pass the whole array to add_link(), the Link class should be detecting the language and loading the appropriate array only...
...it's starting to sound like a language file might be a good idea actually.
For now you just have French and English. I'm assuming you know both languages and (Uberdurky?) are the only one working on this aspect, so it's easier for you to define them "inline". What happens when you want to support 3, 4, or 10 languages? Things will quickly become disorganized and cluttered.
However, you don't have to use the Codeigniter Language class, you might be better off using your own system for something like navigation, which tends to be littered with 1 or two word translations, and changes somewhat frequently (either per site or between sites).
Once again, it's your call. Do what works best for you now and optimize later.
This might be helpful to anyone coming across this question.
https://github.com/cflynn07/CodeIgniterInternationalizationUtility
It's a script to take a cleanly structed HTML table of language translations, and convert them into the required language files used in codeigniter.
Related
i code a small very specific cms in php/mysql/jquery right now. the project have to be in german+english - so store these informations in separate fields : title_de, title_en ..., category_de, category_en and so on. pretty easy.
now there will be some fields for html content where i have to store a combination of unordered image + text combinations. i do it like this right now :
<img>text<img><img>text<img><img>text<img>text<div>otherstuff</div>text<img>
so pretty random html elements no structure ...
so a user will have to copy this structure after creating it to another text-area for another language and translate it.
i dont like the idea to store the "structure" and the "double parts e.g. the images" twice . this would work for 2 languages - but what if its 10 languages.
is there an logic and easy way to separate the structure and how would you model that in a database ?
I think what your looking for is called as internationalisation and localisation.
For that you may not create any new column or any other tables in database. Even you can handle with language file. Since you told that yours is small project it will work fine.
You should really use any good library like https://github.com/Philipp15b/php-i18n which is having good attention in git hub.
Even I have a solution of using basic one.
NOTE : Since I wont be using any caching technique to save the
languages there may be performance issues. Please note I will recommend using any good library. Mine is just an idea for the sake of implementation. You can enhance based on it.
en.php
$language = array(
'Hello' => 'Hello!',
'HtmlText' => '<h1> HTML </h1>'
);
fr.php
$language = array(
'Hello' => 'Bonjor'
'HtmlText' => '<h1> HTML </h1>'
);
In your page now you can implement the following way
Eg:
Advice : Make sure you handle your HTML encoding while displaying.
/* Validate whether $_GET['lang'] is set or not.
Whether your havig any language of that specif or not
Then use the following way to implement
*/
URL : http://127.0.0.1/project/?lang=en
include_once $_GET['lang'].'php'
echo $language['Hello']; //Irrespective which ever language you use it will load
I mass produce very similar sites, meaning they all use the same basic components, pages and are all single industry specific. These are my low end deeply discounted site designs. None of these sites ever get more than 20-30 visitors a day, so any extra load on the server isn't an issue.
In the interest of time, being that they all use the same components, though they may be in different locations or in a different order I would like to write one definition file that can be included with every site, so I can just call the defined constant instead of writing out the code a couple hundred times every year on every site I build. Also for editing later purposes this would make my life MUCH easier.
the definition file would look similar to the following:
define('UPCONTACT','<h1>Contact Us</h1>');
define('ULCONTACT','Contact Us');
define('UPABOUTUS','<h1>About Us</h1>');
define('ULABOUTUS','About Us');
Obviously this is a very basic example but I think you get the idea.
So the question is what are the pros and cons of using define() in this manner?
It's pretty much ok. The disadvantage is that, given you are using constants, you can't override them for a single page or site.
Use an array instead:
config.php
return array(
'aboutus' => '<h1>About Us</h1>',
'contactus' => 'Contact Us'
);
include it like this in your site:
$config = include('config.php');
Then you can print it very easily
<?php echo $config['aboutus'] ?>
You can also change a value when you need it:
$config = include('config.php');
$config['aboutus'] = '<h1>About My Company</h1>';
This is probably your best option.
It has upsides and downsides.
The upsides involve that such way is quicker than loading settings from a database (and creating a database; and creating an abstraction layer, ...).
The downsides involve that such way is not customizable by the client. If they need a change, ensure beforehand the website is static and you will charge them by every change.
IMHO it is better to have some stuff as customizable by the client, and other stuff not. But there's no technical issue at all by using define() in that way (except perhaps allowed datatypes).
A better way to use a ini file or something like that.
(and easily editable from a smartphone if it's a recursive task for you :)
Look for a builtin php function, can make simplify your life
http://php.net/manual/fr/function.parse-ini-file.php
or if you would a more stronger and flexible system,
go for templating (looking for smarty, or self made regex templating)
Looking for my first regex function (loong years ago)
Quitting Smarty to do it manually
Note:
Using Constant does not provide you to dynamically modifying them
inline code, and are poor supported type (you cannot store an array without serialize for example)
I would suggest cascaded ini files:
$conf_dir = dirname(__FILE__);
$config = array_merge_recursive(
parse_ini_file($conf_dir.'base.ini'),
parse_ini_file($conf_dir.'client.ini')
);
The benefits are readability, inability of execution (I like to lock things down that can be), and you can track the base ini in git (or whatever you use) and not the client one. There are some downsides, but such is life. The just feel cleaner, but they are not faster than .php, to be sure.
And if you wanted to eliminate any redundant execution (listen, any "performance benefit" still has "benefit" in it), serialization:
<?php
define('CACHE_DIR', '/tmp/');
// where 'http' is a path part that directly follows the app root, and will always
// be below where this file is called from.
$ini_cache = CACHE_DIR.'config.ser';
if(!file_exists($ini_cache)) {
// Build your config in any way you wish.
$conf_dir = dirname(__FILE__);
$config = array_merge_recursive(
parse_ini_file($conf_dir.'base.ini'),
parse_ini_file($conf_dir.'client.ini')
);
// Store it serialized
file_put_contents($ini_cache, serialize($config));
} else {
$config = deserialize(file_get_contents($ini_cache));
}
You can get more creative with this, but essentially, this allows you to store/generate your configuration in any way you wish. If you wanted to not have to delete the serialized cache on every change, you could add an atime check:
<?php
define('CACHE_DIR', '/tmp/');
// where 'http' is a path part that directly follows the app root, and will always
// be below where this file is called from.
$ini_cache = CACHE_DIR.'config.ser';
$conf_dir = dirname(__FILE__);
$config = array();
if(file_exists($ini_cache)) {
$client_stat = stat($conf_dir.'client.ini');
$cache_stat = stat($ini_cache);
if($client_stat['atime'] < $cache_stat['atime']) {
$config = deserialize(file_get_contents($ini_cache));
}
}
if(empty($config)) {
// Build your config in any way you wish.
$config = array_merge_recursive(
parse_ini_file($conf_dir.'base.ini'),
parse_ini_file($conf_dir.'client.ini')
);
// Store it serialized
file_put_contents($ini_cache, serialize($config));
}
With either serialization method, you can use what ever $config generation scheme you prefer, and if you use PHP, you can even get real creative/complicated with it, and the cached hit to the page will be negligible.
I am developing a multi-langual website. Language variables (phrases/word translations) will be entered in a specific file (one different file for each language)
I wanted to know the best way to enter the phrases/word translations, should I use a normal array?
e.g
Filename = English.php
<?php
$translations = array();
$translations['phrase1'] = "this";
$translations['phrase2'] = "that";
..
?>
and in the template file
<?php
include("English.php");
echo $translations['phrase1'];
etc...
I am pretty new to PHP so I am just looking for the best way to do it.
Any suggestions?
Thank you for your help!
There are multiple of ways to do this, the two things that pop-off my head right now are:
1) Have a look at gettext & GNU gettext page. An example implementation of this to look at is Aur Website of ArchLinux. They their app support multiple languages & its all dynamic. user can can switch between languages easily. The source code is available here, study it & see how they did it.
2) Other option could be use a framework like cakephp, as most of these frameworks have translations support
Hope it somewhat helps
I have been looking online for a tutorial to build a template engine. I know there are many engines that exist, like smarty, twig, and pattemplate, that could do exactly what I want, but I am looking to learn how to build one. I started with a template engine that added strings to an array and then displayed the array. Since then I built one using eval() (see below).
<// Define links & folders
define("ROOT_HTTP", "http://" . $_SERVER['HTTP_HOST'] . "/preprocessor");
define("TEMPLATE", "/template");
// Get the template file
$template = file_get_contents("template/template.php");
// Replace
$template = str_replace("<x Title x>", displayTitle(), $template);
$template = str_replace("<x Menu x>", displayMenu(), $template);
$template = str_replace("<x Content x>", displayContent(), $template);
$result = #eval("?>" . $template . "<?");
function displayMenu(){
return "Link1<br />" .
"Link2<br />" .
"Link3<br />";
}
function displayTitle(){
return "Site Title <?php echo date(\"m-d-y\", time()); ?>";
}
function displayContent(){
return file_get_contents("content.php");
}
It works fairly well but its not what I am looking to achieve. I would like to build something that is like the Joomla template with tags like <jdoc:include type="component" />. I would also like it to be able to handle errors inline meaning that it will display the line number of an error or when I call echo "text" it displays text in the correct position inside the template.
How do I create something along those lines?
http://www.phptal.org/ sounds very similar and has good code organization. if extension of mentioned system does not suit the needs, it would at least work as good tutorial
First of all: Immediately forget the idea about using a TE with XML-like tags. Really, it may look nice on the first glance but only causes too much work in the end and is really limiting.
Secondly I obviously recommend you to use Twig. It is clean, fast, extensible and offers all the features you need.
And lastly: I have written a small tutorial how to write a simple but powerful TE in another Stackoverflow question. It is really simple but for smaller projects it may suffice.
I cannot agree with NikiC's point of view.
XML is, although an old syntax, very powerful and brings a lot of advantages -- one of which is its similitude with properly written HTML.
There is nothing limiting in using an XML-based template syntax.
Besides, although Twig is, indeed, an excellent and famous project, it still lacks from a really good separation paradigm. It is still too dangerous and too easy to make mistakes from within the template and cause damages to the application as a whole.
Finally, the best template engine -- just as the best MVC framework -- is the one you feel really comfortable with.
I recommend having a look at FigDice]1, which was inspired by PHPTal, but takes things a few steps further, with an exclusive approach by giving the Web Designer (integrator, html-ist, etc.) a central position with the project -- much more flexible than the Twig-like approach.
I would be happy to read some feedback.
Thanks
I am a PHP dev trying to start using HAML, using this implementation:
http://phphaml.sourceforge.net/
HAML looks awesome, but I don't understand if/how it supports partials (or includes, as they are called in the PHP world).
I would like to have a master template HAML file that then goes and loads up a bunch of partials for all the little pieces. (Then I can reuse those pieces in other templates too.)
In PHP or Ruby this would be really easy, is there any way to do this with HAML? thanks!
dylan
You could create a global render_haml_partial method by analogy with phpHaml's existing display_haml method that might look something like:
function render_haml_partial($sFilename, $aVariables = array(), $sTmp = true, $bGPSSC = false)
{
$sPath = realpath($sFilename);
$haml = new HamlParser(dirname($sPath), $sTmp);
$haml->append($GLOBALS);
if ($bGPSSC)
{
$haml->append($_GET);
$haml->append($_POST);
$haml->append($_SESSION);
$haml->append($_SERVER);
$haml->append($_COOKIE);
}
$haml->append($aVariables);
return $haml->fetch($sFilename);
}
This method could be placed in phpHaml's HamlParser.class.php file so it is available to all your templates.
The only difference between this and display_haml is that it invokes fetch instead of display at the end and returns the result so you can then insert it in-place into the invoking template.
You would then use it in your PHP/HAML templates as follows:
= render_haml_template("path to partial")
This would then be very similar to the Rails/HAML syntax:
= render :partial => 'path to partial'
Note that using display_haml directly does not have quite the same effect since it renders the template directly to the output instead of returning the result to the caller. Thus you could do the following:
- display_haml("path to partial")
But this doesn't capture the result of the render.
I'm guessing that somebody who cares enough about phpHaml might add such a render_haml_partial or something similar eventually - I might suggest it to the author some time.
Quite an old question, but I've updated the source code of phpHaml to reflect this new functionality!
Check out the commit #github
https://github.com/endorama/phphaml/commit/8d95d5ebff06275db8b14438e566c6e41ec91b7f