Django internationalization switching between languages - django

I have a french and a english site up, very basic. I created my fr language file. I have a few translated strings to test this to make sure it works but I am confused as how to set up the actual link to swap between languages. I have followed this, https://docs.djangoproject.com/en/1.3/topics/i18n/internationalization/#the-set-language-redirect-view but receive a 404 for /next/page, am i doing this correctly? Here is my code if this helps:
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="/next/page/" />
<select name="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for lang in LANGUAGES %}
{% if lang.0 != '' %}
<option value="{{lang.0}}">{{lang.1}}</option>
{% endif %}
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
I have also added my urls like so:
(r'^i18n/', include('django.conf.urls.i18n')),
And I have this in my settings for middleware and language:
'django.middleware.locale.LocaleMiddleware',
LANGUAGES = (
('en', 'English'),
('fr', 'French'),
)
I am confused as to how to have this working so i can swap between the 2 languages, or, If I am doing it correctly, why am I getting that 404 error with the /next/page when trying to change languages?
Thanks!
Jeff

In this line
<input name="next" type="hidden" value="/next/page/" />
you have to substitute "/next/page/" with the page that you want to load after the language change.
In case that you want to load the same page, you should write value="".

Related

How to let user select currency in Django using Django-money?

I am currently working on an online store. I want a user to be able to change their currency option in the header and convert the whole site to the currency choice. I have found app called django-money, which seams to have that functionality, but I cannot find any implementation examples.
I want it to work like localize work in django. Having a form that will redirect to URL and saving choice in session and in cookie. This is the example of the language selection code.
/template.html
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language" onchange="this.form.submit()">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.code|upper}}
</option>
{% endfor %}
</select>
</form>
And then whenever I need something to be translated I will use this inside html:
{% trans "Some text to translate" %}
So is there something similar for currency? What would be the action for the form? Please can somebody help if you have ready solution! I will really appreciate.

set_language not changing language in certain cases (django)

I have the following menu to change languages in my site:
<div class="btn-group navbar-right language menu">
<button class="btn btn-secondary btn-sm dropdown-toggle language-btn" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{% get_language_info for LANGUAGE_CODE as lang %}
{{ lang.name_local }} ({{ lang.code }})
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenu2">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<ul class="language-item">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path }}" />
<input name="language" type="hidden" value="{{ language.code }}" />
<input type="submit" value="{{ language.name_local }} ({{ language.code }})" /> <span>{% if language.code == LANGUAGE_CODE %}✓{% endif %}</span>
</form>
</ul>
{% endfor %}
</div>
</div>
Being shown like
This works the same than the form suggested by Django docs but avoiding the "Go" button to switch languages.
It usually switches languages properly, except in certain cases, as I found out after a user reported the problem.
If the user gets to my site via www.mydomain.com, it will be redirected to www.mydomain.com/en/ (or /es/ or /de/) and as far as I know, changing languages works as expected.
However, if the user gets to my site via www.mydomain.com/es/, then when trying to change the language through the menu, www.mydomain.com/es/ is loaded again. The same behavior occurs with www.mydomain.com/de/.
Strange enough, when entering my site via www.mydomain.com/en/, changing languages works properly. Maybe because it is the default language?
I am able to replicate the issue consistently if entering the site through an incognito window. If I do it through a normal window, it is a similar behavior, but not always consistent. For instance, sometimes entering via www.mydomain.com/en/ will not let me change the language either. This makes me think it might have something to do with cookies. But this is as far as I got.
I checked for similar problems during hours and the only similar thing I found is the Django ticket In some cases i18n set_language does not change url language. Its conclusion is:
...I recreated the issue: we set a language (once) then try to reverse
a URL from the old language when setting the language again.
This obviously fails.
Workarounds:
keeping track of the old language and falling back to try that if the lookup with the current language fails.
Signalling across browser tabs that we already changed the language and adjusting accordingly (???).
Both of these are out of scope for the in-built i18n. (The first would
be possible on a project level — reimplementing e.g. set_language — if
it was deemed cost effective.)
I'm going to close this on that basis.
I am not sure if it is the same case, as I don't understand why it "obviously fails". As I see it, the obvious behavior should be to change the language.
I am surprised that such a basic feature does not work, so probably I am missing something.
Why is it not working in the cases described?
Any help would be appreciated.
Edit 1:
Previously I was using translated URLs instead of the form, as suggested here. However, this was taking 1 second to render due to the translation of the slug. This is why I decided to change
I experienced the same problem. It is still an existing issue, where django seemingly does not translate the HTTP referer header.
See Django source code of set_language
A way to workaround this is to send a hidden input field named next that you set to the same url you are at (request.get_full_path), but replace the current language part with the language you intend to switch to.
Here is a snippet of a language switcher solving this issue:
<li {% if current_language|slice:":2" == 'en' %} class="active"{% endif %}>
<form method="POST" action="{% url 'set_language' %}" autocomplete="off">
{% csrf_token %}
<span class="language-code">en</span>
<input type="submit" name="language" value="en">
<input type="hidden" name="next" value="{{ request.get_full_path|replace_language:"en" }}">
</form>
</li>
<li{% if current_language|slice:":2" == 'da' %} class="active"{% endif %}>
<form method="POST" action="{% url 'set_language' %}" autocomplete="off">
{% csrf_token %}
<span class="language-code">dk</span>
<input type="submit" name="language" value="da">
<input type="hidden" name="next" value="{{ request.get_full_path|replace_language:"da" }}">
</form>
</li>
Then you can implement a custom template tag called replace_language that runs through your configured languages and replaces it with the argument.
Hope this helps :-)
For further reference, I just went back to using translated URLs as suggested here, instead of the form.
I found out that what was making it so slow.
It turned out it was something that could be optimized, so now the translated URLs load very fast as well.
Solved the issue by removing the language code from the "next" input (slice the current language code from the url)
Next input:
<input name="next" type="hidden" value="{{ request.get_full_path|slice:"3:" }}">
Whole dropdown:
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<div class="row g-2">
<div class="col col-sm-12 col-lg-3 col-md-4">
<div class="form-floating">
<input name="next" type="hidden" value="{{ request.get_full_path|slice:"3:" }}">
<select class="form-select" name="language" onchange="this.form.submit()" id="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<label for="language">Language</label>
</div>
</div>
</div>
</form>

