Actualización: Tras haber investigado el error un poco, he llegado a la conclusión de que es un bug de python, y por lo tanto irresoluble hasta que se solucione en la version 2.7.3


Hola,

Estoy realizando un calendario de eventos básico para django utilizando el módulo calendar de python, y debido a que mi aplicación es multilingue tiene que funcionar en varios idiomas.

El problema que tengo es que a pesar de que el módulo calendar ofrece varias opciones de localización, ninguna funciona correctamente.

He probado a través de LocaleHTMLCalendar y me da errores de codificación ASCII dentro del propio módulo de Python (todos los ficheros de mi programa están declarados como UTF-8) concretamente al traducir "Wed" por "Mié" (Miércoles)

1
Unicode error hint The string that could not be encoded/decoded was: d">mi��</th

También he probado a localizarlo a mano, a través de los arrays day_name, day_abbr, month_name y month_abbr pero el resultado es que el calendario se muestra sin texto.

Alguna idea? Os dejo mi código aquí, está basado en el de Elvin Uggedal. Ahora mismo estoy utilizando LocaleHTMLCalendar con un pequeño rodeo para poder cargar el idioma del usuario y no el del sistema.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import calendar
#from calendar import HTMLCalendar
from datetime import date
from itertools import groupby

from django.utils.html import conditional_escape as esc
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import get_language
#from django.db import models

class EventCalendar(calendar.LocaleHTMLCalendar):

    """
    Event calendar is a basic calendar made with HTMLCalendar module.
    """

    def __init__(self, *args):
        events = args[0]
        super(EventCalendar, self).__init__()
        self.events = self.group_by_day(events)

    def formatday(self, day, weekday):
        if day != 0:
            cssclass = self.cssclasses[weekday]
            if date.today() == date(self.year, self.month, day):
                cssclass += ' today'
            if day in self.events:
                cssclass += ' filled'
                body = ['<ul>']
                for event in self.events[day]:
                    body.append('<li>')
                    body.append('<a href="%s">' % event.get_absolute_url())
                    body.append(esc(event.title))
                    body.append('</a></li>')
                body.append('<ul>')
                return self.day_cell(cssclass, '%d %s' % (day, ''.join(body)))
            return self.day_cell(cssclass, day)
        return self.day_cell('noday', '&nbsp;')

    def formatmonth(self, year, month):
        self.year, self.month = year, month
        return super(EventCalendar, self).formatmonth(year, month)

    def group_by_day(self, events):
        field = lambda event: event.meeting_date.day
        return dict(
            [(day, list(items)) for day, items in groupby(events, field)]
        )

    def day_cell(self, cssclass, body):
        return '<td class="%s">%s</td>' % (cssclass, body)

La vista:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from django.shortcuts import render_to_response, get_object_or_404
from django.utils.safestring import mark_safe
from django.template import RequestContext
from django.utils import translation

from e_cidadania.apps.spaces.models import Meeting, Space
from e_cidadania.apps.cal.models import EventCalendar

def calendar(request, space_name, year, month):

    # Avoid people writing wrong numbers or any program errors.
    if int(month) not in range(1, 13):
        return render_to_response('cal/error.html',
                                  context_instance=RequestContext(request))

    place = get_object_or_404(Space, url=space_name)
    next_month = int(month) + 1
    prev_month = int(month) - 1

    meetings = Meeting.objects.order_by('meeting_date') \
                              .filter(space = place,
                                      meeting_date__year = year,
                                      meeting_date__month = month)

    cur_lang = translation.get_language()
    print cur_lang
    cal = EventCalendar(meetings, 0, cur_lang).formatmonth(int(year), int(month))
    return render_to_response('cal/calendar.html',
                              {'calendar': mark_safe(cal),
                               'nextmonth': '%02d' % next_month,
                               'prevmonth': '%02d' % prev_month,
                               'get_place': place},
                               context_instance = RequestContext(request))

preguntado 28 Jun '11, 18:18

oscarcp's gravatar image

oscarcp
2.4k123551
Aceptadas: 51%

editó 29 Jun '11, 12:25

Creo que el código que has puesto le faltan cosas. En el inicializador EventCalendar faltaría pasar bien los parámetros a LocaleHTMLCalendar. Te recomiendo que lo edites así:

1
2
3
def __init__(self, events, *args, **kwargs):
    self.events = self.group_by_day(events)
    super(EventCalendar, self).__init__(*args, **kwargs)

Por otro lado, ¿qué devuelve la vista en el print de la línea 26? ¿LLeva la codificación?

(28 Jun '11, 19:47) chemacortes

El print de la linea 26 devuelve la variante de idioma, sin la codificación ni el idioma en si, es decir "en" en vez de "en_GB.UTF8"

(28 Jun '11, 22:08) oscarcp

Yo probaría con lo siguiente:

En la línea 25 de la vista:

1
2
3
cur_lang = translation.get_language()
cur_locale = translation.to_locale(cur_lang)+'.UTF-8' #default encoding with django
cal = EventCalendar(meetings, 0, cur_locale).formatmonth(int(year), int(month))
enlace permanente

respondido 28 Jun '11, 20:05

chemacortes's gravatar image

chemacortes
4.1k54961
Aceptadas: 50%

editó 28 Jun '11, 20:06

He realizado los cambios que mencionas, pero ahora en vez de dar error de codificación, da error de valores "Too many values to unpack" sin más explicación

(29 Jun '11, 09:39) oscarcp
1

Tras deliberar e investigar, he descubierto que el módulo locale de python está devolviendo "localetuple" como un string en vez de una tupla para construir el código de locale. Acabo de ver esto: http://bugs.python.org/issue3067

(29 Jun '11, 10:45) oscarcp

Ya veo. El módulo locale no espera encontrar argumentos con unicode :-?

Lo que sí podrías hacer es convertir el literal a ascii:

1
cur_locale = translation.to_locale(cur_lang).encode("ascii")+'.UTF-8'

Aunque creo que sería mejor tratar todo ésto dentro de la clase EventCalendar para facilitar el mantenimiento posterior.

(29 Jun '11, 18:52) chemacortes
Tu respuesta
Activar/desactivar vista previa

Seguir esta pregunta

Por Email:

Una vez que entres podrás suscribirte desde aquí para recibir actualizaciones

Por RSS:

Respuestas

Respuestas y Comentarios

Trucos del editor

  • *italic* or __italic__
  • **negrita** o __negrita__
  • enlace:
    [texto](http://url.com/ "Pregunta")
  • imagen:
    ![alt texto](/path/img.jpg "Pregunta")
  • lista numerada:
    1. Foo
    2. Bar
  • Código:
    • Dentro de un parrafo:
      `codigo`
    • Fragmento de código:
      Selecciona el texto y usa el botón del icono de ceros y unos
  • Resaltado de sintaxis:
    Hay dos maneras de hacerlo:
    • La 1ª línea es un Shebang #!/usr/bin/env python
    • La 1ª línea es un lexer
      :::python

      Algunos lexer validos:
      :::python
      :::django
      :::css+django
      :::html+django
      :::console
      :::pycon
  • Para añadir un salto de línea simplemente deja una línea en blanco entre parrafos
  • se permite código HTML básico

Etiquetas de la pregunta:

×213
×6
×2
×1

pregunta realizada: 28 Jun '11, 18:18

pregunta vista: 1,067 veces

última modificación: 29 Jun '11, 18:54