I need to know the user's preferred language—preferrably without having to parse the HTTP Accept-Language header myself. The only reason I need it is to return a list of month names localized for their preferred language in an AJAX call. My application has no other needs for internationalization.
def ajax_get_month_names(request):
# Get the user's preferred language
# Get and return the month names using Python's locale features (pretty easy)
To get a language code try this code:
from django.utils.translation import get_language_from_request
language = get_language_from_request(request)
Related
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.
I want Django to localize all dates (in all regions), but I don't want translations. It seems like for a date to be put into the right locale, we need to add its language to LANGUAGES.
For dates to be localized, we also need USE_I18N = True and USE_L10N = True.
Is this even possible?
I don't want translations, because as long as the site is not fully translated, you will have a website that is only half-translated. This is an issue due to django, because its error messages are all translated.
The best approach for you is to store your data in your database as unix timestamps and then display them using javascript. This immidiately eliminates all the complex code you have for detecting the user's locale in django. With javascript it's a lot easier to do that, and also to display the time using the appropriate format.
toLocaleDateString is your friend
The toLocaleDateString() method returns a string with a language
sensitive representation of the date portion of this date. The new
locales and options arguments let applications specify the language
whose formatting conventions should be used and allow to customize the
behavior of the function. In older implementations, which ignore the
locales and options arguments, the locale used and the form of the
string returned are entirely implementation dependent.
It is easy to get the current language (e.g. en) anywhere in a django app: django.utils.translation.get_lanaguage()
But how do I get the current locale (e.g. en_US or en_GB)?
Did you try to_locale()?
from django.utils.translation import to_locale, get_language
to_locale(get_language())
The distinction between language and locale (in Django, at least) is just a matter of formatting. Both en and en-us are languages, and if en-us is the currently selected language then that will be returned by get_language().
So your problem seems to be that Django is not setting the current language the way you expect. There's a long list of techniques Django uses to try and figure out the language to use, so I suggest working your way down that to see why the language isn't what you expect.
For example:
If a base language is available but the sublanguage specified is not, Django uses the base language. For example, if a user specifies de-at (Austrian German) but Django only has de available, Django uses de.
Django's django.utils.translation.to_locale() expects a "language name" like en-us and will convert that to a "locale name" like en_US.
Source code: https://github.com/django/django/blob/master/django/utils/translation/init.py#L271-L284
It basically just does some string manipulation.
If your "language name" is just a simple language code like en, it will return just en. If you want to convert en to a locale like en_US.UTF8, you will have to write your own to_locale() function. You'll have to determine what locale you want for the language code en. Example:
LANG_TO_LOCALE = {
'en': 'en_US.UTF8',
'nl': 'nl_NL.UTF8',
'es': 'es_ES.UTF8'
}
def lang_to_locale(language_code):
return LANG_TO_LOCALE.get(language_code)
Depending on your taste you might for example want to get the locale en_GB.UTF8 instead of en_US.UTF8 for the language code en.
This then can be used to set the locale in Python:
import locale
locale.setlocale(locale.LC_ALL, lang_to_locale('nl'))
And then you can get a month name in the desired language:
from datetime import datetime
print(datetime.strftime(datetime.now(), '%B')) # Prints month name in Dutch
To make this work you need to have the appropriate locale packages installed on your system. On Ubuntu you can do this with sudo dpkg-reconfigure locales.
In the relevant (virtual) environment:
python
>>> import locale
>>> locale.getlocale()
e.g. ('en_GB', 'UTF-8')
I'm looking for a way to detect user language. I set my default language as 'en_US', and I translated my site for 'pt_BR'. How can I switch the language and show 'pt_BR' version for Brazilians and 'en_US' for the rest of the world?
I read these documentation links:
https://docs.djangoproject.com/en/dev/topics/http/sessions/
https://docs.djangoproject.com/en/1.7/topics/i18n/translation/
I believe that maybe I'll have to take this information from user cookies or browser preferences, but how can I do this?
Furthermore, how can I test different languages? I have to change my browser language? OS language? Use a proxy?
Every user's HTTP request contains in header parameter Accept-Language.
Example would be:
user_langs = request.META.get('HTTP_ACCEPT_LANGUAGE', ['en-US', ])
Try to add navigator.language to your post data and resolve it in your view.
http://www.w3schools.com/jsref/prop_nav_language.asp
I want to generate a PDF which will show the output of my queryset in table format, for example:
query = ModelA.objects.filter(p_id=100)
class ModelA(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
p_id = models.IntegerField()
description = models.TextField()
I need to show the values for name, description and pid in the generated PDF.
As mentioned by other people the best way to do this is to generate a template then convert the result, using one of the many libraries around, into a PDF. This method provides you with the usual amount of control over your templates, for example using tags.
I've used the previously mentioned ReportLab/Pisa setup but found it to be quite limiting, most layouts have to be built using tables and many parts of the CSS2 spec aren't implemented yet.
An easier to use library is wkhtmltopdf which is a headless distribution of WebKit. This has the benefit of rendering your templates like any webkit browser would and thus letting you use webkit specific extras, such as parts of the CSS3 spec that exist in WebKit.
Using the wrapper library django-wkhtmltopdf you can render_to_pdf in your view instead of the usual Django render_to_response.
Disclaimer: I am a contributor to this library.
Update
This library has been converted to CBVs and most of the information below (which I'll leave to help add some context) is now implemented in the library itself for convenience.
See the quickstart docs for an example of how to implement the below code block. If you need to use more advanced usage you can subclass PDFTemplateView and add various options like filename and the margins.
An example view:
from django.shortcuts import render_to_response
from wkhtmltopdf import render_to_pdf
def pdf(request):
context.update({'objects': ModelA.objects.filter(p_id=100)})
kwargs = {}
if request.GET and request.GET.get('as', '') == 'html':
render_to = render_to_response
else:
render_to = render_to_pdf
kwargs.update(dict(
filename='model-a.pdf',
margin_top=0,
margin_right=0,
margin_bottom=0,
margin_left=0))
return render_to('pdf.html', context, **kwargs)
The conditional statement here lets you pass ?as=html to the view so you can develop in the browser. It's a bit of an ugly way to do it currently but there are plans to fix this in a release soon.
Using this view you could loop the contents of objects in your view as you would normally and even extend your base template. I've normally used a different stylesheet specifically for the PDFs for maintainability and readability of the styles as you need to do a few things differently for PDFs, such as setting a min-height if you want to keep your footer block in the same place.
On this note, you can create header and footer templates that will be used on each page of your PDF by passing them into render_to_pdf as part of kwargs.
Just generate the HTML the way you would want it and ask xhtml2pdf to convert it into pdf.
Like one of the comment mentions, there is ReportLab, but that would need you to give specification in PDF's required format. It provides you more control, but if it is easier for you to generate HTML, the standard way which you need to generate anyway, you can use pisa to make it pdf.
Try wkhtmltopdf with python-pdfkit
This seems to be the best solution.Supports javascript and css