Django 2 versions of german

I'm developing website with 2 versions of german (Default and Austrian).
My problem is that template do not differ them, so in select django displays them both as Deutsch(de).
Languages in settings.py:
('en', _('English')),
('de', _('German')),
('de-at', _('Austrian'))
template code:
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select style="border:1px dotted black" name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input class="btn-primary" type="submit" value="{% trans 'Change' %}" />
</form>
Code is from documentation.
Translation in Austrian language doesn't work, because django in select defines Austrian as default Deutsch select it and do not translate.
So, are there any ways to display sublanguage in template, like (Deutsch(de-at)) or just (Austrian instead of Deutsch), or are there any other ways to solve it?
Tried to change all languages in settings:
('en-us', _('English')),
('de-de', _('German')),
('de-at', _('Austrian'))
Then created .po and .mo files to them. But still template defines them as same languages. Also I thought about changing language name in template, but as far as I understand I can't do it.
I've sold my problem, still don't understand what's the reason...
Django front end form, that I copied from documentation doesn't work as it should.
Form, that I used on front side works correct only with base languages and crashes on sublanguages(all). Now I've rewrite this form:
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<select style="border:1px solid black" name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}"
{% ifequal lang.0 request.LANGUAGE_CODE %}
selected="yes"
{% endifequal %}
>{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="{% trans 'Change' %}" />
</form>
Per now it works fine...

How can I change the language name of the I18N code?

i need some help with a internationalization (I18N) issue for a website.
In trying to change the value of the language name of the I18N code, I have a select form with the languages so i change it, this is the code of the select:
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language" onchange="this.form.submit()">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ trans 'language.name_local|capfirst' }}
</option>
{% endfor %}
</select>
</form>
This is the languages declaration in setting.py
ugettext = lambda s: s
LANGUAGES = (
('es', ugettext('Spanish')),
('en', ugettext('English')),
('eu', ugettext('Euskera')),
)
Euskera is the local language of the spanish state Basque country.
But in the select it shows the values: "Español","English","Basque" and I want it to show different values depending the current language.
If i want the website in Spanish it should show: "Español", "Ingles", "Euskera".
If i want the website in English it should show: "Spanish", "English", "Basque"
If i want the website in Spanish it should show: "Español", "Ingles", "Euskera"
I have three django.po files for each languaje and they translate other texts correctly.
If you have any idea, please share it.
Thank you.

Django Language Selector in local and native language

I have a django website I am adding translations to with a language selector that lists the available languages in the user's language. I would like to have the dropdown include the native spelling also.
Currently it looks like this:
English
Dutch
Simplified Chinese
When I switch to Chinese it looks like:
英语
荷兰语
简体中文
I am trying to make it look like:
English/English
Dutch/Nederlands
Simplified Chinese/简体中文
settings.py includes:
ugettext = lambda s: s
LANGUAGES = (
('en', ugettext('English')),
('nl', ugettext('Dutch')),
('zh-cn', ugettext('Simplified Chinese')),
)
base.html:
{% load i18n %}
{% get_available_languages as LANGUAGES %}
<form action="/i18n/setlang/" method="post">{% csrf_token %}
<input name="next" type="hidden" value="/" />
{% csrf_token %}
<select name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
My thought was to add another item to LANGUAGES that is the native language, like:
LANGUAGES = (
('en', ugettext('English'), 'English'),
('nl', ugettext('Dutch'), 'Nederlands'),
('zh-ch', ugettext('Simplified Chinese'), '简体中文'),)
But Django seems to expect a 2 item tuple for LANGUAGES. Any other ideas?
EDIT per Alexander's comment:
I thought that might be a simpler solution, but after changing the code:
<form action="/i18n/setlang/" method="post">{% csrf_token %}
<input name="next" type="hidden" value="/" />
<select name="language">
<option value="en">English</option>
<option value="nl">Dutch\Nederlands</option>
<option value="ru">Russian\Русский</option>
<option value="zh-cn">Simplified Chinese-简体中文</option>
</select>
<input type="submit" value="Go" />
</form>
The Russian and Chinese scripts are showing up as question marks - Russian\???????, Chinese-????
I have <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
in the html, other Russian and Chinese text (outside of this form) appears fine.
Try this:
LANGUAGES = (
('en', '{}/{}'.format(ugettext('English'), 'English')),
('nl', '{}/{}'.format(ugettext('Dutch'), 'Nederlands')),
('zh-cn', '{}/{}'.format(ugettext('Simplified Chinese'), '简体中文')),
)
Then you can use this in your templates:
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
{% endfor %}
Taking Alexander's suggestion, I was able to get the code in the edit above to work properly. I did not have the <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
line within the 'head' area, which is required, and that was giving me the ???? where the Chinese characters should have been.
After seeing it in action, I may have 2 language selectors, one that gets translated into the current language, and another with the English/Native characters if it isn't too busy.
I also will put the language list in a module and pass it to the template similar to getting the LANGUAGES.