Magento multilanguage - double change in language resuts in 404 (or how to change language within stores not views) - url

I have a problem with a magento installation. I used Magento ver. 1.5.0.1, community edition to develop this website http://cissmarket.com/.
The problem appears when I change the language from the EU version to French and after that to German. The change to french is ok, but when in the same page i change to German i receive a 404 error. Also this is generation 404 errors in the Google webmaster tools and when i try for example to take this link and paste it in the browser it gives me also a 404 error. I have there some 50 products and ~550 404 errors in Google Webmaster tools. I understand that the problem is from what I described.
Moreover I have a SEO problem since I have this page in french:
http://cissmarket.com/de/cartouches-refilables.html
And when I switch to the german version of the website it takes me to this link
http://cissmarket.com/de/cartouches-refilables.html?___from_store=fr (if i try now to switch to uk I will get the 404 mentioned above)
instead of going to this one:
http://cissmarket.com/de/nachfullpatronen.html
Already checked this 404 error when switching between stores when in a category on magento but it does not relate to my problem.
About settings:
I use the caching service and also I did index all the content.
The product or category I am trying to access is available and set active for all the languages.
System > General > Web > URL options > Add Store Code to Urls is set
to yes.
System > General > Web > Search Engines Optimization > Use Web Server
Rewrites is set to yes.
No other changes has been made to the .htaccess file except for the
ones that the system itself made.
So to conclude: the problem is the 404 given by 2 succesive changes of the language and the bad url address when I switch from one page to another.
Any suggestions would be appreciated.
UPDATE: tried this http://www.activo.com/how-to-avoid-the-___from_store-query-parameter-when-switching-store-views-in-magento but it results in a 404 at the first language change
Edit #1:
Found the problem: file languages.phtml contained this code <?php echo str_replace ("/fr/","/de/",$_lang->getCurrentUrl()); ?> and actually did replace only the language code and not the whole url according to the corresponding translation.
So applied to this
http://cissmarket.com/fr/cartouches-refilables.html
it will return
http://cissmarket.com/de/cartouches-refilables.html
So does anyone know how to get the corresponding URL of the current page for the other languages available in the store?
Edit #2 (using #Vinai solution):
It works on the product pages but not on the category yet.

