Django Internationalization with Geolocation - django

From what I read in Django documentation, this is what LocaleMiddleware does:
LocaleMiddleware tries to determine the user’s language preference by following this algorithm:
First, it looks for the language prefix in the requested URL. This is
only performed when you are using the i18n_patterns function in your
root URLconf. See Internationalization: in URL patterns for more
information about the language prefix and how to internationalize URL
patterns.
Failing that, it looks for a django_language key in the current user’s
session.
Failing that, it looks for a cookie.
The name of the cookie used is set by the LANGUAGE_COOKIE_NAME
setting. (The default name is django_language.)
Failing that, it looks at the Accept-Language HTTP header. This header
is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
Failing that, it uses the global LANGUAGE_CODE setting.
I want my django project to detect user country and use it in choosing default language?
How to do this:
I have two ideas in mind:
Write a new middleware which to execute before LocaleMiddleware and in this middleware if there is no cookie LANGUAGE_COOKIE_NAME to set it using django GeoLocation
Replace LocaleMiddleware and instead of looking for Accept-Language HTTP header to use django GeoLocation
What do you think?
Or may be there is another easier way?
Edit: I will have an option for changing language, the problem is only when you open the website (any page, not just front page) for the first time. I'm considering now to set django_language for the default website language /bg/ (if there is no such settings) and also use international urls /en/, /bg/. Also there have to be a language switch option. This way there will be no problem with search engines and I will not use geolocation at all.
Edit: Also there is this problem that here (in Bulgaria) most browsers headers are set to prefer English language which is not a good option :(

Actually it isn't a very good idea overall. You should rarely want to set a language for a client, that's why most sites use an optional language form. (flag buttons or possibly a dropdown select).
The LocaleMiddleware runs down a hierarchical path that most likely will pick the right translation (if available). A proper solution would be to hand your clients a form to set or switch their preference. You could populate the django_language session key if the form is processed.
Also crawlers will not scrape pages properly if forced to a language setting.

I found this, that is very usefull:
Middleware that will force django to use settings.LANGUAGE_CODE for default language and not use equest.META['HTTP_ACCEPT_LANGUAGE']
class ForceDefaultLanguageMiddleware(object):
"""
Ignore Accept-Language HTTP headers
This will force the I18N machinery to always choose settings.LANGUAGE_CODE
as the default initial language, unless another one is set via sessions or cookies
Should be installed *before* any middleware that checks request.META['HTTP_ACCEPT_LANGUAGE'],
namely django.middleware.locale.LocaleMiddleware
"""
def process_request(self, request):
if request.META.has_key('HTTP_ACCEPT_LANGUAGE'):
del request.META['HTTP_ACCEPT_LANGUAGE']
Source: https://gist.github.com/vstoykov/1366794

Related

How add variable to django request from my front-end?

I am developing web app, with djangorestframework on the back and Vue.js on the front. Interface was translated to a few language. On the site footer user can see icons of language represented country flag.
After hit the need icon, app translate all text to required language. All actions for translate do in front and my backend know nothing about what is language was chosen. Now I want to tell my back-end about chosen language, how can I do it? I think to add a variable language to my django request object, but I can find nothing about it.
Any ideas?
I see two approach :
Send the language value on every (interesting) request, as you proposed
Or, keep it in user settings in the backend : you add a charfield on a custom user model. When you need the language value during a request, you can access it through self.request.user.lang. You will have to add a route to update the value when users click on the icons.
It depends on how usual the language value is needed ; if its often, it will be simpler to have it in the backend. But you must keep the value up to date... Its a trade off :)
I specified a language variable in my localStorage then I returned value to Content-Language header and after this I've could take the language value in my django request.

Get objects from current site without settings.SITE_ID

