One view fo multiple urls to handle multiple languages in django - django

I would like to use the same views for different supported languages.
For exemple I have the default language and the english.
In my main urls:
url(r'^posts/', include('posts.urls')), #for default language
url(r'^en/posts/', include('posts.urls')), #for english
The urls file of my posts app is like this:
url(r'^newpost/$', views.PostFormView.as_view(), name='add'),
url(r'^favorite/$', views.favorite, name='favorite'),
so, for example, both www.mysite.com/posts/add and www.mysite.com/en/posts/add send to the same view PostFormView and according to the url if it contains "/en/" or not I send the content in the right language.
However, the issue is with the redirect or revers sends always to the default language. For example 'posts:add' sends always to "www.mysite.com/posts/add" because I have url(r'^posts/', include('posts.urls')) before url(r'^en/posts/', include('posts.urls'))
are there any ways to use the same view for two different urls. Or, how can I handle multiple languages website? Do we have to duplicate all the apps for all the supported languages?

This is a long subject and it's not easy to cover everything but i'll try to cover as much as i can:
1 - Use django Internationalization and localization:
Django has a built-in function for multi language websites:
Internationalization and localization
2 - Use a single URL with different GET request:
You can add a GET request in your urls like : site.com/posts?lang=en. And try this in your views:
language = request.GET.get('lang')
and then pass the right template for this language.
example:
LANG_LIST = ['en', 'fa', 'fr']
if language.lower() in LANG_LIST:
template = '{}/posts/post.html'.format(language.lower())
else:
template = 'en/posts/post.html'
or you can use a single template with different language texts and just pass the language to the template and decide there.
Note: You should add users language to their session so you can retrieve the language even without a GET request.
Here is the docs for sessions:
How to use sessions | Django documentation | Django
Also you can add language to your users profile and retrieve the language from there. I recommend using both profile language and user sessions.
3 - Different urls (Your way):
I'm not a fan of this way of handling multi language websites really, but if you really need to do it this way then here you go:
You need different names for your urls lile posts_en, posts_fr and etc so you can redirect to the right page url.
You should get the page url in your view and check for language your using. You can do something like this: request.path.split('/').
Then you should check the language and decide which template to render just like option #2
There can be so many problems with this way of handling multiple languages so i don't think you should go with this one over the other two options.

Related

django internalization in urls? how to make urls like this: "en/articles" and "pt/artigos"...?

Hy!
I would need to make urls based on language.
Example:
If I had the language english and subcategory named "articles" then the url might be like this:
/en/articles/...
If the language were portuguese and subcategory already translated is "artigos" then the url will be:
/pt/artigos/...
How can I do it?
I must use the urls.py or some monkeypatches?
thanks
This features is already existing in the yet-to-be released version 1.4. You can read about it in the release note.
If your really need this feature, and no existing app feets your needs, you can still try to apply the corresponding patch yourself.
Django LocaleURL is a piece of middleware that does exactly this. The documentation can be found in the source, or online.
Edit: I read over the fact that you want to translate the url itself... I'm not aware of any piece of code that provides this. Perhaps you could extend the LocalURL middleware to take care of the translations for you. Say you have a regex match like (?P<articles>\w+), you could in the middleware determine which view you want to use. Something like the following mapping perhaps?
if article_slug in ['articles', 'artigos', 'article']:
article(request) # Call the article view
I've been using transurlvania with great success, it does exactly what you need and more, however i see that in the next Django release django-i18nurls will be included in django core so perhaps it would be better to learn that

What/Where to modify django-registration to use with mobile broswers

