Todo mundo já deve ter passado por um projeto multi-idioma. Se ainda não, recomendo mesmo assim a leitura deste post. Por participar de algo assim, pude aprender mais algumas coisas interessantes.
Aqui seguem alguns passos que podem auxiliar e muito a confecção de um projeto multi-idioma
1. Primeiro de tudo, defina quais idiomas o projeto terá.
Isso se faz com algumas configurações no
settings.py:
LANGUAGE_CODE = 'pt-br'
TIME_ZONE = 'America/Sao_Paulo'
USE_I18N = True
USE_L10N = True
ugettext = lambda s: s
LANGUAGES = (
('pt-BR', ugettext(u'Português')),
('en-US', ugettext(u'Inglês')),
('es-ES', ugettext(u'Espanhol')),
)
USE_TZ = False
LOCALE_PATHS = (
os.path.join( PROJECT_PATH, '../locale' ),
)
- LANGUAGE_CODE: Aqui é definido a linguagem inicial do projeto. Valor padrão: 'en-us'. Veja a lista de outras línguas aqui: http://www.i18nguy.com/unicode/language-identifiers.html
- TIME_ZONE: Define o fuso horário do projeto. Valor padrão: 'America/Chicago'
- USE_I18N: Flag que determina se o sistema de tradução do Django deve ser habilitado ou não. Deve ser True para multi-idiomas e False, por questões de otimização, quando tiver apenas um idioma. Valor padrão: False
- USE_L10N: Um booleano que especifica se a formatação localizada de dados será ativado por padrão ou não. Se esta é definida como True , por exemplo Django irá exibir números e datas usando o formato da localidade atual. Valor padrão: True
- LANGUAGES: Tupla com as linguagens que serão utilizadas no site.
- USE_TZ: Determina se o django usará o datetime com base no fuso ou não.Valor padrão: False
- LOCALE_PATH: Tupla com os diretórios onde serão gerados os arquivos para tradução.
2. Instale o django-modeltranslation
$ pip install django-modeltranslation
No settings, certifique-se que o modeltranslation está acima do admin do Django, pra não ter problemas, coloque ele como a primeira linha do INSTALLED_APPS:
INSTALLED_APPS = (
# TRANSLATION
'modeltranslation',
...
)
Cerfitique-se que o Locale Middleware está instalado:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
E inclua a url de tradução no
urls.py:
...
(r'^i18n/', include('django.conf.urls.i18n')),
...
Na aplicação que terá conteúdos dinâmicos para cada idioma deixe os arquivos como abaixo:
models.py
# coding: utf-8
from django.db import models
# Create your models here.
class Conteudo(models.Model):
"""(Conteudo description)"""
titulo = models.CharField(u'Título', max_length=255)
texto = models.TextField()
slug = models.SlugField(verbose_name=u'Slug / URL')
class Meta:
verbose_name, verbose_name_plural = u"Conteúdo" , u"Conteúdos"
ordering = ('titulo',)
def __unicode__(self):
return u"%s" % self.titulo
admin.py
# Register your models here.
from django.contrib import admin
from .models import *
from modeltranslation.admin import TranslationAdmin
class ConteudoAdmin(TranslationAdmin):
search_fields = ('titulo', 'texto',)
list_display = ('titulo', 'texto')
prepopulated_fields = {"slug": ("titulo",)}
save_on_top = True
admin.site.register(Conteudo, ConteudoAdmin)
translation.py
# translation.py
from modeltranslation.translator import translator, TranslationOptions
from .models import *
class ConteudoOptions(TranslationOptions):
fields = ('titulo', 'texto',)
translator.register(Conteudo, ConteudoOptions)
Quando usar a migração (South para Django<1.7, ou nativo para Django>=1.7), serão gerados no banco os campos definidos no
translation.py para cada idioma, isto é, o resultado será uma tabela com:
- titulo_pt_br
- texto_pt_br
- titulo_en_us
- texto_en_us
- titulo_es_es
- texto_es_es
- slug
E o admin já trará todos eles com uma marcação de idioma através de [<idioma>] nas labels de cada campo.
Observação Importante:
Caso não haja necessidade de traduzir a url que ficará no navegador, não inclua o slug no translation.py (recomendo que não inclua! Insista, convença seu chefe!). Isso facilita e muito quando o usuario troca de idioma para redirecioná-lo para a mesma página ao invés de mandá-lo de volta pra home do site e/ou fazer qualquer gambiarra para redirecioná-lo corretamente.
3. Nos templates, fica muito simples:
{{ obj.titulo }}
Aqui o próprio Model Translation irá verificar qual o é o idioma atual e exibir o valor correto. Sem IFs e sem duplicação de templates.
4. Para conteúdos estáticos, o processo continua o mesmo com a geração dos .po
Carrege o módulo i18n nos templates que for traduzir:
{% load i18n %}
Marque nos templates estáticos onde sofrerá tradução com as tags trans e blocktrans
{% trans "Exemplo de texto a ser traduzido nos seus htmls" %}
Execute o comando
makemessages para gerar as mensagens:
$ python manage.py makemessages --locale=en --ignore=templates/admin --ignore=project/settings.py
Serão gerados arquivos .po para tradução no
LOCALE_PATH definido nas settings com a seguinte estrutura:
Nestes arquivos, serão armazenados os termos a serem traduzidos para envio para a pessoa responsável para tradução, e eles se parecem com isso:
#: templates/atendimento/atendimento.html:21
#: templates/atendimento/sucesso.html:21 templates/curriculos/sucesso.html:21
#: templates/curriculos/trabalhe-conosco.html:25
msgid "Dados enviados com sucesso"
msgstr ""
No exemplo acima, as linhas iniciadas com
# indicam o caminho dos arquivos em tem o termo contido no
msgid em comum, e no
msgstr é onde deve ser preenchido com a tradução para o idioma correspondente.
Caso a pessoa responsável pela tradução não conseguir/quiser editar direto os .po, existem alguns apps que podem ser utilizados para facilitar esse processo, como o Rosetta (mais informações em:
https://github.com/mbi/django-rosetta) por exemplo. Este cria uma interface com base no bom e velho admin provido pelo Django.
Depois de tudo preenchido, basta compilar as mensagens com o comando
compilemessages:
$ python manage.py compilemessages --locale=en
$ python manage.py compilemessages --locale=es
5. Para trocar de idioma no site, basta um form:
{% get_available_languages as LANGUAGES %}
{% get_current_language as LANGUAGE_CODE %}
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language">
{% 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 type="submit" value="Go" />
</form>
Em {{ redirect_to }}, se o slug não tiver sido traduzido e cada conteúdo tiver uma única url, aqui vc pode por a url atual,
{{ request.META.PATH_INFO }}, e quando o usuário trocar de idioma, já vai ser redirecionado para a mesma página que estava visualizando.
Referências:
hasta!