I'm looking for the same functionality as the CurrentSiteManager provides but without having to specify SITE_ID in settings.py as the CurrentSiteManager requires. Information about the current site should come from the request. My take on the problem would be to make a custom manager, but is there something I'm missing? What would be a good way of doing this? It seems quite trivial that the CurrentSiteManager should provide this functionality. Would it make sense to submit a feature request?
You write:
Information about the current site should come from the request.
There is a big assumption here, which is that the manager will always have a request context available.
This isn't an assumption that Django can make: any generic model manager must work outside of a request context because there are all sorts of cases where a request context isn't available - e.g., management commands, migrations, tasks, etc. Even if you are in the context of a request, your manager has no knowledge of this unless you explicitly pass it to any method on the manager (i.e., you need those methods to accept a request argument). This is why CurrentSiteManager requires a SITE_ID:
The CurrentSiteManager is only usable when the SITE_ID setting is defined in your settings.
If you do want to filter objects within a request context, then Django provides the CurrentSiteMiddleware to add the current site to all requests. Within your views you can then filter objects on this site.
There are examples of projects that have implemented a custom CurrentSiteManager that does what you're asking for - the one that comes to mind is Mezzanine which you may be able to borrow from (note that it involves messing around with thread locals, and still requires a fallback to a SITE_ID setting).

Django: which url does the LocaleMiddleware check?

Our company provides both a API and a small number of widgets that are embedded in clients websites through Iframes.
Now we have a Belgian customer who wishes to use our widgets. As you know Belgium is bi-lingual, so we are making liberal use of both the LocaleMiddleware and the {% trans 'string' %} tags.
Now as I understand correctly the middleware checks the URL to see which language to use. When you first visit our clients website you get a large pop-up where you choose your language. After this popup your url changes to this format: www.clientorg.be/fr_BE/rest-of-the-url, so that should (hopefully) work just fine.
However, our widget is served through an Iframe. (src = s2.oururl.com) which contains no language value.
So my question is: Will Django be able to detect the language of the user? Or will it only be able to check 'our' s2.url, meaning we need to contact our client and provide him with 2 urls to paste in the iframe, depending on the language the user chooses.
Here's exactly what LocalMiddleware tries to do to determine the language:
https://docs.djangoproject.com/en/2.0/topics/i18n/translation/
LocaleMiddleware tries to determine the user’s language preference by
following this algorithm:
First, it looks for the language prefix in the requested URL. This is
only performed when you are using the i18n_patterns function in your
root URLconf. See Internationalization: in URL patterns for more
information about the language prefix and how to internationalize URL
patterns.
Failing that, it looks for the LANGUAGE_SESSION_KEY key in the current
user’s session.
Failing that, it looks for a cookie.
The name of the cookie used is set by the LANGUAGE_COOKIE_NAME
setting. (The default name is django_language.)
Failing that, it looks at the Accept-Language HTTP header. This header
is sent by your browser and tells the server which language(s) you
prefer, in order by priority. Django tries each language in the header
until it finds one with available translations.
Failing that, it uses the global LANGUAGE_CODE setting.

Sitecore language embedding and default language

The business has a requirement to always show the language in the URL for our CD sites. I did some research and set the LanguageEmbedding setting to always. This seems to work fine for non-default languages but not for English, which is the default language.
When I try to go to www.abc.com, shouldnt it change to www.abc.com/en ? Am I right to think this or is this how Sitecore will behave for default language where it won't show the language if its not an embedded links?
Thanks
When Sitecore determines your language via browser preference, cookie, URL slug, or query string, it will not redirect to that preferred URL structure with language slug.
You can either create a redirect module (i.e. if language context set, make correct URL and redirect) or write out <link langref=""> tags, which is an SEO best practice anyways.
OOTB that is the way that Sitecore works. When you have LanguageEmbedding="always" - the links should all be generated with the language embedded - including for en, so a link to the home page would be www.abc.com/en - but if you just visit the domain - www.abc.com - Sitecore then uses either the language cookie stored from your last visit, or the default language.
If you want the behavior to be that if you visit www.abc.com the user is always it would be better to set that up using an IIS Redirect or a rewrite .

Using user-agent language with Django Translation

What is the best way to combine user-agent language and django i18n?
Example: I've set LANGUAGES in my settings.py:
LANGUAGES = (
('en', ('English')),
('pt-br', ('Brazilian Portuguese')),
)
If the client user-agent is configured to Portuguese as default, The Django i18n machinery will use Brazilian Portuguese as default language for my website, otherwise it will remain in English
Is it better to use the language based on user-agent default or based on client IP location?
I would go for user agent because the user is able to set his preferred language in his browser. IP location says nothing about the language the user actually speaks nor does the user have any influence on it. In both cases you can still provide a language selector on your page as well.