@@ -16,13 +16,13 @@ from xmodule.contentstore.django import contentstore
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.util.date_utils import get_default_time_display
|
||||
from xmodule.modulestore import InvalidLocationError
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from xmodule.modulestore.django import loc_mapper
|
||||
from xmodule.modulestore.locator import BlockUsageLocator
|
||||
|
||||
from util.date_utils import get_default_time_display
|
||||
from util.json_request import JsonResponse
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
@@ -10,8 +10,8 @@ from django.conf import settings
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from edxmako.shortcuts import render_to_response
|
||||
|
||||
from util.date_utils import get_default_time_display
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.util.date_utils import get_default_time_display
|
||||
from xmodule.modulestore.django import loc_mapper
|
||||
from xmodule.modulestore.locator import BlockUsageLocator
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%inherit file="base.html" />
|
||||
<%!
|
||||
import logging
|
||||
from xmodule.util.date_utils import get_default_time_display, almost_same_datetime
|
||||
from util.date_utils import get_default_time_display, almost_same_datetime
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
%>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%inherit file="base.html" />
|
||||
<%!
|
||||
import logging
|
||||
from xmodule.util import date_utils
|
||||
from util.date_utils import get_default_time_display
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from xmodule.modulestore.django import loc_mapper
|
||||
@@ -188,7 +188,7 @@ require(["domReady!", "jquery", "js/models/location", "js/models/section", "js/v
|
||||
<a href="#" class="edit-release-date action" data-date="" data-time="" data-locator="${section_locator}"><i class="icon-time"></i> <span class="sr">${_("Schedule")}</span></a>
|
||||
%else:
|
||||
<span class="published-status"><strong>${_("Release date:")}</strong>
|
||||
${date_utils.get_default_time_display(section.start)}</span>
|
||||
${get_default_time_display(section.start)}</span>
|
||||
<a href="#" class="edit-release-date action" data-date="${start_date_str}" data-time="${start_time_str}" data-locator="${section_locator}"><i class="icon-time"></i> <span class="sr">${_("Edit section release date")}</span></a>
|
||||
%endif
|
||||
</div>
|
||||
|
||||
373
common/djangoapps/util/date_utils.py
Normal file
373
common/djangoapps/util/date_utils.py
Normal file
@@ -0,0 +1,373 @@
|
||||
"""
|
||||
Convenience methods for working with datetime objects
|
||||
"""
|
||||
|
||||
from datetime import timedelta
|
||||
import re
|
||||
|
||||
from pytz import timezone, UTC, UnknownTimeZoneError
|
||||
from django.utils.translation import pgettext, ugettext
|
||||
|
||||
|
||||
def get_default_time_display(dtime):
|
||||
"""
|
||||
Converts a datetime to a string representation. This is the default
|
||||
representation used in Studio and LMS.
|
||||
|
||||
It will use the "DATE_TIME" format in the current language, if provided,
|
||||
or defaults to "Apr 09, 2013 at 16:00 UTC".
|
||||
|
||||
If None is passed in for dt, an empty string will be returned.
|
||||
|
||||
"""
|
||||
if dtime is None:
|
||||
return u""
|
||||
if dtime.tzinfo is not None:
|
||||
try:
|
||||
timezone = u" " + dtime.tzinfo.tzname(dtime)
|
||||
except NotImplementedError:
|
||||
timezone = dtime.strftime('%z')
|
||||
else:
|
||||
timezone = u" UTC"
|
||||
|
||||
localized = strftime_localized(dtime, "DATE_TIME")
|
||||
return (localized + timezone).strip()
|
||||
|
||||
|
||||
def get_time_display(dtime, format_string=None, coerce_tz=None):
|
||||
"""
|
||||
Converts a datetime to a string representation.
|
||||
|
||||
If None is passed in for dt, an empty string will be returned.
|
||||
|
||||
If the format_string is None, or if format_string is improperly
|
||||
formatted, this method will return the value from `get_default_time_display`.
|
||||
|
||||
Coerces aware datetime to tz=coerce_tz if set. coerce_tz should be a pytz timezone string
|
||||
like "US/Pacific", or None
|
||||
|
||||
format_string should be a unicode string that is a valid argument for datetime's strftime method.
|
||||
"""
|
||||
if dtime is not None and dtime.tzinfo is not None and coerce_tz:
|
||||
try:
|
||||
to_tz = timezone(coerce_tz)
|
||||
except UnknownTimeZoneError:
|
||||
to_tz = UTC
|
||||
dtime = to_tz.normalize(dtime.astimezone(to_tz))
|
||||
if dtime is None or format_string is None:
|
||||
return get_default_time_display(dtime)
|
||||
try:
|
||||
return unicode(strftime_localized(dtime, format_string))
|
||||
except ValueError:
|
||||
return get_default_time_display(dtime)
|
||||
|
||||
|
||||
def almost_same_datetime(dt1, dt2, allowed_delta=timedelta(minutes=1)):
|
||||
"""
|
||||
Returns true if these are w/in a minute of each other. (in case secs saved to db
|
||||
or timezone aren't same)
|
||||
|
||||
:param dt1:
|
||||
:param dt2:
|
||||
"""
|
||||
return abs(dt1 - dt2) < allowed_delta
|
||||
|
||||
|
||||
DEFAULT_SHORT_DATE_FORMAT = "%b %d, %Y"
|
||||
DEFAULT_LONG_DATE_FORMAT = "%A, %B %d, %Y"
|
||||
DEFAULT_TIME_FORMAT = "%I:%M:%S %p"
|
||||
DEFAULT_DATE_TIME_FORMAT = "%b %d, %Y at %H:%M"
|
||||
|
||||
|
||||
def strftime_localized(dtime, format): # pylint: disable=redefined-builtin
|
||||
"""
|
||||
Format a datetime, just like the built-in strftime, but with localized words.
|
||||
|
||||
The format string can also be one of:
|
||||
|
||||
* "SHORT_DATE" for a date in brief form, localized.
|
||||
|
||||
* "LONG_DATE" for a longer form of date, localized.
|
||||
|
||||
* "DATE_TIME" for a date and time together, localized.
|
||||
|
||||
* "TIME" for just the time, localized.
|
||||
|
||||
The localization is based on the current language Django is using for the
|
||||
request. The exact format strings used for each of the names above is
|
||||
determined by the translator for each language.
|
||||
|
||||
Args:
|
||||
dtime (datetime): The datetime value to format.
|
||||
|
||||
format (str): The format string to use, as specified by
|
||||
:ref:`datetime.strftime`.
|
||||
|
||||
Returns:
|
||||
A unicode string with the formatted datetime.
|
||||
|
||||
"""
|
||||
|
||||
if format == "SHORT_DATE":
|
||||
format = "%x"
|
||||
elif format == "LONG_DATE":
|
||||
# Translators: the translation for "LONG_DATE_FORMAT" must be a format
|
||||
# string for formatting dates in a long form. For example, the
|
||||
# American English form is "%A, %B %d %Y".
|
||||
# See http://strftime.org for details.
|
||||
format = ugettext("LONG_DATE_FORMAT")
|
||||
if format == "LONG_DATE_FORMAT":
|
||||
format = DEFAULT_LONG_DATE_FORMAT
|
||||
elif format == "DATE_TIME":
|
||||
# Translators: the translation for "DATE_TIME_FORMAT" must be a format
|
||||
# string for formatting dates with times. For example, the American
|
||||
# English form is "%b %d, %Y at %H:%M".
|
||||
# See http://strftime.org for details.
|
||||
format = ugettext("DATE_TIME_FORMAT")
|
||||
if format == "DATE_TIME_FORMAT":
|
||||
format = DEFAULT_DATE_TIME_FORMAT
|
||||
elif format == "TIME":
|
||||
format = "%X"
|
||||
|
||||
def process_percent_code(match):
|
||||
"""
|
||||
Convert one percent-prefixed code in the format string.
|
||||
|
||||
Called by re.sub just below.
|
||||
|
||||
"""
|
||||
code = match.group()
|
||||
if code == "%":
|
||||
# This only happens if the string ends with a %, which is not legal.
|
||||
raise ValueError("strftime format ends with raw %")
|
||||
|
||||
if code == "%a":
|
||||
part = pgettext('abbreviated weekday name', WEEKDAYS_ABBREVIATED[dtime.weekday()])
|
||||
elif code == "%A":
|
||||
part = pgettext('weekday name', WEEKDAYS[dtime.weekday()])
|
||||
elif code == "%b":
|
||||
part = pgettext('abbreviated month name', MONTHS_ABBREVIATED[dtime.month])
|
||||
elif code == "%B":
|
||||
part = pgettext('month name', MONTHS[dtime.month])
|
||||
elif code == "%p":
|
||||
part = pgettext('am/pm indicator', AM_PM[dtime.hour // 12])
|
||||
elif code == "%x":
|
||||
# Get the localized short date format, and recurse.
|
||||
# Translators: the translation for "SHORT_DATE_FORMAT" must be a
|
||||
# format string for formatting dates in a brief form. For example,
|
||||
# the American English form is "%b %d %Y".
|
||||
# See http://strftime.org for details.
|
||||
actual_format = ugettext("SHORT_DATE_FORMAT")
|
||||
if actual_format == "SHORT_DATE_FORMAT":
|
||||
actual_format = DEFAULT_SHORT_DATE_FORMAT
|
||||
if "%x" in actual_format:
|
||||
# Prevent infinite accidental recursion.
|
||||
actual_format = DEFAULT_SHORT_DATE_FORMAT
|
||||
part = strftime_localized(dtime, actual_format)
|
||||
elif code == "%X":
|
||||
# Get the localized time format, and recurse.
|
||||
# Translators: the translation for "TIME_FORMAT" must be a format
|
||||
# string for formatting times. For example, the American English
|
||||
# form is "%H:%M:%S". See http://strftime.org for details.
|
||||
actual_format = ugettext("TIME_FORMAT")
|
||||
if actual_format == "TIME_FORMAT":
|
||||
actual_format = DEFAULT_TIME_FORMAT
|
||||
if "%X" in actual_format:
|
||||
# Prevent infinite accidental recursion.
|
||||
actual_format = DEFAULT_TIME_FORMAT
|
||||
part = strftime_localized(dtime, actual_format)
|
||||
else:
|
||||
# All the other format codes: just let built-in strftime take
|
||||
# care of them.
|
||||
part = dtime.strftime(code)
|
||||
|
||||
return part
|
||||
|
||||
formatted_date = re.sub(r"%.|%", process_percent_code, format)
|
||||
return formatted_date
|
||||
|
||||
|
||||
# In order to extract the strings below, we have to mark them with pgettext.
|
||||
# But we'll do the actual pgettext later, so use a no-op for now, and save the
|
||||
# real pgettext so we can assign it back to the global name later.
|
||||
real_pgettext = pgettext
|
||||
pgettext = lambda context, text: text # pylint: disable=invalid-name
|
||||
|
||||
AM_PM = {
|
||||
# Translators: This is an AM/PM indicator for displaying times. It is
|
||||
# used for the %p directive in date-time formats. See http://strftime.org
|
||||
# for details.
|
||||
0: pgettext('am/pm indicator', 'AM'),
|
||||
# Translators: This is an AM/PM indicator for displaying times. It is
|
||||
# used for the %p directive in date-time formats. See http://strftime.org
|
||||
# for details.
|
||||
1: pgettext('am/pm indicator', 'PM'),
|
||||
}
|
||||
|
||||
WEEKDAYS = {
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Monday Februrary 10, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
0: pgettext('weekday name', 'Monday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Tuesday Februrary 11, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
1: pgettext('weekday name', 'Tuesday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Wednesday Februrary 12, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
2: pgettext('weekday name', 'Wednesday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Thursday Februrary 13, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
3: pgettext('weekday name', 'Thursday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Friday Februrary 14, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
4: pgettext('weekday name', 'Friday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Saturday Februrary 15, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
5: pgettext('weekday name', 'Saturday'),
|
||||
# Translators: this is a weekday name that will be used when displaying
|
||||
# dates, as in "Sunday Februrary 16, 2014". It is used for the %A
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
6: pgettext('weekday name', 'Sunday'),
|
||||
}
|
||||
|
||||
WEEKDAYS_ABBREVIATED = {
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Mon Feb 10, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
0: pgettext('abbreviated weekday name', 'Mon'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Tue Feb 11, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
1: pgettext('abbreviated weekday name', 'Tue'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Wed Feb 12, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
2: pgettext('abbreviated weekday name', 'Wed'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Thu Feb 13, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
3: pgettext('abbreviated weekday name', 'Thu'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Fri Feb 14, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
4: pgettext('abbreviated weekday name', 'Fri'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Sat Feb 15, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
5: pgettext('abbreviated weekday name', 'Sat'),
|
||||
# Translators: this is an abbreviated weekday name that will be used when
|
||||
# displaying dates, as in "Sun Feb 16, 2014". It is used for the %a
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
6: pgettext('abbreviated weekday name', 'Sun'),
|
||||
}
|
||||
|
||||
MONTHS_ABBREVIATED = {
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Jan 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
1: pgettext('abbreviated month name', 'Jan'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Feb 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
2: pgettext('abbreviated month name', 'Feb'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Mar 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
3: pgettext('abbreviated month name', 'Mar'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Apr 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
4: pgettext('abbreviated month name', 'Apr'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "May 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
5: pgettext('abbreviated month name', 'May'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Jun 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
6: pgettext('abbreviated month name', 'Jun'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Jul 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
7: pgettext('abbreviated month name', 'Jul'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Aug 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
8: pgettext('abbreviated month name', 'Aug'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Sep 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
9: pgettext('abbreviated month name', 'Sep'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Oct 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
10: pgettext('abbreviated month name', 'Oct'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Nov 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
11: pgettext('abbreviated month name', 'Nov'),
|
||||
# Translators: this is an abbreviated month name that will be used when
|
||||
# displaying dates, as in "Dec 10, 2014". It is used for the %b
|
||||
# directive in date-time formats. See http://strftime.org for details.
|
||||
12: pgettext('abbreviated month name', 'Dec'),
|
||||
}
|
||||
|
||||
MONTHS = {
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "January 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
1: pgettext('month name', 'January'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "February 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
2: pgettext('month name', 'February'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "March 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
3: pgettext('month name', 'March'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "April 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
4: pgettext('month name', 'April'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "May 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
5: pgettext('month name', 'May'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "June 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
6: pgettext('month name', 'June'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "July 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
7: pgettext('month name', 'July'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "August 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
8: pgettext('month name', 'August'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "September 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
9: pgettext('month name', 'September'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "October 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
10: pgettext('month name', 'October'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "November 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
11: pgettext('month name', 'November'),
|
||||
# Translators: this is a month name that will be used when displaying
|
||||
# dates, as in "December 10, 2014". It is used for the %B directive in
|
||||
# date-time formats. See http://strftime.org for details.
|
||||
12: pgettext('month name', 'December'),
|
||||
}
|
||||
|
||||
# Now that we are done defining constants, we have to restore the real pgettext
|
||||
# so that the functions in this module will have the right definition.
|
||||
pgettext = real_pgettext
|
||||
221
common/djangoapps/util/tests/test_date_utils.py
Normal file
221
common/djangoapps/util/tests/test_date_utils.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for util.date_utils
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from functools import partial
|
||||
import unittest
|
||||
|
||||
import ddt
|
||||
from mock import patch
|
||||
from nose.tools import assert_equals, assert_false # pylint: disable=E0611
|
||||
from pytz import UTC
|
||||
|
||||
from util.date_utils import (
|
||||
get_default_time_display, get_time_display, almost_same_datetime,
|
||||
strftime_localized,
|
||||
)
|
||||
|
||||
|
||||
def test_get_default_time_display():
|
||||
assert_equals("", get_default_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03 UTC",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_get_dflt_time_disp_notz():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30)
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03 UTC",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_get_time_disp_ret_empty():
|
||||
assert_equals("", get_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("", get_time_display(test_time, ""))
|
||||
|
||||
|
||||
def test_get_time_display():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("dummy text", get_time_display(test_time, 'dummy text'))
|
||||
assert_equals("Mar 12 1992", get_time_display(test_time, '%b %d %Y'))
|
||||
assert_equals("Mar 12 1992 UTC", get_time_display(test_time, '%b %d %Y %Z'))
|
||||
assert_equals("Mar 12 15:03", get_time_display(test_time, '%b %d %H:%M'))
|
||||
|
||||
|
||||
def test_get_time_pass_through():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time))
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, None))
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, "%"))
|
||||
|
||||
|
||||
def test_get_time_display_coerce():
|
||||
test_time_standard = datetime(1992, 1, 12, 15, 3, 30, tzinfo=UTC)
|
||||
test_time_daylight = datetime(1992, 7, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("Jan 12, 1992 at 07:03 PST",
|
||||
get_time_display(test_time_standard, None, coerce_tz="US/Pacific"))
|
||||
assert_equals("Jan 12, 1992 at 15:03 UTC",
|
||||
get_time_display(test_time_standard, None, coerce_tz="NONEXISTENTTZ"))
|
||||
assert_equals("Jan 12 07:03",
|
||||
get_time_display(test_time_standard, '%b %d %H:%M', coerce_tz="US/Pacific"))
|
||||
assert_equals("Jul 12, 1992 at 08:03 PDT",
|
||||
get_time_display(test_time_daylight, None, coerce_tz="US/Pacific"))
|
||||
assert_equals("Jul 12, 1992 at 15:03 UTC",
|
||||
get_time_display(test_time_daylight, None, coerce_tz="NONEXISTENTTZ"))
|
||||
assert_equals("Jul 12 08:03",
|
||||
get_time_display(test_time_daylight, '%b %d %H:%M', coerce_tz="US/Pacific"))
|
||||
|
||||
|
||||
# pylint: disable=W0232
|
||||
class NamelessTZ(tzinfo):
|
||||
"""Static timezone for testing"""
|
||||
|
||||
def utcoffset(self, _dt):
|
||||
return timedelta(hours=-3)
|
||||
|
||||
def dst(self, _dt):
|
||||
return timedelta(0)
|
||||
|
||||
|
||||
def test_get_default_time_display_no_tzname():
|
||||
assert_equals("", get_default_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=NamelessTZ())
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03-0300",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_almost_same_datetime():
|
||||
assert almost_same_datetime(
|
||||
datetime(2013, 5, 3, 10, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29)
|
||||
)
|
||||
|
||||
assert almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29),
|
||||
timedelta(hours=1)
|
||||
)
|
||||
|
||||
assert_false(
|
||||
almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29)
|
||||
)
|
||||
)
|
||||
|
||||
assert_false(
|
||||
almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29),
|
||||
timedelta(minutes=10)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def fake_ugettext(text, translations):
|
||||
"""
|
||||
A fake implementation of ugettext, for testing.
|
||||
"""
|
||||
return translations.get(text, text)
|
||||
|
||||
|
||||
def fake_pgettext(context, text, translations):
|
||||
"""
|
||||
A fake implementation of pgettext, for testing.
|
||||
"""
|
||||
return translations.get((context, text), text)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class StrftimeLocalizedTest(unittest.TestCase):
|
||||
"""
|
||||
Tests for strftime_localized.
|
||||
"""
|
||||
@ddt.data(
|
||||
("%Y", "2013"),
|
||||
("%m/%d/%y", "02/14/13"),
|
||||
("hello", "hello"),
|
||||
(u'%Y년 %m월 %d일', u"2013년 02월 14일"),
|
||||
("%a, %b %d, %Y", "Thu, Feb 14, 2013"),
|
||||
("%I:%M:%S %p", "04:41:17 PM"),
|
||||
)
|
||||
def test_usual_strftime_behavior(self, (fmt, expected)):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
# strftime doesn't like Unicode, so do the work in UTF8.
|
||||
self.assertEqual(expected, dtime.strftime(fmt.encode('utf8')).decode('utf8'))
|
||||
|
||||
@ddt.data(
|
||||
("SHORT_DATE", "Feb 14, 2013"),
|
||||
("LONG_DATE", "Thursday, February 14, 2013"),
|
||||
("TIME", "04:41:17 PM"),
|
||||
("%x %X!", "Feb 14, 2013 04:41:17 PM!"),
|
||||
)
|
||||
def test_shortcuts(self, (fmt, expected)):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.pgettext', partial(fake_pgettext, translations={
|
||||
("abbreviated month name", "Feb"): "XXfebXX",
|
||||
("month name", "February"): "XXfebruaryXX",
|
||||
("abbreviated weekday name", "Thu"): "XXthuXX",
|
||||
("weekday name", "Thursday"): "XXthursdayXX",
|
||||
("am/pm indicator", "PM"): "XXpmXX",
|
||||
}))
|
||||
@ddt.data(
|
||||
("SHORT_DATE", "XXfebXX 14, 2013"),
|
||||
("LONG_DATE", "XXthursdayXX, XXfebruaryXX 14, 2013"),
|
||||
("DATE_TIME", "XXfebXX 14, 2013 at 16:41"),
|
||||
("TIME", "04:41:17 XXpmXX"),
|
||||
("%x %X!", "XXfebXX 14, 2013 04:41:17 XXpmXX!"),
|
||||
)
|
||||
def test_translated_words(self, (fmt, expected)):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.ugettext', partial(fake_ugettext, translations={
|
||||
"SHORT_DATE_FORMAT": "date(%Y.%m.%d)",
|
||||
"LONG_DATE_FORMAT": "date(%A.%Y.%B.%d)",
|
||||
"DATE_TIME_FORMAT": "date(%Y.%m.%d@%H.%M)",
|
||||
"TIME_FORMAT": "%Hh.%Mm.%Ss",
|
||||
}))
|
||||
@ddt.data(
|
||||
("SHORT_DATE", "date(2013.02.14)"),
|
||||
("Look: %x", "Look: date(2013.02.14)"),
|
||||
("LONG_DATE", "date(Thursday.2013.February.14)"),
|
||||
("DATE_TIME", "date(2013.02.14@16.41)"),
|
||||
("TIME", "16h.41m.17s"),
|
||||
("The time is: %X", "The time is: 16h.41m.17s"),
|
||||
("%x %X", "date(2013.02.14) 16h.41m.17s"),
|
||||
)
|
||||
def test_translated_formats(self, (fmt, expected)):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@patch('util.date_utils.ugettext', partial(fake_ugettext, translations={
|
||||
"SHORT_DATE_FORMAT": "oops date(%Y.%x.%d)",
|
||||
"TIME_FORMAT": "oops %Hh.%Xm.%Ss",
|
||||
}))
|
||||
@ddt.data(
|
||||
("SHORT_DATE", "Feb 14, 2013"),
|
||||
("TIME", "04:41:17 PM"),
|
||||
)
|
||||
def test_recursion_protection(self, (fmt, expected)):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
self.assertEqual(expected, strftime_localized(dtime, fmt))
|
||||
|
||||
@ddt.data(
|
||||
"%",
|
||||
"Hello%"
|
||||
"%Y/%m/%d%",
|
||||
)
|
||||
def test_invalid_format_strings(self, fmt):
|
||||
dtime = datetime(2013, 02, 14, 16, 41, 17)
|
||||
with self.assertRaises(ValueError):
|
||||
strftime_localized(dtime, fmt)
|
||||
@@ -828,13 +828,17 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
|
||||
Returns the desired text corresponding the course's start date. Prefers .advertised_start,
|
||||
then falls back to .start
|
||||
"""
|
||||
i18n = self.runtime.service(self, "i18n")
|
||||
_ = i18n.ugettext
|
||||
strftime = i18n.strftime
|
||||
|
||||
def try_parse_iso_8601(text):
|
||||
try:
|
||||
result = Date().from_json(text)
|
||||
if result is None:
|
||||
result = text.title()
|
||||
else:
|
||||
result = result.strftime("%b %d, %Y")
|
||||
result = strftime(result, "SHORT_DATE")
|
||||
except ValueError:
|
||||
result = text.title()
|
||||
|
||||
@@ -843,12 +847,12 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
|
||||
if isinstance(self.advertised_start, basestring):
|
||||
return try_parse_iso_8601(self.advertised_start)
|
||||
elif self.start_date_is_still_default:
|
||||
_ = self.runtime.service(self, "i18n").ugettext
|
||||
# Translators: TBD stands for 'To Be Determined' and is used when a course
|
||||
# does not yet have an announced start date.
|
||||
return _('TBD')
|
||||
else:
|
||||
return (self.advertised_start or self.start).strftime("%b %d, %Y")
|
||||
when = self.advertised_start or self.start
|
||||
return strftime(when, "SHORT_DATE")
|
||||
|
||||
@property
|
||||
def start_date_is_still_default(self):
|
||||
@@ -865,7 +869,11 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
|
||||
|
||||
If the course does not have an end date set (course.end is None), an empty string will be returned.
|
||||
"""
|
||||
return '' if self.end is None else self.end.strftime("%b %d, %Y")
|
||||
if self.end is None:
|
||||
return ''
|
||||
else:
|
||||
strftime = self.runtime.service(self, "i18n").strftime
|
||||
return strftime(self.end, "SHORT_DATE")
|
||||
|
||||
@property
|
||||
def forum_posts_allowed(self):
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
"""Tests for xmodule.util.date_utils"""
|
||||
|
||||
from nose.tools import assert_equals, assert_false # pylint: disable=E0611
|
||||
from xmodule.util.date_utils import get_default_time_display, get_time_display, almost_same_datetime
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from pytz import UTC, timezone
|
||||
|
||||
|
||||
def test_get_default_time_display():
|
||||
assert_equals("", get_default_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03 UTC",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_get_dflt_time_disp_notz():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30)
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03 UTC",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_get_time_disp_ret_empty():
|
||||
assert_equals("", get_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("", get_time_display(test_time, ""))
|
||||
|
||||
|
||||
def test_get_time_display():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("dummy text", get_time_display(test_time, 'dummy text'))
|
||||
assert_equals("Mar 12 1992", get_time_display(test_time, '%b %d %Y'))
|
||||
assert_equals("Mar 12 1992 UTC", get_time_display(test_time, '%b %d %Y %Z'))
|
||||
assert_equals("Mar 12 15:03", get_time_display(test_time, '%b %d %H:%M'))
|
||||
|
||||
|
||||
def test_get_time_pass_through():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time))
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, None))
|
||||
assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, "%"))
|
||||
|
||||
|
||||
def test_get_time_display_coerce():
|
||||
test_time_standard = datetime(1992, 1, 12, 15, 3, 30, tzinfo=UTC)
|
||||
test_time_daylight = datetime(1992, 7, 12, 15, 3, 30, tzinfo=UTC)
|
||||
assert_equals("Jan 12, 1992 at 07:03 PST",
|
||||
get_time_display(test_time_standard, None, coerce_tz="US/Pacific"))
|
||||
assert_equals("Jan 12, 1992 at 15:03 UTC",
|
||||
get_time_display(test_time_standard, None, coerce_tz="NONEXISTENTTZ"))
|
||||
assert_equals("Jan 12 07:03",
|
||||
get_time_display(test_time_standard, '%b %d %H:%M', coerce_tz="US/Pacific"))
|
||||
assert_equals("Jul 12, 1992 at 08:03 PDT",
|
||||
get_time_display(test_time_daylight, None, coerce_tz="US/Pacific"))
|
||||
assert_equals("Jul 12, 1992 at 15:03 UTC",
|
||||
get_time_display(test_time_daylight, None, coerce_tz="NONEXISTENTTZ"))
|
||||
assert_equals("Jul 12 08:03",
|
||||
get_time_display(test_time_daylight, '%b %d %H:%M', coerce_tz="US/Pacific"))
|
||||
|
||||
|
||||
# pylint: disable=W0232
|
||||
class NamelessTZ(tzinfo):
|
||||
"""Static timezone for testing"""
|
||||
|
||||
def utcoffset(self, _dt):
|
||||
return timedelta(hours=-3)
|
||||
|
||||
def dst(self, _dt):
|
||||
return timedelta(0)
|
||||
|
||||
|
||||
def test_get_default_time_display_no_tzname():
|
||||
assert_equals("", get_default_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=NamelessTZ())
|
||||
assert_equals(
|
||||
"Mar 12, 1992 at 15:03-0300",
|
||||
get_default_time_display(test_time))
|
||||
|
||||
|
||||
def test_almost_same_datetime():
|
||||
assert almost_same_datetime(
|
||||
datetime(2013, 5, 3, 10, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29)
|
||||
)
|
||||
|
||||
assert almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29),
|
||||
timedelta(hours=1)
|
||||
)
|
||||
|
||||
assert_false(
|
||||
almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29)
|
||||
)
|
||||
)
|
||||
|
||||
assert_false(
|
||||
almost_same_datetime(
|
||||
datetime(2013, 5, 3, 11, 20, 30),
|
||||
datetime(2013, 5, 3, 10, 21, 29),
|
||||
timedelta(minutes=10)
|
||||
)
|
||||
)
|
||||
@@ -1,64 +0,0 @@
|
||||
"""
|
||||
Convenience methods for working with datetime objects
|
||||
"""
|
||||
from datetime import timedelta
|
||||
from pytz import timezone, UTC, UnknownTimeZoneError
|
||||
|
||||
def get_default_time_display(dtime):
|
||||
"""
|
||||
Converts a datetime to a string representation. This is the default
|
||||
representation used in Studio and LMS.
|
||||
It is of the form "Apr 09, 2013 at 16:00 UTC".
|
||||
|
||||
If None is passed in for dt, an empty string will be returned.
|
||||
"""
|
||||
if dtime is None:
|
||||
return u""
|
||||
if dtime.tzinfo is not None:
|
||||
try:
|
||||
timezone = u" " + dtime.tzinfo.tzname(dtime)
|
||||
except NotImplementedError:
|
||||
timezone = dtime.strftime('%z')
|
||||
else:
|
||||
timezone = u" UTC"
|
||||
return unicode(dtime.strftime(u"%b %d, %Y at %H:%M{tz}")).format(
|
||||
tz=timezone).strip()
|
||||
|
||||
|
||||
def get_time_display(dtime, format_string=None, coerce_tz=None):
|
||||
"""
|
||||
Converts a datetime to a string representation.
|
||||
|
||||
If None is passed in for dt, an empty string will be returned.
|
||||
|
||||
If the format_string is None, or if format_string is improperly
|
||||
formatted, this method will return the value from `get_default_time_display`.
|
||||
|
||||
Coerces aware datetime to tz=coerce_tz if set. coerce_tz should be a pytz timezone string
|
||||
like "US/Pacific", or None
|
||||
|
||||
format_string should be a unicode string that is a valid argument for datetime's strftime method.
|
||||
"""
|
||||
if dtime is not None and dtime.tzinfo is not None and coerce_tz:
|
||||
try:
|
||||
to_tz = timezone(coerce_tz)
|
||||
except UnknownTimeZoneError:
|
||||
to_tz = UTC
|
||||
dtime = to_tz.normalize(dtime.astimezone(to_tz))
|
||||
if dtime is None or format_string is None:
|
||||
return get_default_time_display(dtime)
|
||||
try:
|
||||
return unicode(dtime.strftime(format_string))
|
||||
except ValueError:
|
||||
return get_default_time_display(dtime)
|
||||
|
||||
|
||||
def almost_same_datetime(dt1, dt2, allowed_delta=timedelta(minutes=1)):
|
||||
"""
|
||||
Returns true if these are w/in a minute of each other. (in case secs saved to db
|
||||
or timezone aren't same)
|
||||
|
||||
:param dt1:
|
||||
:param dt2:
|
||||
"""
|
||||
return abs(dt1 - dt2) < allowed_delta
|
||||
Binary file not shown.
@@ -37,7 +37,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-02-18 13:34-0500\n"
|
||||
"POT-Creation-Date: 2014-02-18 16:36-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -338,6 +338,357 @@ msgstr "Nämé réqüïréd Ⱡ'#"
|
||||
msgid "Invalid ID"
|
||||
msgstr "Ìnvälïd ÌD Ⱡ#"
|
||||
|
||||
#. Translators: the translation for "LONG_DATE_FORMAT" must be a format
|
||||
#. string for formatting dates in a long form. For example, the
|
||||
#. American English form is "%A, %B %d %Y".
|
||||
#. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgid "LONG_DATE_FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: the translation for "DATE_TIME_FORMAT" must be a format
|
||||
#. string for formatting dates with times. For example, the American
|
||||
#. English form is "%b %d, %Y at %H:%M".
|
||||
#. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgid "DATE_TIME_FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: the translation for "SHORT_DATE_FORMAT" must be a
|
||||
#. format string for formatting dates in a brief form. For example,
|
||||
#. the American English form is "%b %d %Y".
|
||||
#. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgid "SHORT_DATE_FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: the translation for "TIME_FORMAT" must be a format
|
||||
#. string for formatting times. For example, the American English
|
||||
#. form is "%H:%M:%S". See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgid "TIME_FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This is an AM/PM indicator for displaying times. It is
|
||||
#. used for the %p directive in date-time formats. See http://strftime.org
|
||||
#. for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "am/pm indicator"
|
||||
msgid "AM"
|
||||
msgstr "ÀM Ⱡ'#"
|
||||
|
||||
#. Translators: This is an AM/PM indicator for displaying times. It is
|
||||
#. used for the %p directive in date-time formats. See http://strftime.org
|
||||
#. for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "am/pm indicator"
|
||||
msgid "PM"
|
||||
msgstr "PM Ⱡ'#"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Monday Februrary 10, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Monday"
|
||||
msgstr "Möndäý Ⱡ'σяєм ιρѕ#"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Tuesday Februrary 11, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Tuesday"
|
||||
msgstr "Tüésdäý #"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Wednesday Februrary 12, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Wednesday"
|
||||
msgstr "Wédnésdäý #"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Thursday Februrary 13, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Thursday"
|
||||
msgstr "Thürsdäý #"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Friday Februrary 14, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Friday"
|
||||
msgstr "Frïdäý Ⱡ'σяєм ιρѕ#"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Saturday Februrary 15, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Saturday"
|
||||
msgstr "Sätürdäý #"
|
||||
|
||||
#. Translators: this is a weekday name that will be used when displaying
|
||||
#. dates, as in "Sunday Februrary 16, 2014". It is used for the %A
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "weekday name"
|
||||
msgid "Sunday"
|
||||
msgstr "Sündäý Ⱡ'σяєм ιρѕ#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Mon Feb 10, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Mon"
|
||||
msgstr "Mön Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Tue Feb 11, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Tue"
|
||||
msgstr "Tüé Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Wed Feb 12, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Wed"
|
||||
msgstr "Wéd Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Thu Feb 13, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Thu"
|
||||
msgstr "Thü Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Fri Feb 14, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Fri"
|
||||
msgstr "Frï Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Sat Feb 15, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Sat"
|
||||
msgstr "Sät Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated weekday name that will be used when
|
||||
#. displaying dates, as in "Sun Feb 16, 2014". It is used for the %a
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated weekday name"
|
||||
msgid "Sun"
|
||||
msgstr "Sün Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Jan 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Jan"
|
||||
msgstr "Jän Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Feb 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Feb"
|
||||
msgstr "Féß Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Mar 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Mar"
|
||||
msgstr "Mär Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Apr 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Apr"
|
||||
msgstr "Àpr Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "May 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "May"
|
||||
msgstr "Mäý Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Jun 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Jun"
|
||||
msgstr "Jün Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Jul 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Jul"
|
||||
msgstr "Jül Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Aug 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Aug"
|
||||
msgstr "Àüg Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Sep 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Sep"
|
||||
msgstr "Sép Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Oct 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Oct"
|
||||
msgstr "Öçt Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Nov 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Nov"
|
||||
msgstr "Növ Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is an abbreviated month name that will be used when
|
||||
#. displaying dates, as in "Dec 10, 2014". It is used for the %b
|
||||
#. directive in date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "abbreviated month name"
|
||||
msgid "Dec"
|
||||
msgstr "Déç Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "January 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "January"
|
||||
msgstr "Jänüärý #"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "February 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "February"
|
||||
msgstr "Féßrüärý #"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "March 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "March"
|
||||
msgstr "Märçh Ⱡ'σяєм ι#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "April 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "April"
|
||||
msgstr "Àprïl Ⱡ'σяєм ι#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "May 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "May"
|
||||
msgstr "Mäý Ⱡ'σя#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "June 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "June"
|
||||
msgstr "Jüné Ⱡ'σяєм#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "July 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "July"
|
||||
msgstr "Jülý Ⱡ'σяєм#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "August 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "August"
|
||||
msgstr "Àügüst Ⱡ'σяєм ιρѕ#"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "September 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "September"
|
||||
msgstr "Séptémßér #"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "October 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "October"
|
||||
msgstr "Öçtößér #"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "November 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "November"
|
||||
msgstr "Növémßér #"
|
||||
|
||||
#. Translators: this is a month name that will be used when displaying
|
||||
#. dates, as in "December 10, 2014". It is used for the %B directive in
|
||||
#. date-time formats. See http://strftime.org for details.
|
||||
#: common/djangoapps/util/date_utils.py
|
||||
msgctxt "month name"
|
||||
msgid "December"
|
||||
msgstr "Déçémßér #"
|
||||
|
||||
#: common/djangoapps/util/password_policy_validators.py
|
||||
msgid "Invalid Length ({0})"
|
||||
msgstr "Ìnvälïd Léngth ({0}) Ⱡ'σя#"
|
||||
|
||||
Binary file not shown.
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.1a\n"
|
||||
"Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2014-02-18 13:34-0500\n"
|
||||
"PO-Revision-Date: 2014-02-18 18:34:51.762964\n"
|
||||
"POT-Creation-Date: 2014-02-18 16:36-0500\n"
|
||||
"PO-Revision-Date: 2014-02-18 21:36:33.541469\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
||||
@@ -23,7 +23,9 @@ generates output conf/locale/$DUMMY_LOCALE/LC_MESSAGES,
|
||||
where $DUMMY_LOCALE is the dummy_locale value set in the i18n config
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
import polib
|
||||
from path import path
|
||||
|
||||
@@ -173,6 +175,10 @@ def make_dummy(filename, locale, converter):
|
||||
raise IOError('File does not exist: %r' % filename)
|
||||
pofile = polib.pofile(filename)
|
||||
for msg in pofile:
|
||||
# Some strings are actually formatting strings, don't dummy-ify them,
|
||||
# or dates will look like "DÀTÉ_TÌMÉ_FÖRMÀT Ⱡ'σ# EST"
|
||||
if re.match(r"^[A-Z_]+_FORMAT$", msg.msgid):
|
||||
continue
|
||||
converter.convert_msg(msg)
|
||||
|
||||
# Apply declaration for English pluralization rules so that ngettext will
|
||||
|
||||
@@ -25,8 +25,6 @@ from lms.lib.xblock.runtime import LmsModuleSystem, unquote_slashes
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from psychometrics.psychoanalyze import make_psychometrics_data_update_handler
|
||||
from student.models import anonymous_id_for_user, user_by_anonymous_id
|
||||
from util.json_request import JsonResponse
|
||||
from util.sandboxing import can_execute_unsafe_code
|
||||
from xblock.core import XBlock
|
||||
from xblock.fields import Scope
|
||||
from xblock.runtime import KvsFieldData, KeyValueStore
|
||||
@@ -42,6 +40,10 @@ from xmodule_modifiers import replace_course_urls, replace_jump_to_id_urls, repl
|
||||
from xmodule.lti_module import LTIModule
|
||||
from xmodule.x_module import XModuleDescriptor
|
||||
|
||||
from util.date_utils import strftime_localized
|
||||
from util.json_request import JsonResponse
|
||||
from util.sandboxing import can_execute_unsafe_code
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -428,10 +430,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
|
||||
wrappers=block_wrappers,
|
||||
get_real_user=user_by_anonymous_id,
|
||||
services={
|
||||
# django.utils.translation implements the gettext.Translations
|
||||
# interface (it has ugettext, ungettext, etc), so we can use it
|
||||
# directly as the runtime i18n service.
|
||||
'i18n': django.utils.translation,
|
||||
'i18n': ModuleI18nService(),
|
||||
},
|
||||
get_user_role=lambda: get_user_role(user, course_id),
|
||||
)
|
||||
@@ -652,3 +651,20 @@ def _check_files_limits(files):
|
||||
return msg
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class ModuleI18nService(object):
|
||||
"""
|
||||
Implement the XBlock runtime "i18n" service.
|
||||
|
||||
Mostly a pass-through to Django's translation module.
|
||||
django.utils.translation implements the gettext.Translations interface (it
|
||||
has ugettext, ungettext, etc), so we can use it directly as the runtime
|
||||
i18n service.
|
||||
|
||||
"""
|
||||
def __getattr__(self, name):
|
||||
return getattr(django.utils.translation, name)
|
||||
|
||||
def strftime(self, *args, **kwargs):
|
||||
return strftime_localized(*args, **kwargs)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%!
|
||||
from django.core.urlresolvers import reverse
|
||||
from xmodule.util.date_utils import get_time_display
|
||||
from util.date_utils import get_time_display
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
%>
|
||||
@@ -31,7 +31,7 @@
|
||||
due_date = ''
|
||||
else:
|
||||
formatted_string = get_time_display(section['due'], due_date_display_format, coerce_tz=settings.TIME_ZONE)
|
||||
due_date = '' if len(formatted_string)==0 else _('due {date}'.format(date=formatted_string))
|
||||
due_date = '' if len(formatted_string)==0 else _('due {date}').format(date=formatted_string)
|
||||
%>
|
||||
<p class="subtitle">${section['format']} ${due_date}</p>
|
||||
</a>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
%>
|
||||
|
||||
<%!
|
||||
from xmodule.util.date_utils import get_time_display
|
||||
from util.date_utils import get_time_display
|
||||
from django.conf import settings
|
||||
%>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
<%!
|
||||
from xmodule.util.date_utils import get_default_time_display
|
||||
from util.date_utils import get_default_time_display
|
||||
%>
|
||||
<div class="folditbasic">
|
||||
<p><strong>${_("Due:")}</strong> ${get_default_time_display(due)}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
<%! from time import strftime %>
|
||||
<%inherit file="main.html" />
|
||||
<%namespace name='static' file='static_content.html'/>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
-e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk
|
||||
|
||||
# Our libraries:
|
||||
-e git+https://github.com/edx/XBlock.git@6d431d786587bd8f3a19a893364914d6e2d6c28f#egg=XBlock
|
||||
-e git+https://github.com/edx/XBlock.git@893cd83dfb24405ce81b07f49c1c2e3053cdc865#egg=XBlock
|
||||
-e git+https://github.com/edx/codejail.git@e3d98f9455#egg=codejail
|
||||
-e git+https://github.com/edx/diff-cover.git@v0.2.9#egg=diff_cover
|
||||
-e git+https://github.com/edx/js-test-tool.git@v0.1.5#egg=js_test_tool
|
||||
|
||||
Reference in New Issue
Block a user