There is no such thing in the native Magento as far as I know.
That said, you can use the following code to get the current page URL for each store.
$resource = Mage::getSingleton('core/resource');
$requestPath = Mage::getSingleton('core/url')->escape(
trim(Mage::app()->getRequest()->getRequestString(), '/')
);
$select = $resource->getConnection('default_read')->select()
->from(array('c' => $resource->getTableName('core/url_rewrite')), '')
->where('c.request_path=?', $requestPath)
->where('c.store_id=?', Mage::app()->getStore()->getId())
->joinInner(
array('t' => $resource->getTableName('core/url_rewrite')),
"t.category_id=c.category_id AND t.product_id=c.product_id AND t.id_path=c.id_path",
array('t.store_id', 't.request_path')
);
$storeUrls = (array) $resource->getConnection('default_read')
->fetchPairs($select);
This will give you an array with the array key being the store IDs and the array values being the request path after the Magento base URL, e.g. assuming your French store has the ID 1 and the German one has the ID 2, you would get:
Array
(
[1] => cartouches-refilables.html
[2] => nachfullpatronen.html
)
Then, in the foreach loop where the URL for each store is output, use
<?php $url = isset($storeUrls[$_lang->getId()]) ? $_lang->getUrl($storeUrls[$_lang->getId()]) : $_lang->getCurrentUrl() ?>
The call to $_lang->getUrl() will add the base URL, so you will get the full URL for each store (e.g. http://cissmarket.com/de/nachfullpatronen.html). If no store view value is found in the core_url_rewrite table it will revert to the default behaviour.
You still need the ___store=fr query parameter because otherwise Magento will think you are trying to access the new path in the context of the old store. Luckily, the getUrl() call an the store model adds that for you automatically.
The code querying the database can be anywhere of course (since its PHP), even in the template, but please don't put it there. The correct place to have code that access the database is a resource model. I suggest you create a resource model and put it in a method there.

I've found an ugly patch until a better approach comes up.
In the admin section, i've added the following javascript inside the wysiwyg in CMS > PAGES > (My 404 pages) (at the beginning of the wysiwyg) :
<script type="text/javascript" language="javascript">// <![CDATA[
var lang = "en";
var rooturl = "{{config path="web/unsecure/base_url"}}"
var url = document.location.href;
if(!(url.match("/"+lang+"/")))
{
var newUrl = url.replace(rooturl , rooturl+lang+"/" );
window.location.href = newUrl;
}
// ]]></script>
(Note: you need to do this for all of your translated 404 pages. In each 404 page you need to modify lang="en" for your storeview url value)
Because the wysiwyg (tiny_mce) does not allow javascript to be threated, you'll have to modify js/mage/adminhtml/wysiwyg/tinymce/setup.js. Add the following code under line 97 (under "var settings = "):
extended_valid_elements : 'script[language|type|src]',

For Magento 1.7.0.2 and 1.8.0.0 this is the bugfix:
Starting from line 251 of /app/code/core/Mage/Core/Model/Url/Rewrite.php
:
Mage::app()->getCookie()->set(Mage_Core_Model_Store::COOKIE_NAME, $currentStore->getCode(), true);
// endur 02-03-2013 fix for missed store code
// $targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
if (Mage::getStoreConfig('web/url/use_store') && $storeCode = Mage::app()->getStore()>getCode()) {
$targetUrl = $request->getBaseUrl(). '/' . $storeCode . '/' .$this->getRequestPath();
} else {
$targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
}
// endur 02-03-2013 end
Make sure to create a custom copy of the file in:
/app/code/local/Mage/Core/Model/Url/Rewrite.php or:
/app/code/local/YourTheme/Mage/Core/Model/Url/Rewrite.php
source:

It looks like a bug in Magento 1.7. Here is a hack that worked for me.
It should work for a two language store with store code in URL
in var/www/html/shop1/app/code/core/Mage/Core/Model/Url/Rewrite.php
remove this line
// $targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
and add these:
$storecode = Mage::app()->getStore()->getCode();
if ($storecode='en')
{
$targetUrl = $request->getBaseUrl(). '/'.$storecode.'/' . $this->getRequestPath();
}
else
{
$targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
}

Here a another solution for this problem. Just add this code after "$this->load($pathInfo, 'request_path');" in app/code/core/Mage/Core/Model/Url/Rewrite.php:
if (!$this->getId() && !isset($_GET['___from_store'])) {
$db = Mage::getSingleton('core/resource')->getConnection('default_read');
$result = $db->query('select store_id from core_url_rewrite WHERE request_path = "' . $pathInfo . '"');
if ($result) {
$storeIds = array();
if($row = $result->fetch(PDO::FETCH_ASSOC)) {
$storeId = $row['store_id'];
$storeCode = Mage::app()->getStore($storeId)->getCode();
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://" . $_SERVER['HTTP_HOST'] . "/" . $pathInfo . "?___store=" . $storeCode);
exit();
}
}
}

guys. For this error there is magento module. It have rewrite 2 models
http://www.magentocommerce.com/magento-connect/fix-404-error-in-language-switching.html

Related

How to compile custom format ini file with redirects?

I'm working with an application that has 3 ini files in a somewhat irritating custom format. I'm trying to compile these into a 'standard' ini file.
I'm hoping for some inspiration in the form of pseudocode to help me code some sort of 'compiler'.
Here's an example of one of these ini files. The less than/greater than indicates a redirect to another section in the file. These redirects could be recursive.. i.e. one redirect then redirects to another. It could also mean a redirect to an external file (3 values are present in that case). Comments start with a # symbol
[PrimaryServer]
name = DEMO1
baseUrl = http://demo1.awesome.com
[SecondaryServer]
name = DEMO2
baseUrl = http://demo2.awesome.com
[LoginUrl]
# This is a standard redirect
baseLoginUrl = <PrimaryServer:baseUrl>
# This is a redirect appended with extra information
fullLoginUrl = <PrimaryServer:baseUrl>/login.php
# Here's a redirect that points to another redirect
enableSSL = <SSLConfiguration:enableSSL>
# This is a key that has mutliple comma-separated values, some of which are redirects.
serverNames = <PrimaryServer:name>,<SecondaryServer:name>,AdditionalRandomServerName
# This one is particularly nasty. It's a redirect to another file...
authenticationMechanism = <Authenication.ini:Mechanisms:PrimaryMechanism>
[SSLConfiguration]
enableSSL = <SSLCertificates:isCertificateInstalled>
[SSLCertificates]
isCertificateInstalled = true
Here's an example of what I'm trying to achieve. I've removed the comments for readability.
[PrimaryServer]
name = DEMO1
baseUrl = http://demo1.awesome.com
[SecondaryServer]
name = DEMO2
baseUrl = http://demo2.awesome.com
[LoginUrl]
baseLoginUrl = http://demo1.awesome.com
fullLoginUrl = http://demo1.awesome.com/login.php
enableSSL = true
serverNames = DEMO1,DEMO2,AdditionalRandomServerName
authenticationMechanism = valueFromExternalFile
[SSLConfiguration]
enableSSL = <SSLCertificates:isCertificateInstalled>
[SSLCertificates]
isCertificateInstalled = true
I'm looking at using ini4j (Java) to achieve this, but am by no means fixed on using that language.
My main questions are:
1) How can I handle the recursive redirects
2) How am I best to handle the redirects that have an additional string, e.g. serverNames
3) Bonus points for any suggestions about how to handle the external redirects. No big deal if that part isn't working just yet.
So far, I'm able to parse and tidy up the file, but I'm struggling with these redirects.
Once again, I'm only hoping for pseudocode. Perhaps I need more coffee, but I'm really puzzled by this one.
Thanks in advance for any suggestions.

