redirect root url according to locale in Zend - url

Working in ZF: Is it possible to change the base or root url on the www.example.com to www.example.com/$language/home, thus depending on the (browser) locale of the users browser?
Example; If a guest manually types www.example.com I would like to change the url automatically to a url with locale: www.example.com/en/home for guests in en_GB region or www.example.fr/home for guests in fr_FR region.
From the root-url I have all the menu-urls and content locale aware. Clicking a link to a menu item in the url the lang is automatically added after the root. The content on the root url is locale aware too using translate, so english for en_GB en french for fr_FR, etc.
Still missing though I would like to have the root url change to locale aware right from the start of the visit to the application if only the root is entered.
I guess something like
root :to => redirect("/prepayments")
in Rails 3 from what I understand from this Q&A on this forum
I have tried and implemented controller action helpers, redirects, etc. etc. for as far as I could find on this forum, but they all don't offer the solution.
A redirect in htaccess is not possible I think since I first need to get the locale from the browser. Since I don't know this the redirect is dynamic and I cannot set a redirect in htaccess.
I woud appreciate any suggestions?

Since I don't know what version of Zend you're using I am posting this for Zend 1.1x. One thing you could do is "catch" the request before it is dispatched, get the Accept-Language header and based on the user's preferences there set the locale or redirect the user to a URL you like. One way to do this is in the FrontController's preDispatch() method.
Keep in mind that:
You will need to check if all browsers send this through
This header string must be parsed careful
Because of the way it is defined:
Accept-Language en,bg;q=0.7,en-us;q=0.3
Also users may and often do set language preferences to a foreign language so this header on its own may not be enough.
The best way to do this in a OOP way is to wrap this functionality in a ZendPlugin.
Attach it in your bootstrap:
protected function _initLocaleHandlerControllerPlugin() {
$frontController = Zend_Controller_Front::getInstance();
$plugin = new App_Controller_Plugin_LocaleHandler();
$frontController->registerPlugin($plugin);
}
Now in this plugin redefine the preDispatch() callback:
public function preDispatch(Zend_Controller_Request_Http $request) {
$acceptLang = $request->getHeader('Accept-Language');
//Parse string and get language
//After parsing set the appropriate locale in `Zend_Locale`
//redirect the user/dispatch the request?
//THIS IS JUST AN EXAMPLE:
$request->setModuleName('home')
->setControllerName('registration')
->setDispatched(true);
}
Zend 1.x doesn't seem to have a built in class for this, Zend 2 does have the "Zend\Http\Header\AcceptLanguage" class.

