I'm developing a niche social networking site that is going multilingual. That means our current URL structure will soon need to start using translated words for slugs like the following:
www.example.com/home becomes www.example.com/inicio
www.example.com/profile becomes www.example.com/perfil
www.example.com/help becomes www.example.com/ayuda
And so on. My question is: what's the best way to support this in a PHP application? For incoming requests, I thought a dictionary like the following in my router.php file would suffice:
<?php
$request = explode("/", trim($_SERVER['REQUEST_URI'], "/"));
// Dictionaries of page slugs.
$slugs = array(
'es' => array(
'inicio' => 'home',
'perfil' => 'profile',
'ayuda' => 'help',
)
// additional languages can be added here
);
// Rewrite any incoming (foreign) requests
if ($host=="www.example.es") { // to be made programmatic
$lang = "es"; // pick up from locale constant rather being hard-coded
if (array_key_exists($request[0], $slugs[$lang])) {
$request[0] = $slugs[$lang][$request[0]];
}
}
...
Which basically takes URL segments and matches them against an English counter-part if it exists. If not, then it will proceed as normal and most likely cause a 404 as a controller doesn't exist for URL segment.
Although this words, I need it to be backwards-compatible too. For example, when building URLs in my application.
Naturally, as the application is only English at the moment these are just hard-coded. So say, when fetching a User object I do the following:
<?php
class User {
function __construct($id) {
// fetch user details
$this->profile_url = ROOT . "/profile/" . $this->username;
}
}
What is the best method to then replace instances of "/profile/" being hard-coded to getting the translated version, i.e. "/perfil/" in the Spanish site?
I could always be wrong, but here goes...
The standard way to achieve multilingual websites is to use i18n dictionary/template techniques in which you have a separate dictionary for each language, and in some cases different templates.
However, in such cases, I have never seen anybody change the language of their URL's. URL's map a request to files on the server disk (generally speaking), and there for shouldn't change based on language if you can avoid it.
It is common to prefix the 'path' section of your URL with the language you are requesting - ie:
http://foo.bar/en-us/foobar.html
To summarize:
I wouldn't worry about translating your URLs as it isn't a standard practice (atleast, not that I have seen). Simply prefix the URL 'path' with a language denotation such as in the URL above.
I have something similar in an application I'm developing.
Each page has a unique ID which is matched to a slug, page title, meta description and such for each language in a table.
As for the people saying it's not standard practice and not to bother with it I disagree as having nicely translated URLs can help your SEO in different languages.
Well, a common pattern I've seen for php is to create a php file for each language and initialize a large dictionary in which the keys are the same for all languages.
Have a session variable called language which can initially be 'en' for english (or whatever you prefer), and then include using command "include(language . '/main.php');" in which you have a folder called 'en' which contains all php files to include for translations. If main gets too large, you can subdivide and include whichever translation serves your needs (for example a /en/forum.php for forum translations and a /en/blob.php for front page translations).
It has the tremendous advantage of being flexible and allowing you to control the language simply by modifying one session variable. You can even do tricks like detect browser language settings and assign language according to that if it hasn't already been defined rather than simply making it english.
I was thinking about this, as I'm going down this path now. I was going to use a similar method, but not the same...
I was going to have language "include" files with all the strings of the site. So...
/languages/en.php
would have all the correct strings for the English language, and the other language files could be dropped in as new translations are done.
In the en.php file, I was going to put in fields like this
define('PageTitleWelcomeMessage', 'Welcome to Foo');
And then call that static variable anywhere in the site. The en language would be defined in their profile
I could then call that variable like so:
echo PageTitleWelcomeMessage;
Related
I am working on a site and the builders have used a mix of php and html for links. For example:
<li>Variable Speed Drives</li>
<li>Corrosion Resistant Baseplates</li>
and
<li>MP Repair</li>
<li>MTA Repair</li>
The php is referenced in another file in this way:
<?php
$pdf_link = "../pdf/";
$external_pdf_link = "../../pdf/";
$video_link = "../video/";
$external_video_link = "../../video/";
?>
My concern is not knowing the function of the php, other than it being a placeholder, and given that the links work both ways, I don't want to break something because I am clueless to its purpose.
In doing my due diligence researching, I ran across this post, which is close, but still no cigar, Add php variable inside echo statement as href link address?. All of the research seems to be about how rather than why. This is the site, and they only used it for the "Downloads" links: http://magnatexpumps.com/
Thank you...
B
There is no right way. They are just different.
Let's forget the PHP for a while. If you have this link in a page:
<a href='about.html'/>About</a>
What will happen? The browser will change the URL of the document. If you are at the root of the site like: "www.example.com", will redirect to "www.example.com/about.html". If you are in a URL like "www.example.com/news/index.html" will redirect you to "www.example.com/new/about". That's why sometimes it is useful to have a variable before, to force a full path URL.
Another case of URL variable interpolation is when you have different systems running in the same url. In this case, you will have to append the system name in order to get to where you want. If you don't know where your application will run if it will run on the doc root, or in a subfolder, use a variable to indicate the base path.
I'm using typo3 and realurl.
In my extension I generate some ID's (next and previous page) and everything works fine up to this point. An example link looks like:
/index.php?id=12
The link takes the visitor to the specific page, but this link is in the url as well. Of course I generate this linke exactly like this:
$GLOBALS['TSFE']->baseURL . "index.php?id=" . $banner->getPrevious();
So, it is exactly what i expected. But how can i turn this url into a seo-friendly URL?
Is there something like $realUrl->createUrlFromId()? :P
I checked the manual, looked in some forums, but 99% of the time it is something related to TypoScript, which I don't need (from my point of view) in this case.
Edit:
Here is the .htaccess:
http://pastebin.com/DBXjLYjp
Thank you in advance
RealURL hooks into several core methods to generate links, and manipulates the result to be a speaking URL. So, no, it does not offer an own method, but extends existing ones.
You don't use a link generation, but build it by yourself. RealURL therefore can not access your link.
The htaccess only converts speaking urls back into GET-params.
Use a method like pi_linkToPage, a link viewhelper, or a TypoScript typolink to generate a link.
$myLink1 = $this->pi_linkToPage('example', 42);
$myLink2 = $this->cObj->typolink('example', array(
'parameter' => 42,
));
I'm trying to figure out what the best way to go about rewriting urls to accommodate not only a directory structure, but appended actions for a menu for a site I'm building in PHP.
I have one page that dynamically loads content based on whatever "page" is being loaded. Includes are pulled based on what the page is. Right now that's tied to directories in my includes folder. So folder/page will include includes/folder/page.php.
If I have a structure like "root/page/action/param" that works fine as long as I say "whatever is in this place in the url is this." But I ran into trouble when I started adding folders that hold different levels of pages. If I explode page out to "folder/subfolder/page" then using placement to determine what is what goes out the window. I was thinking about using something like a hyphen as a delimiter to go "root/folder-subfolder1-subfolder2-page/action/param" so I can identify the page easily but I don't really like that option.
I also don't really like tying my includes directory structure to my urls but the only other way I would think to go about avoiding that would be to have an in-memory object to handle what exactly goes where. But I want to avoid that as I want the menu to be dynamic, based on an XML file that gets parsed and urls generated accordingly. I don't want the overhead of parsing the xml and not only generating URLs but also dynamically generating an in-memory object that has seemingly arbitrary rules.
Any suggestions?
PHPonTrax uses an implementation that I think would allow for this type of routing that you want, and it's open source so you could look at the code for some inspiration. (Note: I am not making any judgement as to the framework, I just have seen the code and think it might work for you).
Basically, you store your routes in an array and you provide some placeholder's as well so that you can have multiple possible controllers/actions/ids after a given path.
So if $routes[] is our array to hold everything, we could add:
$routes[0]['path'] = "foo/bar/:controller/:action";
$routes[0]['params'] = null;
$routes[1]['path'] = "baz/:action";
$routes[1]['params'] = array("controller"=>"blah");
$routes[2]['path'] = "catalog/:id";
$routes[2]['params'] = array("controller"=>"products", "action"=>"view");
$routes[3]['path'] = ":controller/:action/:id";
$routes[3]['params'] = null;
":controller", ":action", and ":id" are unique tokens that indicate what you are allowing a token to represent in the path. So "/baz/edit", "/baz/delete", "/baz/create", "/baz/funkify", etc are all valid provided controller "blah" has edit, delete, create, and funkify methods. If the path is "/catalog/1234", then '1234' is the id and it's a valid path if and only if you can find a product with id=1234. If your request is to "/products/dothis/12345", routes 0-2 don't match, but route 3 does, so you can then look for a controller file named "products", and provided it has a method named "dothis", then you can call "dothis(12345)". Obviously, if there's no "dothis" method, or '12345' can't be found, it's an invalid path and you can raise an exception. Note you need to provide a default route, and in this case it's $routes[3].
In your file structure, you can have:
/app
/controllers
/views
/etc, etc
Possible drawback is that in your rewrite, you send every request to one php script.
If this interests you: PHPonTrax. You will want to look at the router class and action_controller class (see the process_route() and recognize_route() methods).
Use Absolute Paths instead of relative in your menu html & scripts and you shouldn't have problems as it will always point to correct source.
Absolute Path Example (notice the /):
Home
Services
My Page
My Page 2
My old web site has an index.html page … nothing strange! Everything is fine.
The new web site has an english and a french version, so the new index is index.php?lang=eng…. That makes sense.
I don’t like to make a front page that will say “english” or “french”. But that’s not good for ranking or seo.
So the question is: How do I manage to get a default index.php with request (?lang=eng) to become the front page?
domain.com/en/index.php
domain.com/fr/index.php
Use url rewriting with regular expressions (mod_rewrite, ISAPI, whatever) to handle requests to relevant pages so
domain.com/en/index.php REWRITE TO domain.com/index.php?lang=en
domain.com/fr/index.php REWRITE TO domain.com/index.php?lang=fr
This way your pages are two seperate pages to search engines but handled via one gateway in code. I'm not a regex expert but it would be a very simple regex I would imagine
I'm not sure I understand the question. It seems to have two parts:
How to provide a default language of English:
$lang = empty($_GET['lang']) ? "eng" : $_GET['lang'];
Do you also have a problem of where to put the English/Francais links so search engines don't ding you? I wasn't aware of this problem.
It might also help to let us know if you're using a CMS, and if so which one.
Unless I'm misunderstanding the question, in index.php, when you check the language, put something like this:
$lang = #$_GET['lang'];
if ( empty($lang) ) $lang = 'eng';
Just put an argument in the php code that says :
if (lang == "") // haven't done php in a while so the syntax is probably wrong
{
lang = "eng";
}
In other words, if there isn't an argument on the lang variable, you can just set it to be eng automatically, and so the first page will default to English every time, unless told otherwise.
Just make the default english and offer an option on the index page to change to french? This, of course, depends on what language most of the visitors speak, which isn't all that hard to figure out with visitor logs.
I would use a neutral URL for entry, such as:
http://example.com/foo/bar
On this page I would do some language negotiation or simply ask the user for the prefered language. Then I can redirect to the language specific URL:
http://example.com/en/foo/bar
what do you think about that solution
<?php
$lang = $_GET['lang'];
if ( empty($lang) ) $lang = 'fra';
header( 'Location: http://acecrodeo.com/new/01-acec.php?lang='.$lang) ;
?>
I'm writing a basic crawler that simply caches pages with PHP.
All it does is use get_file_contents to get contents of a webpage and regex to get all the links out DESCRIPTION - at the moment it returns:
Array {
[url] => URL
[desc] => DESCRIPTION
}
The problem I'm having is figuring out the logic behind determining whether the page link is local or sussing out whether it may be in a completely different local directory.
It could be any number of combinations: i.e. href="../folder/folder2/blah/page.html" or href="google.com" or href="page.html" - the possibilities are endless.
What would be the correct algorithm to approach this? I don't want to lose any data that could be important.
First of all, regex and HTML don't mix. Use:
foreach(DOMDocument::loadHTML($source)->getElementsByTagName('a') as $a)
{
$a->getAttribute('href');
}
Links that may go outside your site start with protocol or //, i.e.
http://example.com
//example.com/
href="google.com" is link to a local file.
But if you want to create static copy of a site, why not just use wget?
Let's first consider the properties of local links.
These will either be:
relative with no scheme and no host, or
absolute with a scheme of 'http' or 'https' and a host that
matches the machine from which the
script is running
That's all the logic you'd need to identify if a link is local.
Use the parse_url function to separate out the different components of a URL to identify the scheme and host.
You would have to look for http:// in the href. Else, you could determine if it starts with ./ or any combination of "./". If you don't find a "/" then you would have to assume that its a file. Would you like a script for this?