Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #7452 from lightsofapollo/calendar-localize

Bug 828311 / 825181 / 803249 - Localize AllDay + fix various issues, r=kaze
  • Loading branch information...
commit eb3b9aaea8ba3ec614339716a5c711158042da81 2 parents 914a7d1 + bf6da75
@fabi1cazenave fabi1cazenave authored
View
52 apps/calendar/js/app.js
@@ -202,6 +202,55 @@ Calendar.App = (function(window) {
},
/**
+ * Observes localized events and localizes elements
+ * with data-l10n-date-format should be registered
+ * after the first localized event.
+ *
+ *
+ * Example:
+ *
+ *
+ * <span
+ * data-date="Wed Jan 09 2013 19:25:38 GMT+0100 (CET)"
+ * data-l10n-date-format="%x">
+ *
+ * 2013/9/19
+ *
+ * </span>
+ *
+ */
+ observeDateLocalization: function() {
+ function localize() {
+ var elements = document.querySelectorAll(
+ '[data-l10n-date-format]'
+ );
+
+ var len = elements.length;
+ var i = 0;
+
+ var date;
+ var format;
+ var el;
+
+ for (; i < len; i++) {
+ el = elements[i];
+
+ date = el.dataset.date;
+ format = el.dataset.l10nDateFormat;
+
+ if (date) {
+ el.textContent = Calendar.App.dateFormat.localeFormat(
+ new Date(date),
+ format
+ );
+ }
+ }
+ }
+
+ window.addEventListener('localized', localize);
+ },
+
+ /**
* Adds observers to objects capable of being pending.
*
* Object must emit some kind of start/complete events
@@ -304,6 +353,9 @@ Calendar.App = (function(window) {
this.dateFormat = navigator.mozL10n.DateTimeFormat();
+ // re-localize dates on screen
+ this.observeDateLocalization();
+
this.timeController.observe();
this.alarmController.observe();
View
1  apps/calendar/js/db.js
@@ -379,6 +379,7 @@
account._id = uuid();
var calendar = {
+ _id: Calendar.Provider.Local.calendarId,
accountId: account._id,
remote: Calendar.Provider.Local.defaultCalendar()
};
View
2  apps/calendar/js/provider/local.js
@@ -10,6 +10,8 @@
this.alarms = this.app.store('Alarm');
}
+ Local.calendarId = LOCAL_CALENDAR_ID;
+
/**
* Returns the details for the default calendars.
*/
View
14 apps/calendar/js/templates/account.js
@@ -3,17 +3,21 @@
var Account = Calendar.Template.create({
provider: function() {
return '<li class="' + this.h('name') + '">' +
- '<a data-provider="' + this.h('name') +
- '" href="/create-account/' + this.h('name') + '">' +
+ '<a ' +
+ 'data-l10n-id="preset-' + this.h('name') + '" ' +
+ 'data-provider="' + this.h('name') + '" href="/create-account/' +
+ this.h('name') + '">' +
this.l10n('name', 'preset-') +
'</a>' +
'</li>';
},
account: function() {
- return '<li id="account-' + this.h('id') + '">' +
- '<a href="/update-account/' + this.h('id') + '">' +
- '<span class="preset">' +
+ var id = this.h('id');
+ return '<li id="account-' + id + '">' +
+ '<a href="/update-account/' + id + '">' +
+ '<span class="preset"' +
+ ' data-l10n-id="preset-' + this.h('preset') + '">' +
this.l10n('preset', 'preset-') +
'</span>' +
'<span class="user">' + this.h('user') + '</span>' +
View
18 apps/calendar/js/templates/calendar.js
@@ -2,13 +2,21 @@
var Cal = Calendar.Template.create({
item: function() {
- return '<li id="calendar-' + this.h('_id') + '">' +
- '<div class="calendar-id-' +
- this.h('_id') + ' calendar-color"></div>' +
+ var id = this.h('_id');
+ var l10n = '';
+
+ // hack localize the only default calendar
+ if (id && Calendar.Provider.Local.calendarId === id) {
+ // localize the default calendar name
+ l10n = 'data-l10n-id="calendar-local"';
+ }
+
+ return '<li id="calendar-' + id + '">' +
+ '<div class="calendar-id-' + id + ' calendar-color"></div>' +
'<label>' +
- '<span class="name">' + this.h('name') + '</span>' +
+ '<span ' + l10n + ' class="name">' + this.h('name') + '</span>' +
'<input ' +
- 'value="' + this.h('_id') + '" ' +
+ 'value="' + id + '" ' +
'type="checkbox" ' +
this.bool('localDisplayed', 'checked') + ' />' +
'<span></span>' +
View
24 apps/calendar/js/templates/day.js
@@ -2,11 +2,21 @@
var Day = Calendar.Template.create({
hour: function() {
- return '<section class="hour hour-' + this.h('hour') +
- ' ' + this.h('classes') + ' calendar-display">' +
+ var hour = this.h('hour');
+ var l10n = '';
+ var displayHour;
+
+ if (hour === Calendar.Calc.ALLDAY) {
+ l10n = ' data-l10n-id="hour-allday" ';
+ displayHour = navigator.mozL10n.get('hour-allday');
+ } else {
+ displayHour = this.h('displayHour');
+ }
+
+ return '<section class="hour hour-' + hour+ ' ' + this.h('classes') + ' calendar-display">' +
'<h4>' +
- '<span class="display-hour ' + this.h('hour') + '">' +
- this.h('displayHour') +
+ '<span ' + l10n + 'class="display-hour ' + hour + '">' +
+ displayHour +
'</span>' +
'</h4>' +
/** has no semantic value - re-evaluate */
@@ -19,10 +29,10 @@
},
event: function() {
- return '<section class="event calendar-id-' + this.h('calendarId') + ' ' +
+ var calendarId = this.h('calendarId');
+ return '<section class="event calendar-id-' + calendarId + ' ' +
'calendar-display" data-id="' + this.h('busytimeId') + '">' +
- '<div class="container calendar-id-' +
- this.h('calendarId') + ' calendar-color">' +
+ '<div class="container calendar-id-' + calendarId + ' calendar-color">' +
'<h5>' + this.h('title') + '</h5>' +
'<span class="details">' +
'<span class="location">' +
View
19 apps/calendar/js/templates/week.js
@@ -5,9 +5,20 @@
},
sidebarHour: function() {
- return '<li class="hour-' + this.h('hour') + '">' +
- this.h('displayHour') +
- '</li>';
+ var l10n = '';
+ var hour = this.h('hour');
+ var displayHour;
+
+ if (hour === Calendar.Calc.ALLDAY) {
+ l10n = ' data-l10n-id="hour-allday" ';
+ displayHour = navigator.mozL10n.get('hour-allday');
+ } else {
+ displayHour = this.h('displayHour');
+ }
+
+ return '<li ' + hour + ' class="hour-' + this.h('hour') + '">' +
+ displayHour +
+ '</li>';
},
hour: function() {
@@ -18,7 +29,7 @@
event: function() {
return '<li class="event" data-id="' + this.h('busytimeId') + '">' +
- '<div class="container calendar-id-' + this.h('calendarId') + ' ' +
+ '<div class="container calend +ar-id-' + this.h('calendarId') + ' ' +
'calendar-display calendar-color">' +
this.h('title') +
'</div>' +
View
12 apps/calendar/js/views/months_day.js
@@ -40,12 +40,20 @@ Calendar.ns('Views').MonthsDay = (function() {
},
_updateHeader: function() {
+ var header = this.header;
+ var template = navigator.mozL10n.get(
+ 'agenda-date-format'
+ );
+
// maybe we should localize this output ?
var format = this.app.dateFormat.localeFormat(
this.date,
- '%A %B %Y'
+ template || '%A %e %B %Y'
);
- this.header.textContent = format;
+
+ header.textContent = format;
+ header.dataset.date = this.date.toString();
+ header.dataset.l10nDateFormat = template;
},
handleEvent: function(e) {
View
11 apps/calendar/js/views/time_header.js
@@ -130,7 +130,16 @@ Calendar.ns('Views').TimeHeader = (function() {
_updateTitle: function() {
var con = this.app.timeController;
- this.title.textContent = this.getScale(
+ var date = this.getScale(con.scale);
+
+ var title = this.title;
+
+ title.dataset.l10nDateFormat =
+ this.scales[con.scale] || this.scales.month;
+
+ title.dataset.date = con.position.toString();
+
+ title.textContent = this.getScale(
con.scale
);
},
View
4 apps/calendar/locales/calendar.en-US.properties
@@ -81,8 +81,10 @@ sync-frequency-hourly.textContent=Each hour
alarm-starting={{title}} started {{distance}}
alarm-started={{title}} starting in {{distance}}
-# 24 vs 12 see http://www.cplusplus.com/reference/clibrary/ctime/strftime/
+# Date formatting details (http://pubs.opengroup.org/onlinepubs/007908799/xsh/strftime.html)
+agenda-date-format=%A %e %B %Y
hour-format=%I %p
+hour-allday=All Day
#errors
error-start-after-end=End date must come after start date
View
53 apps/calendar/test/unit/app_test.js
@@ -45,6 +45,59 @@ suite('app', function() {
router = subject.router;
});
+ suite('date localization', function() {
+ var expected;
+ var fmt;
+ var id = 0;
+
+ function dateElement(date, format) {
+ var el = document.createElement('span');
+ el.dataset.l10nDateFormat = format;
+ el.dataset.date = date.toString();
+ el.textContent = 'you-faiL!';
+
+ document.body.appendChild(el);
+
+ return el;
+ }
+
+ function addExpect(date, format) {
+ var elId = 'dateId-' + (++id);
+ dateElement(date, format).id = elId;
+
+ expected.push(
+ [elId, fmt.localeFormat(date, format)]
+ );
+ }
+
+ setup(function() {
+ fmt = Calendar.App.dateFormat = navigator.mozL10n.DateTimeFormat();
+ expected = [];
+
+ var formatXDate = new Date(2012, 1, 1);
+ var formatCDate = new Date(2012, 1, 1, 7, 2, 9);
+
+ addExpect(formatCDate, '%x');
+ addExpect(formatCDate, '%c');
+
+ subject.observeDateLocalization();
+ window.dispatchEvent(new Event('localized'));
+ });
+
+ test('updates elements with data-l10n-date-format', function() {
+ expected.forEach(function(item) {
+ var element = document.getElementById(item[0]);
+ var expectedText = item[1];
+
+ assert.equal(
+ element.textContent,
+ expectedText,
+ 'should relocalize given'
+ );
+ });
+ });
+ });
+
suite('PendingManager', function() {
var subject;
View
17 apps/calendar/test/unit/templates/calendar_test.js
@@ -14,6 +14,18 @@ suite('templates/calendar', function() {
return subject[type].render(options);
}
+ test('#item with local id', function() {
+ var model = {
+ localDisplayed: true,
+ _id: Calendar.Provider.Local.calendarId,
+ name: 'foo'
+ };
+
+ var output = renderHTML('item', model);
+ assert.ok(output);
+ assert.include(output, 'calendar-local');
+ });
+
test('#item', function() {
var model = {
localDisplayed: true,
@@ -28,6 +40,11 @@ suite('templates/calendar', function() {
assert.include(output, model.name);
assert.include(output, 'calendar-1');
+ assert.ok(
+ output.indexOf('calendar-local') === -1,
+ 'does not include calendar-local l10n id'
+ );
+
model.localDisplayed = false;
output = renderHTML('item', model);
View
15 apps/calendar/test/unit/views/months_day_test.js
@@ -93,8 +93,21 @@ suite('views/months_day', function() {
subject.date = date;
subject._updateHeader();
+ var format = '%A %e %B %Y';
var expected = date.toLocaleFormat(
- '%A %B %Y'
+ format
+ );
+
+ assert.equal(
+ el.dataset.date,
+ date.toString(),
+ 'sets element\'s date'
+ );
+
+ assert.equal(
+ el.dataset.l10nDateFormat,
+ format,
+ 'sets element\'s l10nDateFormat'
);
assert.ok(el.innerHTML, 'has contents');
View
13 apps/calendar/test/unit/views/time_header_test.js
@@ -98,6 +98,19 @@ suite('views/time_header', function() {
test('#_updateTitle', function() {
subject._updateTitle();
+
+ assert.equal(
+ subject.title.dataset.date,
+ controller.position.toString(),
+ 'sets element date'
+ );
+
+ assert.equal(
+ subject.title.dataset.l10nDateFormat,
+ subject.scales.month,
+ 'sets element scale'
+ );
+
assert.equal(
subject.title.textContent,
subject.getScale('month')
Please sign in to comment.
Something went wrong with that request. Please try again.