dart HTMLrequest default to index.html does not work

I have a simple Dart HTTPServer running which serves requests by virDir.serveRequest(request); which works for the URL 192.168.1.200:8080/index.html but serves a 404 Not Found if I use 192.168.1.200:8080 or 192.168.1.200:8080/. I, probably naively, though that the default was automatic. BTW this is all new to me.
I didn't notice any default settings in HTMLServer, how is this accomplished?
(edit)
I've been able to detect the use using the default and compute the correct file name but don't understand how to deliver it to the browser:
_processRequest(newPath, request) { // new path is index.html
File file = new File(newPath);
file.exists().then((found) {
if(found) {
file.openRead().pipe(request.response); // probably dies here
}
else {
_send404(request.response);
}
});
}
[edit]
Still unable to serve the index.html file. I've tried using VirtualDirector.serveFile() but can't make it work when I try to handle the default index.html file. I've been attempting to follow an example.
final HTTP_ROOT_PATH = Platform.script.resolve('../web').toFilePath();
final virDir = new VirtualDirectory(HTTP_ROOT_PATH)
..jailRoot = false // process links will work
..followLinks = true
..allowDirectoryListing = true;
var dir = new Directory(virDir.root);
var indexUri = new Uri.file(dir.path).resolve('/index.html');
virDir.serveFile(new File(indexUri.toFilePath()), request);
When I run this and print indexUri.toFilePath() the output is '/index.html'
My code is in /srv/fireimager/bin and /srv/fireimager/web with the latter the virtual directory root. When I detect that the user has not specified /index.html in the url it doesn't work, there's no error emitted, and the javascript console shows nothing so nothing is served to the browser.
I obviously don't understand how to use VirtualDirectly.serveFiler.
Your default page or index.html is not assumed by your browser but by the server.
What you will want to do is check to see what your request ends with. In my server, I check to see if it ends with a "/". If it does end with a "/", I open and send my default page.
Also, you will want to make sure you check your request to make sure it's not trying to access areas it it not suppose to. Check for ".." in your path segments. If you have any, you probably want to kill the connection.

How can I find the current language in a Laravel view?