I finally found the next solution on my question with a little help from Florent in Zend Framework: Redirect from action helper:
In my Language Plugin I added
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{...some code handling translate...
$url = $request->getRequestUri();
if ($url === '/') {
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
$redirector->gotoUrl($lang.'/home');
}
The routes I have them in a routes.ini so $lang.'/home' is routed to the indexController and indexAction of the Default module.

Related

Implementing a single module controller while leaving the controller out of the URL

I'd like to have one module controller implement the different action methods, but I don't want the URLs to come out like
www.example.com/module/index/action1
www.example.com/module/index/action2
www.example.com/module/index/action3
where /index/ takes us to the "IndexController". To have the URLs like I want
www.example.com/module/action1
www.example.com/module/action2
www.example.com/module/action3
I would need to create a controller class for every action method. What is the best way to get the URLs I want with the different action methods in one nice class/file/controller? I was wondering if there was a way besides URL rewrites. If not, could you point me to a good URL rewriting tutorial for Magento?
There is no real reason to violate Magento reuter/controller/action scheme. For any deviation they created the URL rewrites functional.
You can create Url rewrite even omitting the module part. Creating URL rewrites is really simple, I don't think you need tutorial for that, just open admin panel, go to Catalog->Url Rewrites Management. Click on create new rewrite, choose Custom type, add the desired uri part to Request Path (module/action), and the actual uri to the Target Path (module/controller/action).
If you don't want to do an URL rewrite at the web server, you can also do, essentially, an URL rewrite inside Magento's code. For example, you can override the function Match within Mage_Core_Controller_Varien_Router_Standard like so:
/* after getting the controller name and action name... */
if ((strcmp($module, 'myModuleName') == 0) && (strcmp($action, 'index') == 0)) {
$action = $controller;
$controller = 'index';
}
/* before checking if this place should be secure and instantiate controller class
I think URL rewrite at the web server will be cleaner and more manageable, though.
If you are using Magento's URL rewrite, you'll probably need to specify a rule for every action, such as:
Type: custom
Request Path: myModuleName/hello
Target Path: myModuleName/index/hello
You can specify these URL rewrite rules in the admin, under Catalog > URL Rewrite Management

Localized URLs in Play 2.0?

Yesterday we had a Play 2.0 presentation at our local JUG but we couldn't figure out whether it is possible to have localized URLs (for SEO purposes).
For example /help, /hilfe etc should point to the same controller but the template should be rendered with different language content.
Is there any way to do this in Play 2.0?
I like your question, because it was creative at least for me :) Check this approach it works for me:
conf/routes:
GET /help controllers.Application.helpIndex(lang = "en")
GET /hilfe controllers.Application.helpIndex(lang = "de")
GET /help/:id controllers.Application.helpTopic(lang = "en", id: Long)
GET /hilfe/:id controllers.Application.helpTopic(lang = "de", id: Long)
controllers/Application.java:
public static Result helpIndex(String lang) {
return ok("Display help's index in " + lang.toUpperCase());
}
public static Result helpTopic(String lang, Long id) {
return ok("Display details of help topic no " + id + " in " + lang.toUpperCase());
}
views/someView.scala.html:
Help index<br/>
Hilfe index<br/>
Help topic no 12<br/>
Hilfe topic no 12
(This is different approach than in previous answer, therefore added as separate one)
You can also create some kind of mapping table in DB where you can store full paths to records with different params:
urlpath record_id lang
/help/some-topic 12 en
/hilfe/ein-topic 12 de
than in conf/routes file you need to use rule allowing you to use Dynamic parts spanning several / (see routing doc) ie:
GET /:topic controller.Application.customDbRouter(topic:String)
You can also mix both - standard routing mechanismus with custom one by placing above rule at the end of your conf/routes file if no 'static' rule will be available, then it will try to find it in mapping table or will return notFound() Result.
You use from GlobalSettings.onHandlerNotFound() and check if the is a translated version of the url. Then you can make a redirect. However this ends with urls in default language.
More cleaner would be to use the GlobalSettings.onRouteRequest where you can implement your own logic to get the handler.
Furthermore you can create your own router. There was a discussion about it at google-groups with a scala solution.
It was possible in Play 1.2.x, not in 2.x as far as I know. I mean, it's not possible without duplicating the mappings in your file, adding one for EN, one for DE, etc.
A simpler alternative for SEO may be to "fake" the urls in your Sitemaps file.
So your Routes file has
GET /action/:param/:seo-string Controller.methodAction(param)
so seo-string will be ignored in processing, and you generate several links on your Sitemaps file:
/action/1/english-text
/action/1/german-text
This would set the search engines. For users, so they see the url in the right language, you could change the URL using HTML 5 history.
It's extra work, but if you really want it...

struts2 localization by embedding the locale code in the action name rather than by using ...?request_locale=<locale_code>

hi all,
i want to make localization feature in a website written in struts 2. as far as i know, the standard way of doing so is using get in the following manner:
http://.../namespace/action_name?request_locale=<locale code>
however, my boss doesn't like such hairy url. instead, i'm required to write it in the following manner:
http://.../namespace/a_param/<locale code>/another_param...
i tried to change the action mapping in my struts.xml into something like
<action name="*/*..." ... >
<param name="locale">{2}</param>
...
</action>
it doesn't work
after i changed it into
<action name="*/*..." ...>
<param name="request_locale">{2}</param>
...
</action>
it doesn't work either T_T
by the way, i know there is trick of putting ActionContext.getContext().setLocale(new Locale(...)); in action which basically change the locale for that instance. however, it seems that the effect will only be transient (in contrast, i18n saves the chosen locale in session, which basically makes it quite persistent.
so, how to change the locale by embedding the locale code in the url?
Your help is highly appreciated =D
I have not done much with locals but i18n should automatically determine the correct local from the browser via the headers, there is no need for anything to be in the url. As long as there is a language bundle for the particular locale it will try to pull properties from that file.
This page shows an example of using basic i18n (only looked at it for a moment, personally I always start at http://struts.apache.org/2.x/ but the tutorial/guides are a bit dry.
Why do you need to refer to anything in the url at all concerning language? Personally if the user did want to override the default locale I would provide some form of control (menu) to do so. Then I would set a variable in session then I would create an interceptor which would call setLocale on the action using the local parameter on the session (if there is a value set of course). This way there would not be any need to embed parameters into individual pages and the local is out of the url all together.
There is a way to do what you want with the url... Something to do with conventions and slashes in allowing slashes in the action name I think. I'll post back if I remember. But I think the above is generally a better approach anyways.
Edit: Taking into consideration what you are trying to accomplish I can see two very different solutions.
1) You can use a proxy, the incoming URL www.example.com/en/ and www.example.com/fr/ can be mapped to different web applications or even the same web application but the url is re-written into a form that suites your application. Tools that can do this include: iptables, apache mod_rewrite, squid... and a multitude of others. This type of solution is more valuable if you handle multiple ip addressses/urls/applications on one server.
2) You can set the struts2 property struts.enable.SlashesInActionNames then using wildcards you can do something like:
<action name="*/*">
<result>/WEB-INF/content/{1}/{2}.jsp</result>
<action>
You can also pass parameters to actions each asterisk found in the action name becomes {1}, {2}, etc. It sounds like you might need this feature. If someone else knows it escapes me at the moment how you would capture parts of the url like this with struts2-conventions-plugin so the action can make use of them I would find that interesting.
#Quaternion
basically the intention is that, the website has several national "sub-website". based on user's ip address, he/she will be redirected to the national "sub-website". it's like when you open www.google.com, you may be redirected to www.google.com.country_domain.
each national "sub-website" has several languages, with 1 default language. it's just like when you open google israel website, by default you will see a website written in hebrew language, although you can override this default choice by choosing it to be in english.
in my planned website, following isreal website and hebrew language example, it is supposed to be like this:
the user is in israel
he is opening www.abcdef.com
the server is recognizing that the client is in israel. there are 3 languages can be chosen for the israel "sub-website": hebrew, arabian, english. the default one is hebrew, but client can override this choice
the user is then redirected to www.abcdef.com/il/he ("il" stands for israel country and "he" stands for hebrew language)
but the user is apparently a british tourist with no knowledge on hebrew or arabian language. so he/she chose english language
he/she will be redirected to www.abcdef.com/il/en ("en" stands for english language)
the next time that client opens www.abcdef.com in israel again (assuming the cookies & sessions are still around), he/she will be redirected to www.abcdef.com/il/en
thx fr your help =D
Definitely I would leave the responsibility to handle the Locale to an interceptor.
Here is a tutorial to Create an Interceptor.
This interceptor can be placed in a common stack shared by all (or most of) incoming requests and it will assign the locale
ActionContext.getContext().setLocale(locale);
with the proper logic that could take into account:
query-string parameters
stored user preferences
cookies
session
browser preferences (are in the request)

Codeigniter _remap function

Please help I want to use first URI segment into my CodeIgniter website.
Like when I open these url they opens my profile:
http://www.facebook.com/buddyforever
or
http://www.myspace.com/zarpio
How can I do this with CodeIgniter? I checked _remap function but first coming controller how to hide controller?
You can do this using the URL routing of codeigniter...
If you want your URL to be http://www.mydomain.com/zarpio and you want it to refer to your_controller, then do the following.
/config/routes.php
$route['(.*)'] = "your_controller/$1"; // Now, `zarpio` will be passed to `your_controller`
You can access it in your controller like this...
$my_name = $this->uri->rsegment(2);
However I do not suggest this way of configuring URLs. A better way would be...
$route['users/(.*)'] = "your_controller/$1";
This way, you're just renaming your controller name your_controller to users.
If you want to access profile of a user, you can do it like this...
$route['users/profile/(.*)'] = "another_controller/method/$1";
$route['users/(.*)'] = "your_controller/$1";
Consider the order of routing. Since you wrote users/(.*) in your route, it will match users/zarpio as well as users/profile/zarpio, and route both of them to your_controller/$1, which in the case of profile will give you a 404 page not found error. That is why you need to write users/profile/(.*) before users/(.*) in your routing configuration.
More information in codeigniter URI class documentation

Grails how to change the current locale

How can I change the current locale ?
I tried to put controller/action?lang=de but my locale is still en_US
I tried to override the value using this piece of code:
def key = "org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER"
def localeResolver = request.getAttribute(key)
localeResolver.setLocale(request, response, new Locale("de","DE"))
Nothing changed.
I tried to override the value using this piece of code:
import org.springframework.web.servlet.support.RequestContextUtils as RCU;
RCU.getLocaleResolver(request).setLocale(request, response, new Locale("de","DE"))
And... nothing happened. i still got my locale set to en_US.
Any idea to change the locale ?
According to the chapter 10. Internationalization of the Grails documentation, Grails supports i18n out of the box and you should indeed be able to change the locale using the lang parameter:
By default the user locale is detected
from the incoming Accept-Language
header. However, you can provide users
the capability to switch locales by
simply passing a parameter called lang
to Grails as a request parameter:
/book/list?lang=de
Grails will automatically switch the
user locale and store it in a cookie
so subsequent requests will have the
new header.
But sometimes you may want to preset the default language because not all your applications will be in english. To do this, all you have to do is to set your localeResolver in your resources.groovy spring configuration file as shown below:
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("de","DE")
java.util.Locale.setDefault(defaultLocale)
}
}
Now, without more details, I can't say why using the lang parameter isn't working in your case. Just in case, how do you know that the locale is still en_US?.
As far as I understand the way you are checking the locale "request.locale" is wrong, it gives the locale of browser, not the locale of grails applciation.
You should use "LocaleContextHolder.locale".
In 2.0.3 it changes the locale by simply passing parameter lang=someLocale.
Do you try to change locale in application root url (eg. http://localhost:8080/myapp/?lang=de)?
In Grails basic setup trying to change locale in application root url does not work. Grails change locale in localChangeInterceptor which is called before all controllers are called. When you access application root url, no controller is called as can be seen in default UrlMappings.
That's why changing locale in application root url does not work. If you try to change url in some controller, it works.
Current locale is stored under key org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME in http session. You can check it there.
Correct solution is to map root url to some controller in UrlMappings.
This is problably way too late but for reference, I do this in my index page controller:
session['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'] = new Locale("es", "PR")
I had a similar issue, and it was because a space. I had:
[space]messages_de.properties instead messages_de.properties
I had a problem with this awhile back when proxy-ing through an older version of Apache2.2 and using the grails (2.3.9) war file. I've had better luck using mod_proxy_html (3.1) / Apache 2.4. Maybe more advanced versions of grails fix this.

Resources