diff --git a/app/coffeescripts/models/DateGroup.coffee b/app/coffeescripts/models/DateGroup.coffee
index 21b55114a2f..3732b54ed46 100644
--- a/app/coffeescripts/models/DateGroup.coffee
+++ b/app/coffeescripts/models/DateGroup.coffee
@@ -3,7 +3,8 @@ define [
'underscore'
'jquery'
'i18n!assignments'
-], (Backbone, _, $, I18n) ->
+ 'timezone'
+], (Backbone, _, $, I18n, tz) ->
class DateGroup extends Backbone.Model
@@ -15,19 +16,19 @@ define [
dueAt: ->
dueAt = @get("due_at")
- if dueAt then Date.parse(dueAt) else null
+ if dueAt then tz.parse(dueAt) else null
unlockAt: ->
unlockAt = @get("unlock_at")
- if unlockAt then Date.parse(unlockAt) else null
+ if unlockAt then tz.parse(unlockAt) else null
lockAt: ->
lockAt = @get("lock_at")
- if lockAt then Date.parse(lockAt) else null
+ if lockAt then tz.parse(lockAt) else null
now: ->
now = @get("now")
- if now then Date.parse(now) else new Date()
+ if now then tz.parse(now) else new Date()
# no lock/unlock dates
@@ -61,4 +62,4 @@ define [
available: @available()
pending: @pending()
open: @open()
- closed: @closed()
\ No newline at end of file
+ closed: @closed()
diff --git a/app/views/jst/assignments/CreateAssignment.handlebars b/app/views/jst/assignments/CreateAssignment.handlebars
index 91f9164a3ac..263a1e4e6f9 100644
--- a/app/views/jst/assignments/CreateAssignment.handlebars
+++ b/app/views/jst/assignments/CreateAssignment.handlebars
@@ -57,7 +57,7 @@
{{#each allDates}}
{{dueFor}}
- {{#if dueAt}} {{strftime dueAt "%b %-d"}} {{else}} - {{/if}}
+ {{#if dueAt}} {{tDateToString (fudge dueAt) 'short'}} {{else}} - {{/if}}
{{/each}}
diff --git a/app/views/jst/assignments/DateDueColumnView.handlebars b/app/views/jst/assignments/DateDueColumnView.handlebars
index 62d85a2cd2a..d65f8ddeadf 100644
--- a/app/views/jst/assignments/DateDueColumnView.handlebars
+++ b/app/views/jst/assignments/DateDueColumnView.handlebars
@@ -15,7 +15,7 @@
{{#if dueAt}}
- {{strftime dueAt "%b %-d"}}
+ {{tDateToString (fudge dueAt) 'short'}}
{{else}}
-
diff --git a/app/views/jst/assignments/_available_date_description.handlebars b/app/views/jst/assignments/_available_date_description.handlebars
index 5ca814fe642..ee0c7324291 100644
--- a/app/views/jst/assignments/_available_date_description.handlebars
+++ b/app/views/jst/assignments/_available_date_description.handlebars
@@ -1,14 +1,14 @@
{{#if pending}}
{{#t "not_available_until"}}Not available until{{/t}}
- {{strftime unlockAt "%b %-d"}}
+ {{tDateToString (fudge unlockAt) 'short'}}
{{/if}}
{{#if open}}
{{#t "available_until"}}Available until{{/t}}
- {{strftime lockAt "%b %-d"}}
+ {{tDateToString (fudge lockAt) 'short'}}
{{/if}}
diff --git a/app/views/jst/calendar/agendaView.handlebars b/app/views/jst/calendar/agendaView.handlebars
index b0d09ad43bc..a1ff418079d 100644
--- a/app/views/jst/calendar/agendaView.handlebars
+++ b/app/views/jst/calendar/agendaView.handlebars
@@ -23,11 +23,11 @@
{{#if assignment}}
{{#t "due"}}Due{{/t}},
- {{strftime originalStart "%l:%M%P"}}
+ {{tTimeToString originalStart "tiny"}}
{{else}}
{{#unless all_day}}
{{#t "starts_at"}}Starts at{{/t}},
- {{strftime originalStart "%l:%M%P"}}
+ {{tTimeToString originalStart "tiny"}}
{{/unless}}
{{/if}}
diff --git a/app/views/jst/feature_flags/featureFlag.handlebars b/app/views/jst/feature_flags/featureFlag.handlebars
index a1cd7325f30..8aca8168424 100644
--- a/app/views/jst/feature_flags/featureFlag.handlebars
+++ b/app/views/jst/feature_flags/featureFlag.handlebars
@@ -22,7 +22,7 @@
{{#if releaseOn}}
{{#t "estimated_release"}}Estimated Release:{{/t}}
- {{strftime releaseOn "%B %-d, %Y"}}
+ {{tDateToString (fudge releaseOn) "medium"}}
{{/if}}
diff --git a/spec/coffeescripts/calendar/AgendaViewSpec.coffee b/spec/coffeescripts/calendar/AgendaViewSpec.coffee
index 80eb68e2921..34d622669ce 100644
--- a/spec/coffeescripts/calendar/AgendaViewSpec.coffee
+++ b/spec/coffeescripts/calendar/AgendaViewSpec.coffee
@@ -3,11 +3,14 @@ define [
'underscore'
'timezone'
'vendor/timezone/America/Denver'
+ 'vendor/timezone/America/Juneau'
+ 'vendor/timezone/fr_FR'
'compiled/views/calendar/AgendaView'
'compiled/calendar/EventDataSource'
'helpers/ajax_mocks/api/v1/calendarEvents'
'helpers/ajax_mocks/api/v1/calendarAssignments'
-], ($, _, tz, denver, AgendaView, EventDataSource, eventResponse, assignmentResponse) ->
+ 'helpers/I18nStubber'
+], ($, _, tz, denver, juneau, french, AgendaView, EventDataSource, eventResponse, assignmentResponse, I18nStubber) ->
loadEventPage = (server, includeNext = false) ->
sendCustomEvents(server, eventResponse, assignmentResponse, includeNext)
@@ -28,11 +31,13 @@ define [
@server = sinon.fakeServer.create()
@snapshot = tz.snapshot()
tz.changeZone(denver, 'America/Denver')
+ I18nStubber.pushFrame()
teardown: ->
@container.remove()
@server.restore()
tz.restore(@snapshot)
+ I18nStubber.popFrame()
test 'should render results', ->
view = new AgendaView(el: @container, dataSource: @dataSource)
@@ -57,6 +62,11 @@ define [
ok @container.find('.agenda-load-btn').length
test 'toJSON should properly serialize results', ->
+ I18nStubber.stub 'en',
+ 'date.formats.short_with_weekday': '%a, %b %-d'
+ 'date.abbr_day_names.1': 'Mon'
+ 'date.abbr_month_names.10': 'Oct'
+
view = new AgendaView(el: @container, dataSource: @dataSource)
view.fetch(@contextCodes, @startDate)
loadEventPage(@server)
@@ -101,3 +111,53 @@ define [
sendCustomEvents(@server, JSON.stringify(events), JSON.stringify([]), false, 2)
ok @container.find('.ig-row').length == 60, 'finds 60 ig-rows'
+
+ test 'renders non-assignment events with locale-appropriate format string', ->
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR', 'time.formats.tiny': '%k:%M'
+
+ view = new AgendaView(el: @container, dataSource: @dataSource)
+ view.fetch(@contextCodes, @startDate)
+ loadEventPage(@server)
+
+ # this event has a start_at of 2013-10-08T20:30:00Z, or 1pm MDT
+ ok @container.find('.ig-details').slice(2, 3).text().match(/13:00/), 'formats according to locale'
+
+ test 'renders assignment events with locale-appropriate format string', ->
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR', 'time.formats.tiny': '%k:%M'
+
+ view = new AgendaView(el: @container, dataSource: @dataSource)
+ view.fetch(@contextCodes, @startDate)
+ loadEventPage(@server)
+
+ # this event has a start_at of 2013-10-13T05:59:59Z, or 11:59pm MDT
+ ok @container.find('.ig-details').slice(12, 13).text().match(/23:59/), 'formats according to locale'
+
+ test 'renders non-assignment events in appropriate timezone', ->
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'time.formats.tiny': '%l:%M%P'
+ 'date': {}
+
+ view = new AgendaView(el: @container, dataSource: @dataSource)
+ view.fetch(@contextCodes, @startDate)
+ loadEventPage(@server)
+
+ # this event has a start_at of 2013-10-08T20:30:00Z, or 11:00am AKDT
+ ok @container.find('.ig-details').slice(2, 3).text().match(/11:00am/), 'formats in correct timezone'
+
+ test 'renders assignment events in appropriate timezone', ->
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'time.formats.tiny': '%l:%M%P'
+ 'date': {}
+
+ view = new AgendaView(el: @container, dataSource: @dataSource)
+ view.fetch(@contextCodes, @startDate)
+ loadEventPage(@server)
+
+ # this event has a start_at of 2013-10-13T05:59:59Z, or 9:59pm AKDT
+ ok @container.find('.ig-details').slice(12, 13).text().match(/9:59pm/), 'formats in correct timezone'
diff --git a/spec/coffeescripts/views/assignments/AssignmentListItemViewSpec.coffee b/spec/coffeescripts/views/assignments/AssignmentListItemViewSpec.coffee
index 1a1b653f610..9ec31bd1d18 100644
--- a/spec/coffeescripts/views/assignments/AssignmentListItemViewSpec.coffee
+++ b/spec/coffeescripts/views/assignments/AssignmentListItemViewSpec.coffee
@@ -4,9 +4,13 @@ define [
'compiled/models/Submission'
'compiled/views/assignments/AssignmentListItemView'
'jquery'
+ 'timezone'
+ 'vendor/timezone/America/Juneau'
+ 'vendor/timezone/fr_FR'
+ 'helpers/I18nStubber'
'helpers/fakeENV'
'helpers/jquery.simulate'
-], (Backbone, Assignment, Submission, AssignmentListItemView, $, fakeENV) ->
+], (Backbone, Assignment, Submission, AssignmentListItemView, $, tz, juneau, french, I18nStubber, fakeENV) ->
screenreaderText = null
nonScreenreaderText = null
@@ -144,9 +148,15 @@ define [
setup: ->
genSetup.call @
+ @snapshot = tz.snapshot()
+ I18nStubber.pushFrame()
+
teardown: ->
genTeardown.call @
+ tz.restore(@snapshot)
+ I18nStubber.popFrame()
+
test "initializes child views if can manage", ->
view = createView(@model, canManage: true)
ok view.publishIconView
@@ -310,6 +320,57 @@ define [
equal spy.callCount, 0
AssignmentListItemView.prototype.updateScore.restore()
+ test "renders lockAt/unlockAt with locale-appropriate format string", ->
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR',
+ 'date.formats.short': '%-d %b'
+ 'date.abbr_month_names.8': 'août'
+ model = new AssignmentCollection([buildAssignment
+ id: 1
+ all_dates: [
+ { lock_at: "2113-08-28T04:00:00Z", title: "Summer Session" }
+ { unlock_at: "2113-08-28T04:00:00Z", title: "Winter Session" }]]).at(0)
+
+ view = createView(model, canManage: true)
+ $dds = view.dateAvailableColumnView.$("#vdd_tooltip_#{@model.id}_lock div")
+ equal $("span", $dds.first()).last().text().trim(), '28 août'
+ equal $("span", $dds.last()).last().text().trim(), '28 août'
+
+ test "renders lockAt/unlockAt in appropriate time zone", ->
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'date.formats.short': '%b %-d'
+ 'date.abbr_month_names.8': 'Aug'
+
+ model = new AssignmentCollection([buildAssignment
+ id: 1
+ all_dates: [
+ { lock_at: "2113-08-28T04:00:00Z", title: "Summer Session" }
+ { unlock_at: "2113-08-28T04:00:00Z", title: "Winter Session" }]]).at(0)
+
+ view = createView(model, canManage: true)
+ $dds = view.dateAvailableColumnView.$("#vdd_tooltip_#{@model.id}_lock div")
+ equal $("span", $dds.first()).last().text().trim(), 'Aug 27'
+ equal $("span", $dds.last()).last().text().trim(), 'Aug 27'
+
+ test "renders due date column with locale-appropriate format string", ->
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR',
+ 'date.formats.short': '%-d %b'
+ 'date.abbr_month_names.8': 'août'
+ view = createView(@model, canManage: true)
+ equal view.dateDueColumnView.$("#vdd_tooltip_#{@model.id}_due div dd").first().text().trim(), '29 août'
+
+ test "renders due date column in appropriate time zone", ->
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'date.formats.short': '%b %-d'
+ 'date.abbr_month_names.8': 'Aug'
+ view = createView(@model, canManage: true)
+ equal view.dateDueColumnView.$("#vdd_tooltip_#{@model.id}_due div dd").first().text().trim(), 'Aug 28'
+
module 'AssignmentListItemViewSpec—alternate grading type: percent',
setup: ->
genSetup.call @, assignment_grade_percent()
diff --git a/spec/coffeescripts/views/assignments/CreateAssignmentViewSpec.coffee b/spec/coffeescripts/views/assignments/CreateAssignmentViewSpec.coffee
index 1d484ff2cbf..b7e90f0ffd9 100644
--- a/spec/coffeescripts/views/assignments/CreateAssignmentViewSpec.coffee
+++ b/spec/coffeescripts/views/assignments/CreateAssignmentViewSpec.coffee
@@ -6,9 +6,13 @@ define [
'compiled/views/assignments/CreateAssignmentView'
'compiled/views/DialogFormView'
'jquery'
+ 'timezone'
+ 'vendor/timezone/America/Juneau'
+ 'vendor/timezone/fr_FR'
+ 'helpers/I18nStubber'
'helpers/jquery.simulate'
'compiled/behaviors/tooltip'
-], (Backbone, AssignmentGroupCollection, AssignmentGroup, Assignment, CreateAssignmentView, DialogFormView, $) ->
+], (Backbone, AssignmentGroupCollection, AssignmentGroup, Assignment, CreateAssignmentView, DialogFormView, $, tz, juneau, french, I18nStubber) ->
fixtures = $('#fixtures')
@@ -113,12 +117,18 @@ define [
@assignment4 = assignment4()
@group = assignmentGroup()
+ @snapshot = tz.snapshot()
+ I18nStubber.pushFrame()
+
teardown: ->
ENV.VALID_DATE_RANGE = {
start_at: {date: null, date_context: null}
end_at: {date: null, date_context: null}
}
+ tz.restore(@snapshot)
+ I18nStubber.popFrame()
+
test "initialize generates a new assignment for creation", ->
view = createView(@group)
equal view.model.get("assignment_group_id"), @group.get("id")
@@ -297,3 +307,19 @@ define [
ok errors["due_at"]
equal errors['due_at'][0]['message'], 'Due date cannot be before unlock date'
+ test "renders due dates with locale-appropriate format string", ->
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR',
+ 'date.formats.short': '%-d %b'
+ 'date.abbr_month_names.8': 'août'
+ view = createView(@assignment1)
+ equal view.$("#vdd_tooltip_assign_1 div dd").first().text().trim(), '28 août'
+
+ test "renders due dates in appropriate time zone", ->
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'date.formats.short': '%b %-d'
+ 'date.abbr_month_names.8': 'Aug'
+ view = createView(@assignment1)
+ equal view.$("#vdd_tooltip_assign_1 div dd").first().text().trim(), 'Aug 27'
diff --git a/spec/coffeescripts/views/feature_flags/FeatureFlagViewSpec.coffee b/spec/coffeescripts/views/feature_flags/FeatureFlagViewSpec.coffee
new file mode 100644
index 00000000000..701b284b344
--- /dev/null
+++ b/spec/coffeescripts/views/feature_flags/FeatureFlagViewSpec.coffee
@@ -0,0 +1,58 @@
+define [
+ 'compiled/views/feature_flags/FeatureFlagView'
+ 'compiled/models/FeatureFlag'
+ 'jquery'
+ 'timezone'
+ 'vendor/timezone/America/Juneau'
+ 'vendor/timezone/fr_FR'
+ 'helpers/I18nStubber'
+ 'helpers/fakeENV'
+], (FeatureFlagView, FeatureFlag, $, tz, juneau, french, I18nStubber, fakeENV) ->
+
+ module "FeatureFlagView",
+ setup: ->
+ @container = $('', id: 'feature-flags').appendTo('#fixtures')
+ @snapshot = tz.snapshot()
+ I18nStubber.pushFrame()
+ fakeENV.setup()
+
+ teardown: ->
+ @container.remove()
+ tz.restore(@snapshot)
+ I18nStubber.popFrame()
+ fakeENV.teardown()
+
+ test 'should format release date with locale-appropriate format string', ->
+ releaseDate = tz.parse('2100-07-04T00:00:00Z')
+
+ tz.changeLocale(french, 'fr_FR')
+ I18nStubber.setLocale 'fr_FR'
+ I18nStubber.stub 'fr_FR',
+ 'date.formats.medium': '%-d %b %Y'
+ 'date.abbr_month_names.7': 'juil.'
+
+ flag = new FeatureFlag
+ releaseOn: releaseDate
+ feature_flag:
+ transitions: {}
+ view = new FeatureFlagView el: @container, model: flag
+ view.render()
+
+ equal view.$('.feature-release-date').text().trim(), '4 juil. 2100'
+
+ test 'should format release date in locale-appropriate format string', ->
+ releaseDate = tz.parse('2100-07-04T00:00:00Z')
+
+ tz.changeZone(juneau, 'America/Juneau')
+ I18nStubber.stub 'en',
+ 'date.formats.medium': '%b %-d, %Y'
+ 'date.abbr_month_names.7': 'Jul'
+
+ flag = new FeatureFlag
+ releaseOn: releaseDate
+ feature_flag:
+ transitions: {}
+ view = new FeatureFlagView el: @container, model: flag
+ view.render()
+
+ equal view.$('.feature-release-date').text().trim(), 'Jul 3, 2100'