I'm using the Laravel Lang class for localization of my web app. I've added two languages to the languages array in application/config/application.php. This changes the default language it uses for localization to whatever the first part of the URI indicates (e.g. bla.com/en/bla and bla.com/co/bla). Now I need to be able to check what the current default language is in my view. However, the Lang class provides no way of checking this as far as I've been able to figure out, as the Lang::$language variable is protected. Is there any way of checking this apart from manually parsing the URI?
The cleanest way to know the current language of your website in Laravel appears to be :
Lang::locale();
https://laravel.com/api/5.8/Illuminate/Translation/Translator.html#method_locale
It's different than this command that will return the default language of your website :
Config::get('app.locale');
An alternative, a bit shorter way could be using something like this:
app()->getLocale()
The advantage of this is that IDEs such as PHPStorm recognize this function and can help you develop much faster.
BenjaminRH's answer is very good, and his suggested approach works perfectly. I've improved the snippet a bit. Now it detects the browser language and checks if that language is supported according to the application's config file.
It's a quick hack, but it works on my app. Note that the application language is also set now. Feel free to use ore improve it.
Route::filter('before', function()
{
// current uri language ($lang_uri)
$lang_uri = URI::segment(1);
// Set default session language if none is set
if(!Session::has('language'))
{
// use lang in uri, if provided
if(in_array($lang_uri, Config::get('application.languages')))
{
$lang = $lang_uri;
}
// detect browser language
elseif(isset(Request::server('http_accept_language')))
{
$headerlang = substr(Request::server('http_accept_language'), 0, 2);
if(in_array($headerlang, Config::get('application.languages')))
{
// browser lang is supported, use it
$lang = $headerlang;
}
// use default application lang
else
{
$lang = Config::get('application.language');
}
}
// no lang in uri nor in browser. use default
else
{
// use default application lang
$lang = Config::get('application.language');
}
// set application language for that user
Session::put('language', $lang);
Config::set('application.language', $lang);
}
// session is available
else
{
// set application to session lang
Config::set('application.language', Session::get('language'));
}
// prefix is missing? add it
if(!in_array($lang_uri, Config::get('application.languages')))
{
return Redirect::to(URI::current());
}
// a valid prefix is there, but not the correct lang? change app lang
elseif(in_array($lang_uri, Config::get('application.languages')) AND $lang_uri != Config::get('application.language'))
{
Session::put('language', $lang_uri);
Config::set('application.language', $lang_uri);
}
});
In the newer Laravel versions, you can get the current language with:
Config::get('app.locale');
This would work fine
lang="{{ app()->getLocale() }}"
I've figured out a solution to the language problem (thanks to nickstr on the IRC and the accepted answer to this question). It involves storing the current language as a session variable, which is updated when the language uri segment is changed.
Route::filter('before', function()
{
// Do stuff before every request to your application...
// Default language ($lang) & current uri language ($lang_uri)
$lang = 'he';
$lang_uri = URI::segment(1);
// Set default session language if none is set
if(!Session::has('language'))
{
Session::put('language', $lang);
}
// Route language path if needed
if($lang_uri !== 'en' && $lang_uri !== 'he')
{
Return Redirect::to($lang.'/'.URI::current());
}
// Set session language to uri
elseif($lang_uri !== Session::get('language'))
{
Session::put('language', $lang_uri);
}
});
This might help.
Config::get('application.language')
You can use
https://github.com/mcamara/laravel-localization
Laravel Localization uses the URL given for the request. In order to achieve this purpose, a group should be added into the routes.php file. It will filter all pages that must be localized.
// app/routes.php
Route::group(array('prefix' => LaravelLocalization::setLanguage()), function()
{
/** ADD ALL LOCALIZED ROUTES INSIDE THIS GROUP **/
Route::get('/', function()
{
return View::make('hello');
});
Route::get('test',function(){
return View::make('test');
});
});
/** OTHER PAGES THAT SHOULD NOT BE LOCALIZED **/
Once this group is added to the routes file, an user can access to all languages added into the 'languagesAllowed' ('en' and 'es' for default, look at the config section to change that option). For example, an user can now access to two different languages, using the following addresses:
http://laravel.com/en
http://laravel.com/es
http://laravel.com
I use App::getLocale() which is probably the most supported way as the App::setLocale('EN') method is used in the documentation.
You can use this method everywhere. If it throughs an error somewhere, you can use \App::... to make it work.
I'm using Laravel 5.0.
Your can get current language in laravel blade by:
{{Lang::locale()}}
The Lang class is specifically for outputting the correct language and as you say manages the language internally.
Looking through the API there is no method to help you directly with this and parsing the URI to get the language would seem the appropriate course of action.
You can always just do this to retrieve the language string in the URI:
$language = URI::segment(1);
Examining Laravel Requests