I am using django-registration along side django auth for my client account creation and login.
Our site will be used by moble users and desktop users. We just started tackling the idea of mobile users by loading different templates from the view depending on user agent strings. It's cleanly done, but I am not sure if it is the right way to do it as we are now stuck with what to do on views that are not easily accessible (that we didn't write ourselves).
Which brings me to the problem at hand:
I have no idea how to tackle redirecting the mobile user away from the login url that django-registration/auth sends them to (the desktop version).
I could change tactics and tackle the different browsers in the template files themselves. That feels like it is going to get messy fast. I don't like that idea at all!
Or I stay with my current method, which is to render the request with different templates based on user agent strings. Then i need to know how I should be dealing with django-registration (how to load a different set of templates based on the user agent string). I would rather not change the django-registration code, if just to make updating modules easier.
The django registration templates are very simple and are used very rarely. I simply handle these as special cases and just come up with a base.html for that works on both platforms reasonably well.
My registration pages look very simple, many sites do this and it is not unexpected.
Another option is to us a middleware which sets the template directory based upon detecting if it is a mobile device. You can detect the mobile browser like this Detect mobile browser (not just iPhone) in python view and then have a middleware that uses the make_tls_property trick to update the TEMPLATE_DIRS something like this:
TEMPLATE_DIRS = settings.__dict__['_wrapped'].__class__.TEMPLATE_DIRS = make_tls_property(settings.TEMPLATE_DIRS)
class MobileMiddleware(object):
"""Sets settings.SITE_ID based on request's domain"""
def process_request(self, request):
if *mobile*:
TEMPLATE_DIRS.value = *mobiletemplates* + settings.BASE_TEMPLATE_DIRS
else:
TEMPLATE_DIRS.value = *normaltemplates* + settings.BASE_TEMPLATE_DIRS
Just to be clear, make_tls_property, which is part of djangotoolbox, makes the TEMPLATE_DIRS setting a per thread variable instead of a global variable so each request response loop gets it's own "version" of the variable.
One method is to simply write your own login view that calls the django-registration view to do the hard work, but passing it a different template depending on the context:
def login(request, *args, **kwargs):
my_kwargs = kwargs.copy()
if <mobile condition>:
my_kwargs['template_name'] = 'my_app/some_template.html'
else:
my_kwargs['template_name'] = 'my_app/some_other_template.html'
from django.contrib import auth
return auth.login(request, *args, **my_kwargs)

How to pass language information from page to page?

If I have a multilingual site, what is the best way to pass information about language?
Right now the language is saved in cookies. That's convenient except that might be not good for search optimization, if search bots don't use cookies.
The other option would be specifying language in address, like exampel.com/?lang=de, but then you probably need to add ?lang=xx to every link on the page.
Is there a right way?
Better way is to maintain this info in session,
The other option would be specifying
language in address, like
exampel.com/?lang=de, but then you
probably need to add ?lang=xx to every
link on the page.
Is there a right way?
I would have created filter than parse each request and fetches the lang param and process accordingly.
Moreover I would recommend you to use following url pattern, and get the lang from filter
yourapp.com/en/welcome/
If you want all the content crawlable then you'd have to pass it in the URL. Either as a parameter http://mydomain.com/en/english-content or maybe have separate sites/subdomains http://english.mydomain.com/english-content
I would use Wikepedia's approach: Different URLs for different languages.
http://en.wikipedia.org for english
http://es.wikipedia.org for Spanish

how to make RSS feeds where the /rss/ is at the end of the URL, not at the beginning?

http://docs.djangoproject.com/en/dev/ref/contrib/syndication/ describes the way to use the Feeds class, and it works well for me, but it requires the URL to be like http://example.com/rss/feedid/parameters/
I need it to be http://example.com/feedid/parameters/rss/
How to do that?
Since Django's URLs are based on regexes, I think that you can use a rule like this:
(r'^(?P<url>.*)/rss/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
Though personally, I have never used the Django syndication framework - I just use generic views (or wrappers around generic views) with the content_type option, and generate the RSS/Atom with a template.

Recursive URL Patterns CMS Style

Whenever I learn a new language/framework, I always make a content management system...
I'm learning Python & Django and I'm stuck with making a URL pattern that will pick the right page.
For example, for a single-level URL pattern, I have:
url(r'^(?P<segment>[-\w]+)/$', views.page_by_slug, name='pg_slug'),
Which works great for urls like:
http://localhost:8000/page/
Now, I'm not sure if I can get Django's URL system to bring back a list of slugs ala:
http://localhost:8000/parent/child/grandchild/
would return parent, child, grandchild.
So is this something that Django does already? Or do I modify my original URL pattern to allow slashes and extract the URL data there?
Thanks for the help in advance.
That's because your regular expression does not allow middle '/' characters. Recursive definition of url segments pattern may be possible, but anyway it would be passed as a chunk to your view function.
Try this
url(r'^(?P<segments>[-/\w]+)/$', views.page_by_slug, name='pg_slug'),
and split segments argument passed to page_by_slug() by '/', then you will get ['parent', 'child', 'grandchild']. I'm not sure how you've organized the page model, but if it is not much sophiscated, consider using or improving flatpages package that is already included in Django.
Note that if you have other kind of urls that does not indicate user-generated pages but system's own pages, you should put them before the pattern you listed because Django's url matching mechanism follows the given order.