Add parameters to the URL (redirect) via a Greasemonkey/Tampermonkey/Userscript

I'd like to write a Greasemonkey/userscript that automatically adds .compact to URLs starting with https://pay.reddit.com/ so It automatically redirects me to the mobile version.
I've been looking at similar userscripts, particularly this one: https://userscripts.org/scripts/review/112568 trying to figure out how to edit the replacement pattern, but I lack skills in this domain.
How do I write a Greasemonkey script that redirects me from https://pay.reddit.com/* to https://pay.reddit.com/*.compact ?
Thanks
The script should do these things:
Detect if the current URL is already to the compact site.
Load the compact version of the page if necessary.
Beware of "anchor" URLS (they end with "fragments" or "hashes" (#...) ) and account for them.
Keep the unwanted pages out of the browser history so that the back button works well. Only .compact URL's will be remembered.
By running at document-start, the script can give better performance in this case.
To that end, this script works:
// ==UserScript==
// #name _Reddit, ensure compact site is used
// #match *://*.reddit.com/*
// #run-at document-start
// #grant none
// ==/UserScript==
var oldUrlPath = window.location.pathname;
/*--- Test that ".compact" is at end of URL, excepting any "hashes"
or searches.
*/
if ( ! /\.compact$/.test (oldUrlPath) ) {
var newURL = window.location.protocol + "//"
+ window.location.host
+ oldUrlPath + ".compact"
+ window.location.search
+ window.location.hash
;
/*-- replace() puts the good page in the history instead of the
bad page.
*/
window.location.replace (newURL);
}
The example script you showed is using a regex to manipulate the window's location:
replace(/^https?:\/\/(www\.)?twitter.com/, 'https://mobile.twitter.com');
Unsurprisingly, this replaces https://www.twitter.com and http://twitter.com etc. with https://mobile.twitter.com.
Your situation is slightly different, because you want to append a string to your url if it matches some regex. Try:
var url = window.location.href;
var redditPattern = /^https:\/\/pay.reddit.com\/.*/;
// Edit: To prevent multiple redirects:
var compactPattern = /\.compact/;
if (redditPattern.test(url)
&& !compactPattern.test(url)) {
window.location.href = url + '.compact';
}
See: http://jsfiddle.net/RichardTowers/4VjdZ/3 for test case.

magento display request url

i wanted to display the module,controller,method being called
i thought that the cms module found in the
app\code\core\Mage\cms\
calls the IndexController.php and uses the IndexAction method .since it is the default page url.
but when I tried to echo out something inside the IndexAction method .nothing comes out. I even tried to call it manually and it still redirects to the home page.
localhost/magento/index.php/cms/index/index/
am i doing it right?
how can i display the request url being called in magento?
I was looking for this also, here's how to do it:
echo Mage::helper('core/url')->getCurrentUrl();
Hi you could try to output the following
<?php
echo Mage::app()->getRequest()->getModuleName();
echo Mage::app()->getRequest()->getControllerName();
echo Mage::app()->getRequest()->getActionName();
?>
Not tested but maybe you can do something like this
<?php
echo Mage::app()->getRequest()->getRequestUri();
?>
Hope this helps
greetings
I needed the URL segments, so I used this:
function getUrlSegment($i) {
$_baseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
$_currentUrl = Mage::helper('core/url')->getCurrentUrl();
$_path = str_replace($_baseUrl, '', $_currentUrl);
$_segments = explode('/', rtrim($_path, '/'));
return $_segments[$i];
}
// Would get 'store' if URL: http://example.com/store/product/123
$root = getUrlSegment(1);
You might be getting 'headers already sent' warnings in your log files using an echo in the controller. Instead of using echo use Mage::log, e.g.
Mage::log('My request url is: '.$requestUrl);
The log line should appear in the /var/logs/system.log file.
The route cms/index/index is only ever used for the home page. Other standard pages like "no-route" and "enable-cookies" are optionally handled by specific actions on the IndexController. The remaining pages are handled by Mage_Cms_PageController::viewAction() instead. Try the path cms/page/view/id/customer-service to see. The parameter is id and so the next term customer-service is the page identifier which you set in the admin as "URL Key".

Resources