From d8e0a271966ef36022af6d144745c4e9ba2526ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Mayol?= Date: Mon, 17 Jun 2019 04:57:43 -0700 Subject: [PATCH] Add i18n for most of the app --- bower.json | 5 +- www/i18n/en.json | 243 ++++++++++++++++++++ www/index.html | 6 + www/js/app.js | 23 +- www/js/diary/current.js | 29 ++- www/js/diary/detail.js | 19 +- www/js/diary/list.js | 62 ++--- www/js/diary/services.js | 25 +- www/js/heatmap.js | 62 ++--- www/js/incident/post-trip-manual.js | 4 +- www/js/incident/post-trip-map-display.js | 11 +- www/js/intro.js | 5 +- www/js/main.js | 5 +- www/js/metrics.js | 112 ++++----- www/js/recent.js | 8 +- www/js/tripconfirm/post-trip-map-display.js | 5 +- www/js/tripconfirm/post-trip-prompt.js | 36 +-- www/js/tripconfirm/trip-confirm-services.js | 8 +- www/templates/caloriePopup.html | 12 +- www/templates/common/map.html | 4 +- www/templates/control/main-control.html | 48 ++-- www/templates/diary/current.html | 8 +- www/templates/diary/detail.html | 10 +- www/templates/diary/list.html | 26 +-- www/templates/diary/mode-popover.html | 2 +- www/templates/diary/purpose-popover.html | 2 +- www/templates/incident/map.html | 4 +- www/templates/intro/consent.html | 6 +- www/templates/intro/intro.html | 3 +- www/templates/intro/reconsent.html | 3 +- www/templates/main-heatmap.html | 14 +- www/templates/main-metrics.html | 56 ++--- www/templates/main.html | 8 +- www/templates/metrics/metrics-control.html | 42 ++-- www/templates/recent/map.html | 2 +- www/templates/tripconfirm/map.html | 18 +- 36 files changed, 624 insertions(+), 312 deletions(-) create mode 100644 www/i18n/en.json diff --git a/bower.json b/bower.json index 00f405129..452cf7824 100644 --- a/bower.json +++ b/bower.json @@ -26,6 +26,9 @@ "nz-tour": "^1.2.1", "jquery": "^3.1.0", "leaflet-plugins": "^3.0.0", - "angularjs-slider": "^6.2.2" + "angularjs-slider": "^6.2.2", + "angular-translate": "^2.18.1", + "angular-translate-loader-static-files": "^2.18.1", + "angular-translate-interpolation-messageformat": "^2.18.1" } } diff --git a/www/i18n/en.json b/www/i18n/en.json new file mode 100644 index 000000000..2b03cb5d7 --- /dev/null +++ b/www/i18n/en.json @@ -0,0 +1,243 @@ +{ + "loading" : "Loading...", + "map-refresh": "Refresh", + "map-fixmap": "Fix Map", + + "weekdays-all": "All", + "weekdays-select": "Select day of the week", + + "post-trip-prompt":{ + "notification-option-mute": "Mute", + "notification-option-snooze": "Snooze", + "notification-option-choose": "Choose", + "notification-title": "How and why did you come here?", + "choose-mode": "Choose Mode", + "skip": "Skip", + "snoozed-reminder": "Snoozed reminder", + "snoozed-reapper-message": "Will reappear in 30 mins", + "platform-specific-message-ios": "Swipe left or tap to add information about this trip.", + "platform-specific-message-android": "See options or tap to add information about this trip.", + "platform-specific-message-other": "Tap to add information about this trip.", + "notifications-muted": "Notifications for TRIP_END incident report muted", + "notifications-reenabled": "Can be re-enabled from the Profile -> Developer Zone screen. Select to re-enable now, clear to ignore", + "muted": "Muted", + "unmute": "Unmute", + "keep-muted": "Keep muted" + }, + + "post-trip-map-display-tour-incident": "Zoom in as much as possible to the location where the incident occurred and click on the blue line of the trip to mark a or incident", + + "tour-next": "Next", + "tour-previous": "Previous", + "tour-finish": "Finish", + + "trip-confirm": { + "recenttrip": "Recent trip from: {{startTime}} → to: {{endTime}}", + "continue": "Continue", + "done": "Done", + "services-please-fill-in": "Please fill in the {{text}} not listed.", + "services-cancel": "Cancel", + "services-save": "Save" + }, + + "place-common-place": "Common place", + "place-successor-trips": "Successor trips", + "place-trips-to": "{{trips}} trips to", + "place-usually-starts": "Usually starts at: {{hour}}:00", + "place-usually-takes": "Usually takes: {{duration}}", + + "trip-start-hours": "Start hours", + "trip-start-duration": "Duration", + + "control":{ + "profile": "Profile", + "tracking": "Tracking", + "medium-accuracy": "Medium accuracy", + "dark-theme": "Dark theme", + "force-sync": "Force sync", + "share": "Share", + "check-ui-updates": "Check for UI updates", + "download-json-dump": "Download json dump", + "email-log": "Email log", + "user-data": "User data", + "erase-data": "Erase data", + "dev-zone": "Developer zone", + "refresh": "Refresh", + "end-trip-sync": "End trip + sync", + "check-consent": "Check consent", + "invalidate-cached-docs": "Invalidate cached docs", + "nuke-all": "Nuke all buffers and cache", + "set-ui-channel": "Set UI channel", + "check-log": "Check log", + "check-sensed-data": "Check sensed data", + "check-map": "Check map", + "collection": "Collection", + "sync": "Sync", + "transition-notify": "Transition Notify" + }, + + "general-settings-choose-date" : "Choose date to download data", + "general-settings-nuke-ui-state-only" : "UI state only", + "general-settings-nuke-native-cache-only" : "Native cache only", + "general-settings-nuke-everything" : "Everything", + "general-settings-clear-data": "Clear data", + "general-settings-cancel": "Cancel", + "general-settings-user-data-erased": "User data erased.", + "general-settings-consent-not-found": "Consent for data collection not found, consent now?", + "general-settings-no-consent-message": "OK! Note that you won't get any personalized stats until you do!", + "general-settings-consent-found": "Consent found!", + "general-settings-consented-to": "Consented to protocol {{protocol_id}}, {{approval_date}}", + "general-settings-consented-ok": "OK", + "general-settings-share-message": "Join me in making transportation greener and healthier \nDownload the emission app:", + "general-settings-share-subject": "Emission - UC Berkeley Research Project", + "general-settings-share-url": "https://bic2cal.eecs.berkeley.edu/#download", + + "metrics":{ + "cancel": "Cancel", + "confirm": "Confirm", + "get": "Get", + "range": "Range", + "filter": "Filter", + "from": "From:", + "to": "To:", + "last-week": "Last week", + "frequency": "Frequency:", + "pandafreqoptions-daily": "DAILY", + "pandafreqoptions-weekly": "WEEKLY", + "pandafreqoptions-biweekly": "BIWEEKLY", + "pandafreqoptions-monthly": "MONTHLY", + "pandafreqoptions-yearly": "YEARLY", + "freqoptions-daily": "DAILY", + "freqoptions-monthly": "MONTHLY", + "freqoptions-yearly": "YEARLY", + "select-pandafrequency": "Select summary freqency", + "select-frequency": "Select summary freqency", + "chart-xaxis-date": "Date", + "chart-no-data": "No Data Available", + "trips-yaxis-number": "Number", + "calorie-data-change": " change", + "carbon-data-change": " change", + "carbon-data-calculating": "Calculating...", + "carbon-data-unknown": "Unknown", + "calorie-data-unknown": "Unknown...", + "calorie-data-change-increase": " increase over a week", + "calorie-data-change-decrease": " decrease over a week", + "carbon-data-change-increase": " increase over a week", + "carbon-data-change-decrease": " decrease over a week", + "pick-a-date": "Pick a date" + }, + + "diary": { + "current-trip": "Current Trip", + "current-yesterday": "Yesterday", + "current-weekago": "Week ago", + "history": "History", + "began": "Began {{startTime}}", + "report-incident": "Report Incident", + "draft": "DRAFT", + "distance-in-time": "{{distance}} km in {{time}}", + "distance": "Distance", + "time": "Time", + "mode": "Mode", + "purpose": "Purpose", + "choose-mode": "Choose Mode", + "choose-purpose": "Choose Purpose", + "how-did-you-get-here": "How did you get here?", + "why-did-you-come-here": "Why did you come here?", + "list-pick-a-date": "Pick a date" + }, + + "user-gender": "Gender", + "gender-male": "Male", + "gender-female": "Female", + "user-height": "Height", + "user-weight": "Weight", + "user-age": "Age", + + "main-metrics":{ + "dashboard": "Dashboard", + "summary": "Summary", + "chart": "Chart", + "change-data": "Change data:", + "distance": "Distance", + "trips": "Trips", + "duration": "Duration", + "speed": "Speed", + "footprint": "Footprint", + "optimal": "Optimal:", + "average": "Average:", + "worst": "Worst:", + "lastweek": "Last Week:", + "calories": "Calories", + "calibrate": "Calibrate", + "no-summary-data": "No summary data", + "median-speed": "Median Speed", + "equals-cookies": "Equals {cookies, plural, =0{0 homemade chocolate chip cookies} one {1 homemade chocolate chip cookie} other {# homemade chocolate chip cookies}}", + "equals-icecream": "Equals {icecream, plural, =0{0 half cups vanilla ice cream} one {1 half cup vanilla ice cream} other {# half cups vanilla ice cream}}", + "equals-bananas": "Equals {bananas, plural, =0{0 bananas} one {1 banana} other {# bananas}}" + }, + + "main-diary" : "Diary", + + "main-heatmap":{ + "title": "Heatmap", + "counts" : "Counts", + "stress" : "Stress", + "from" : "From:", + "to" : "To:", + "get" : "Get!", + "all": "ALL", + "none": "NONE", + "bicycling": "BICYCLING", + "walking": "WALKING", + "in-vehicle": "IN_VEHICLE", + "select-travel-mode" : "Select travel mode", + "cancel": "Cancel", + "tour-datepicker": "This heatmap shows the aggregate data for all E-mission users. Select the dates you want to see, and filter by hours of the day (24h format) and days of the week. For example, if you enter 16 and 19 in the last field, and select Monday and Friday, you'll see the Heatmap filtered to show the traffic on weekdays between 4pm and 7pm.", + "tour-mode": "Click here to filter your results by mode of transportation. The default is to show all modes.", + "tour-get": "Click here to generate the heatmap." + }, + + "details":{ + "speed": "Speed", + "time": "Temps", + "tour-detail-content": "To report an incident, zoom in as much as possible to the location where the incident occurred and click on the trip to mark a ☻ or ☹ incident", + "tour-sectionList-content": "Trip sections, along with times and modes", + "tour-sectionPct-content": "% of time spent in each mode for this trip" + }, + + "list-explainDraft-alert": "This trip has not yet been analysed. If it stays in this state, please ask your sysadmin to check what is wrong.", + "list-datepicker-today": "Today", + "list-datepicker-close": "Close", + "list-datepicker-set": "Set", + "list-tour-datepicker-button" : "Use this to select the day you want to see.", + "list-tour-diary-entry" : "Click on the map to see more details about each trip.", + "list-tour-map-fix-button" : "Use this to fix the map tiles if they have not loaded properly.", + + "service":{ + "reading-server": "Reading from server...", + "reading-cache": "Reading from cache...", + "reading-unprocessed-data": "Reading unprocessed data..." + }, + + + "post-trip-manual-incident-time" : "Choose incident time", + + "recent":{ + "email-account-not-configured": "Email account is not configured, cannot send email", + "email-account-mail-app": "You must have the mail app on your phone configured with an email address. Otherwise, this won't work", + "going-to-email": "Going to email database from {{parentDir}}/userCacheDB" + }, + + "consent":{ + "button-accept": "I accept", + "button-decline": "I refuse" + }, + + "updatecheck-downloading-update": "Downloading UI-only update", + "updatecheck-extracting-update": "Extracting UI-only update", + "updatecheck-done": "Update done, reloading...", + "updatecheck-download-new-ui": "Download new UI-only update?.", + "updatecheck-download-not-now": "Not now", + "updatecheck-download-apply": "Apply" +} diff --git a/www/index.html b/www/index.html index d4f39f03f..5346b3dcd 100644 --- a/www/index.html +++ b/www/index.html @@ -30,7 +30,13 @@ + + + + + + diff --git a/www/js/app.js b/www/js/app.js index 0914f9960..2711e562e 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -11,7 +11,8 @@ angular.module('emission', ['ionic', 'emission.controllers','emission.services', 'emission.plugin.logger', 'emission.splash.customURLScheme', 'emission.splash.referral', 'emission.splash.updatecheck', - 'emission.intro', 'emission.main']) + 'emission.intro', 'emission.main', + 'pascalprecht.translate']) .run(function($ionicPlatform, $rootScope, $http, Logger, CustomURLScheme, ReferralHandler, UpdateCheck) { @@ -70,7 +71,7 @@ angular.module('emission', ['ionic', console.log("Ending run"); }) -.config(function($stateProvider, $urlRouterProvider) { +.config(function($stateProvider, $urlRouterProvider, $translateProvider) { console.log("Starting config"); // alert("config"); @@ -102,5 +103,23 @@ angular.module('emission', ['ionic', // alert("about to fall back to otherwise"); // if none of the above states are matched, use this as the fallback $urlRouterProvider.otherwise('/splash'); + + // Allow the use of MessageForm interpolation for Gender and Plural. + $translateProvider.addInterpolation('$translateMessageFormatInterpolation'); + + // Define where we can find the .json and the fallback language + $translateProvider + .fallbackLanguage('en') + .registerAvailableLanguageKeys(['en', 'fr'], { + 'en_*': 'en', + 'fr_*': 'fr', + '*': 'en' + }) + .determinePreferredLanguage() + .useStaticFilesLoader({ + prefix: 'i18n/', + suffix: '.json' + }); + console.log("Ending config"); }); diff --git a/www/js/diary/current.js b/www/js/diary/current.js index 3d87c4a50..ac322586e 100644 --- a/www/js/diary/current.js +++ b/www/js/diary/current.js @@ -8,7 +8,7 @@ 'emission.plugin.logger']) .controller('CurrMapCtrl', function($scope, Config, $state, $timeout, $ionicActionSheet,leafletData, - Logger, $window, PostTripManualMarker, CommHelper, $http, KVStore, $ionicPlatform) { + Logger, $window, PostTripManualMarker, CommHelper, $http, KVStore, $ionicPlatform, $translate) { console.log("controller CurrMapCtrl called from current.js"); var _map; @@ -46,9 +46,9 @@ hideLimitLabels: true, translate: function(value) { if (value === 1) { - return "Yesterday"; + return $translate.instant('diary.current-yesterday'); } else if (value === 7) { - return "Week ago"; + return $translate.instant('diary.current-weekagos'); } return ""; } @@ -84,15 +84,20 @@ sel_region: null }; - var startTimeFn = function(ts) { - var date = new Date(ts*1000); - var hours = date.getHours(); - var minutes = date.getMinutes(); - var amOrPm = hours < 12 ? 'AM' : 'PM'; - hours = hours % 12; - hours = hours ? hours : 12; - minutes = minutes < 10 ? '0'+ minutes : minutes; - return hours + ':' + minutes + ' ' + amOrPm; + var startTimeFn = function (ts) { + var date = new Date(ts * 1000); + if ($translate.use() != "en") { + return moment(date).format('HH:mm'); + } else { + return moment(date).format('HH:mmA') + } + // var hours = date.getHours(); + // var minutes = date.getMinutes(); + // var amOrPm = hours < 12 ? 'AM' : 'PM'; + // hours = hours % 12; + // hours = hours ? hours : 12; + // minutes = minutes < 10 ? '0'+ minutes : minutes; + // return hours + ':' + minutes + ' ' + amOrPm; }; var getSpeed = function(curr_lglat, last_lglat, curr_ts, last_ts) { diff --git a/www/js/diary/detail.js b/www/js/diary/detail.js index afa67bc64..b887f9e7a 100644 --- a/www/js/diary/detail.js +++ b/www/js/diary/detail.js @@ -7,7 +7,7 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', .controller("DiaryDetailCtrl", function($scope, $rootScope, $window, $stateParams, $ionicActionSheet, leafletData, leafletMapEvents, nzTour, KVStore, Logger, Timeline, DiaryHelper, Config, - CommHelper, PostTripManualMarker) { + CommHelper, PostTripManualMarker, $translate) { console.log("controller DiaryDetailCtrl called with params = "+ JSON.stringify($stateParams)); @@ -85,7 +85,7 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', } var dataset = { values: data, - key: 'Speed', + key: $translate.instant('details.speed'), color: '#7777ff', } var chart = nv.models.lineChart() @@ -97,10 +97,10 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', .showXAxis(true); //Show the x-axis chart.xAxis .tickFormat(d3.format(".1f")) - .axisLabel('Time (mins)'); + .axisLabel($translate.instant('details.time') + ' (mins)'); chart.yAxis //Chart y-axis settings - .axisLabel('Speed (m/s)') + .axisLabel($translate.instant('details.speed') + ' (m/s)') .tickFormat(d3.format('.1f')); d3.select('#chart svg') //Select the element you want to render the chart in. @@ -119,17 +119,20 @@ angular.module('emission.main.diary.detail',['ui-leaflet', 'ng-walkthrough', mask: { visibleOnNoTarget: true, clickExit: true - } + }, + previousText: $translate.instant('tour-previous'), + nextText: $translate.instant('tour-next'), + finishText: $translate.instant('tour-finish') }, steps: [{ target: '#detail', - content: 'To report an incident, zoom in as much as possible to the location where the incident occurred and click on the trip to mark a ☻ or ☹ incident' + content: $translate.instant('details.tour-detail-content') }, { target: '#sectionList', - content: 'Trip sections, along with times and modes' + content: $translate.instant('details.tour-sectionList-content') }, { target: '#sectionPct', - content: '% of time spent in each mode for this trip' + content: $translate.instant('details.tour-sectionPct-content') }] }; diff --git a/www/js/diary/list.js b/www/js/diary/list.js index 63f344415..092c0a084 100644 --- a/www/js/diary/list.js +++ b/www/js/diary/list.js @@ -24,7 +24,7 @@ angular.module('emission.main.diary.list',['ui-leaflet', $ionicActionSheet, ionicDatePicker, leafletData, Timeline, CommonGraph, DiaryHelper, - Config, PostTripManualMarker, ConfirmHelper, nzTour, KVStore, Logger, UnifiedDataLoader, $ionicPopover) { + Config, PostTripManualMarker, ConfirmHelper, nzTour, KVStore, Logger, UnifiedDataLoader, $ionicPopover, $translate) { console.log("controller DiaryListCtrl called"); var MODE_CONFIRM_KEY = "manual/mode_confirm"; var PURPOSE_CONFIRM_KEY = "manual/purpose_confirm"; @@ -42,6 +42,8 @@ angular.module('emission.main.diary.list',['ui-leaflet', // TODO: Convert the usercache calls into promises so that we don't have to // do this juggling Timeline.updateForDay(day); + // This will be used to show the date of datePicker in the user language. + $scope.currDay = moment(day).format('DD MMM YYYY'); // CommonGraph.updateCurrent(); }; @@ -59,23 +61,23 @@ angular.module('emission.main.diary.list',['ui-leaflet', angular.extend($scope.defaults, Config.getMapTiles()) - moment.locale('en', { - relativeTime : { - future: "in %s", - past: "%s ago", - s: "secs", - m: "a min", - mm: "%d m", - h: "an hr", - hh: "%d h", - d: "a day", - dd: "%d days", - M: "a month", - MM: "%d months", - y: "a year", - yy: "%d years" - } -}); +// moment.locale('en', { +// relativeTime : { +// future: "in %s", +// past: "%s ago", +// s: "secs", +// m: "a min", +// mm: "%d m", +// h: "an hr", +// hh: "%d h", +// d: "a day", +// dd: "%d days", +// M: "a month", +// MM: "%d months", +// y: "a year", +// yy: "%d years" +// } +// }); /* * While working with dates, note that the datepicker needs a javascript date because it uses @@ -123,9 +125,12 @@ angular.module('emission.main.diary.list',['ui-leaflet', $scope.datepickerObject = { - todayLabel: 'Today', //Optional - closeLabel: 'Close', //Optional - setLabel: 'Set', //Optional + todayLabel: $translate.instant('list-datepicker-today'), //Optional + closeLabel: $translate.instant('list-datepicker-close'), //Optional + setLabel: $translate.instant('list-datepicker-set'), //Optional + monthsList: moment.monthsShort(), + weeksList: moment.weekdaysMin(), + titleLabel: $translate.instant('diary.list-pick-a-date'), setButtonType : 'button-positive', //Optional todayButtonType : 'button-stable', //Optional closeButtonType : 'button-stable', //Optional @@ -225,7 +230,7 @@ angular.module('emission.main.diary.list',['ui-leaflet', $scope.explainDraft = function($event) { $event.stopPropagation(); $ionicPopup.alert({ - template: "This trip has not yet been analysed. If it stays in this state, please ask your sysadmin to check what is wrong." + template: $translate.instant('list-explainDraft-alert') }); // don't want to go to the detail screen } @@ -402,20 +407,23 @@ angular.module('emission.main.diary.list',['ui-leaflet', config: { mask: { visibleOnNoTarget: true, - clickExit: true - } + clickExit: true, + }, + previousText: $translate.instant('tour-previous'), + nextText: $translate.instant('tour-next'), + finishText: $translate.instant('tour-finish') }, steps: [{ target: '#date-picker-button', - content: 'Use this to select the day you want to see.' + content: $translate.instant('list-tour-datepicker-button') }, { target: '.diary-entry', - content: 'Click on the map to see more details about each trip.' + content: $translate.instant('list-tour-diary-entry') }, { target: '#map-fix-button', - content: 'Use this to fix the map tiles if they have not loaded properly.' + content: $translate.instant('list-tour-diary-entry') } ] }; diff --git a/www/js/diary/services.js b/www/js/diary/services.js index 249461f00..5c025aa68 100644 --- a/www/js/diary/services.js +++ b/www/js/diary/services.js @@ -3,7 +3,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', 'emission.services', 'emission.main.common.services', 'emission.incident.posttrip.manual']) -.factory('DiaryHelper', function(CommonGraph, PostTripManualMarker){ +.factory('DiaryHelper', function(CommonGraph, PostTripManualMarker, $translate){ var dh = {}; // dh.expandEarlierOrLater = function(id) { // document.querySelector('#hidden-' + id.toString()).setAttribute('style', 'display: block;'); @@ -166,12 +166,17 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', return retVal; }; - dh.getLocalTimeString = function(dt) { - var hr = ((dt.hour > 12))? dt.hour - 12 : dt.hour; - var post = ((dt.hour >= 12))? " pm" : " am"; - var min = (dt.minute.toString().length == 1)? "0" + dt.minute.toString() : dt.minute.toString(); - return hr + ":" + min + post; + dh.getLocalTimeString = function (dt) { + if ($translate.use() != "en") { + return moment(dt).format('HH:mm'); + } else { + // var hr = ((dt.hour > 12)) ? dt.hour - 12 : dt.hour; + // var post = ((dt.hour >= 12)) ? " pm" : " am"; + // var min = (dt.minute.toString().length == 1) ? "0" + dt.minute.toString() : dt.minute.toString(); + // return hr + ":" + min + post; + return moment(dt).format('HH:mmA') } + }; dh.getFormattedTime = function(ts_in_secs) { if (angular.isDefined(ts_in_secs)) { @@ -439,7 +444,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', return dh; }) .factory('Timeline', function(CommHelper, $http, $ionicLoading, $window, - $rootScope, CommonGraph, UnifiedDataLoader, Logger) { + $rootScope, CommonGraph, UnifiedDataLoader, Logger, $translate) { var timeline = {}; // corresponds to the old $scope.data. Contains all state for the current // day, including the indication of the current day @@ -456,7 +461,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', timeline.updateFromDatabase = function(day) { console.log("About to show 'Reading from cache'"); $ionicLoading.show({ - template: 'Reading from cache...' + template: $translate.instant('service.reading-cache') }); return window.cordova.plugins.BEMUserCache.getDocument(getKeyForDate(day), false) .then(function (timelineDoc) { @@ -477,7 +482,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', timeline.updateFromServer = function(day) { console.log("About to show 'Reading from server'"); $ionicLoading.show({ - template: 'Reading from server...' + template: $translate.instant('service.reading-server') }); return CommHelper.getTimelineForDay(day).then(function(response) { var tripList = response.timeline; @@ -830,7 +835,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', * https://github.com/e-mission/e-mission-phone/issues/214#issuecomment-284312004 */ $ionicLoading.show({ - template: 'Reading unprocessed data...' + template: $translate.instant('service.reading-unprocessed-data') }); if (tripListForDay.length == 0) { var last_processed_ts = moment(day).startOf("day").unix(); diff --git a/www/js/heatmap.js b/www/js/heatmap.js index aaa76e62c..66d52e7c4 100644 --- a/www/js/heatmap.js +++ b/www/js/heatmap.js @@ -6,7 +6,7 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', .controller('HeatmapCtrl', function($scope, $ionicLoading, $ionicActionSheet, $http, leafletData, Logger, Config, PostTripManualMarker, - $window, nzTour, KVStore) { + $window, nzTour, KVStore, $translate) { $scope.mapCtrl = {}; angular.extend($scope.mapCtrl, { @@ -84,18 +84,18 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', */ $scope.modeOptions = [ - {text: "ALL", value:null}, - {text: "NONE", value:[]}, - {text: "BICYCLING", value:["BICYCLING"]}, - {text: "WALKING", value:["WALKING", "ON_FOOT"]}, - {text: "IN_VEHICLE", value:["IN_VEHICLE"]} + {text: $translate.instant('main-heatmap.all'), value:null}, + {text: $translate.instant('main-heatmap.none'), value:[]}, + {text: $translate.instant('main-heatmap.bicycling'), value:["BICYCLING"]}, + {text: $translate.instant('main-heatmap.walking'), value:["WALKING", "ON_FOOT"]}, + {text: $translate.instant('main-heatmap.in-vehicle'), value:["IN_VEHICLE"]} ]; $scope.changeMode = function() { $ionicActionSheet.show({ buttons: $scope.modeOptions, - titleText: "Select travel mode", - cancelText: "Cancel", + titleText: $translate.instant('main-heatmap.select-travel-mode'), + cancelText: $translate.instant('main-heatmap.cancel'), buttonClicked: function(index, button) { $scope.selectCtrl.modeString = button.text; $scope.selectCtrl.modes = button.value; @@ -120,19 +120,19 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', $scope.changeWeekday = function(stringSetFunction, localDateObj) { var weekdayOptions = [ - {text: "All", value: null}, - {text: "Monday", value: 0}, - {text: "Tuesday", value: 1}, - {text: "Wednesday", value: 2}, - {text: "Thursday", value: 3}, - {text: "Friday", value: 4}, - {text: "Saturday", value: 5}, - {text: "Sunday", value: 6} + {text: $translate.instant('weekdays-all'), value: null}, + {text: moment.weekdays(1), value: 0}, + {text: moment.weekdays(2), value: 1}, + {text: moment.weekdays(3), value: 2}, + {text: moment.weekdays(4), value: 3}, + {text: moment.weekdays(5), value: 4}, + {text: moment.weekdays(6), value: 5}, + {text: moment.weekdays(0), value: 6} ]; $ionicActionSheet.show({ buttons: weekdayOptions, - titleText: "Select day of the week", - cancelText: "Cancel", + titleText: $translate.instant('weekdays-select'), + cancelText: $translate.instant('main-heatmap.cancel'), buttonClicked: function(index, button) { stringSetFunction(button.text); localDateObj.weekday = button.value; @@ -173,11 +173,11 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', $scope.selectCtrl.showStress = false; $scope.selectCtrl.showCount = true; $scope.selectCtrl.modes = null; - $scope.selectCtrl.modeString = "ALL"; - $scope.selectCtrl.fromDate = moment2Localdate(dayago) + $scope.selectCtrl.modeString = $translate.instant('main-heatmap.all'); + $scope.selectCtrl.fromDate = moment2Localdate(dayago); $scope.selectCtrl.toDate = moment2Localdate(now); - $scope.selectCtrl.fromDateWeekdayString = "All" - $scope.selectCtrl.toDateWeekdayString = "All" + $scope.selectCtrl.fromDateWeekdayString = $translate.instant('weekdays-all'); + $scope.selectCtrl.toDateWeekdayString = $translate.instant('weekdays-all'); $scope.selectCtrl.region = null; }; @@ -235,7 +235,7 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', var setSelData = function(map, selData) { if (selData.isLoading == true) { $ionicLoading.show({ - template: 'Loading...' + template: $translate.instant('loading') }); // Don't set any layer - it will be filled in when the load completes } else { @@ -339,19 +339,23 @@ angular.module('emission.main.heatmap',['ui-leaflet', 'emission.services', mask: { visibleOnNoTarget: true, clickExit: true - } + }, + previousText: $translate.instant('tour-previous'), + nextText: $translate.instant('tour-next'), + finishText: $translate.instant('tour-finish') }, steps: [{ target: '.datepicker', - content: 'This heatmap shows the aggregate data for all E-mission users. Select the dates you want to see, and filter by hours of the day (24h format) and days of the week. For example, if you enter 16 and 19 in the last field, and select Monday and Friday, you\'ll see the Heatmap filtered to show the traffic on weekdays between 4pm and 7pm.' + content: $translate.instant('main-heatmap.tour-datepicker') }, - { + { target: '.heatmap-mode-button', - content: 'Click here to filter your results by mode of transportation. The default is to show all modes.' + content: $translate.instant('main-heatmap.tour-mode') + }, - { + { target: '.heatmap-get-button', - content: 'Click here to generate the heatmap.' + content: $translate.instant('main-heatmap.tour-get') }] }; diff --git a/www/js/incident/post-trip-manual.js b/www/js/incident/post-trip-manual.js index d2e52fc1c..ae0424575 100644 --- a/www/js/incident/post-trip-manual.js +++ b/www/js/incident/post-trip-manual.js @@ -3,7 +3,7 @@ angular.module('emission.incident.posttrip.manual', ['emission.plugin.logger', 'emission.main.diary.services']) .factory('PostTripManualMarker', function($window, $state, $ionicActionSheet, $ionicPlatform, - Logger, Timeline) { + Logger, Timeline, $translate) { var ptmm = {}; var MULTI_PASS_THRESHOLD = 90; @@ -409,7 +409,7 @@ angular.module('emission.incident.posttrip.manual', ['emission.plugin.logger', return {text: getFormattedTime(ts), selValue: ts}; }); - $ionicActionSheet.show({titleText: "Choose incident time", + $ionicActionSheet.show({titleText: $translate.instant('post-trip-manual-incident-time'), buttons: timeSelActions, buttonClicked: function(index, button) { var ts = button.selValue; diff --git a/www/js/incident/post-trip-map-display.js b/www/js/incident/post-trip-map-display.js index 23cbd0f4f..3381ae0ec 100644 --- a/www/js/incident/post-trip-map-display.js +++ b/www/js/incident/post-trip-map-display.js @@ -9,7 +9,7 @@ angular.module('emission.incident.posttrip.map',['ui-leaflet', 'ng-walkthrough', $stateParams, $ionicLoading, leafletData, leafletMapEvents, nzTour, KVStore, Logger, Timeline, DiaryHelper, Config, - UnifiedDataLoader, PostTripManualMarker) { + UnifiedDataLoader, PostTripManualMarker, $translate) { Logger.log("controller PostTripMapDisplay called with params = "+ JSON.stringify($stateParams)); $scope.mapCtrl = {}; @@ -54,7 +54,7 @@ angular.module('emission.incident.posttrip.map',['ui-leaflet', 'ng-walkthrough', }; Logger.log("About to query buffer for "+JSON.stringify(tq)); $ionicLoading.show({ - template: 'Loading...' + template: $translate.instant('loading') }); UnifiedDataLoader.getUnifiedSensorDataForInterval(LOC_KEY, tq) // .then(PostTripManualMarker.addLatLng) @@ -159,11 +159,14 @@ angular.module('emission.incident.posttrip.map',['ui-leaflet', 'ng-walkthrough', mask: { visibleOnNoTarget: true, clickExit: true - } + }, + previousText: $translate.instant('tour-previous'), + nextText: $translate.instant('tour-next'), + finishText: $translate.instant('tour-finish') }, steps: [{ target: '#incident', - content: 'Zoom in as much as possible to the location where the incident occurred and click on the blue line of the trip to mark a or incident' + content: $translate.instant('post-trip-map-display-tour-incident') }] }; diff --git a/www/js/intro.js b/www/js/intro.js index bfe778dff..c796973fa 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -19,7 +19,10 @@ angular.module('emission.intro', ['emission.splash.startprefs', }) .controller('IntroCtrl', function($scope, $state, $ionicSlideBoxDelegate, - $ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs) { + $ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs, $translate) { + + $scope.lang = $translate.use(); + $scope.getIntroBox = function() { return $ionicSlideBoxDelegate.$getByHandle('intro-box'); }; diff --git a/www/js/main.js b/www/js/main.js index a542bfbe7..d0f95ffb9 100644 --- a/www/js/main.js +++ b/www/js/main.js @@ -146,10 +146,13 @@ angular.module('emission.main', ['emission.main.recent', } }) -.controller('MainCtrl', function($scope, $state, $rootScope) { +.controller('MainCtrl', function($scope, $state, $rootScope, $translate) { // Currently this is blank since it is basically a placeholder for the // three screens. But we can totally add hooks here if we want. It is the // controller for all the screens because none of them do anything for now. + + moment.locale($translate.use()); + $scope.tabsCustomClass = function() { return "tabs-icon-top tabs-custom"; } diff --git a/www/js/metrics.js b/www/js/metrics.js index 2431e02ec..85d82a1e4 100644 --- a/www/js/metrics.js +++ b/www/js/metrics.js @@ -6,7 +6,8 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date CommHelper, $window, $ionicPopup, ionicDatePicker, $ionicPlatform, FootprintHelper, CalorieCal, $ionicModal, $timeout, KVStore, - $rootScope, $location, $state, ReferHelper, $http, Logger) { + $rootScope, $location, $state, ReferHelper, $http, Logger, + $translate) { var lastTwoWeeksQuery = true; var first = true; var lastWeekCalories = 0; @@ -266,6 +267,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date bottom: 40, left: 55 }, + noData: $translate.instant('metrics.chart-no-data'), showControls: false, showValues: true, stacked: false, @@ -287,7 +289,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date xAxis: { axisLabelDistance: 3, - axisLabel: 'Date', + axisLabel: $translate.instant('metrics.chart-xaxis-date'), tickFormat: function(d) { var day = new Date(d * 1000) day.setDate(day.getDate()+1) // Had to add a day to match date with data @@ -297,7 +299,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date staggerLabels: true }, yAxis: { - axisLabel: "Number", + axisLabel: $translate.instant('metrics.trips-yaxis-number'), axisLabelDistance: -10 }, callback: function(chart) { @@ -426,7 +428,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date var getMetrics = function() { $ionicLoading.show({ - template: 'Loading...' + template: $translate.instant('loading') }); if(!first){ $scope.uictrl.current = "Custom"; @@ -444,15 +446,15 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.caloriesData.aggrCalories = 0; $scope.caloriesData.lastWeekUserCalories = 0; $scope.caloriesData.changeInPercentage = "0%" - $scope.caloriesData.change = " change"; + $scope.caloriesData.change = $translate.instant('metrics.calorie-data-change'); $scope.carbonData.userCarbon = "0 kg CO₂"; - $scope.carbonData.aggrCarbon = "Calculating..."; + $scope.carbonData.aggrCarbon = $translate.instant('metrics.carbon-data-calculating');; $scope.carbonData.optimalCarbon = "0 kg CO₂"; $scope.carbonData.worstCarbon = "0 kg CO₂"; $scope.carbonData.lastWeekUserCarbon = "0 kg CO₂"; $scope.carbonData.changeInPercentage = "0%"; - $scope.carbonData.change = " change"; + $scope.carbonData.change = $translate.instant('metrics.carbon-data-change'); $scope.summaryData.userSummary = []; $scope.chartDataUser = {}; @@ -512,8 +514,8 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date }) .catch(function(error) { $ionicLoading.hide(); - $scope.carbonData.aggrCarbon = "Unknown"; - $scope.caloriesData.aggrCalories = "Unknown..."; + $scope.carbonData.aggrCarbon = $translate.instant('metrics.carbon-data-unknown'); + $scope.caloriesData.aggrCalories = $translate.instant('metrics.calorie-data-unknown'); Logger.displayError("Error loading aggregate data, averages not available", error); }); @@ -644,11 +646,11 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date if (isValidNumber(calorieCalculation)) { $scope.caloriesData.changeInPercentage = calorieCalculation + "%"; if(lastWeekCalories > twoWeeksAgoCalories){ - $scope.caloriesData.change = " increase over a week"; + $scope.caloriesData.change = $translate.instant('metrics.calorie-data-change-increase'); $scope.caloriesUp = true; $scope.caloriesDown = false; } else { - $scope.caloriesData.change = " decrease over a week" + $scope.caloriesData.change = $translate.instant('metrics.calorie-data-change-decrease'); $scope.caloriesUp = false; $scope.caloriesDown = true; } @@ -742,11 +744,11 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date // instead of having to work around it here if (isValidNumber(calculation)) { if(lastWeekCarbonInt[0] > twoWeeksAgoCarbonInt[0]){ - $scope.carbonData.change = " increase over a week"; + $scope.carbonData.change = $translate.instant('metrics.carbon-data-change-increase'); $scope.carbonUp = true; $scope.carbonDown = false; } else { - $scope.carbonData.change = " decrease over a week" + $scope.carbonData.change = $translate.instant('metrics.carbon-data-change-decrease'); $scope.carbonUp = false; $scope.carbonDown = true; } @@ -772,7 +774,7 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.data.duration = getDataFromMetrics(agg_metrics.duration); $scope.data.speed = getDataFromMetrics(agg_metrics.speed); $scope.countOptions = angular.copy($scope.options) - $scope.countOptions.chart.yAxis.axisLabel = 'Number'; + $scope.countOptions.chart.yAxis.axisLabel = $translate.instant('metrics.trips-yaxis-number'); $scope.distanceOptions = angular.copy($scope.options) $scope.distanceOptions.chart.yAxis.axisLabel = 'm'; $scope.durationOptions = angular.copy($scope.options) @@ -781,16 +783,16 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.speedOptions.chart.yAxis.axisLabel = 'm/sec' }; $scope.pandaFreqOptions = [ - {text: "DAILY", value: 'D'}, - {text: "WEEKLY", value: 'W'}, - {text: "BIWEEKLY", value: '2W'}, - {text: "MONTHLY", value: 'M'}, - {text: "YEARLY", value: 'A'} + {text: $translate.instant('metrics.pandafreqoptions-daily'), value: 'D'}, + {text: $translate.instant('metrics.pandafreqoptions-weekly'), value: 'W'}, + {text: $translate.instant('metrics.pandafreqoptions-biweekly'), value: '2W'}, + {text: $translate.instant('metrics.pandafreqoptions-monthly'), value: 'M'}, + {text: $translate.instant('metrics.pandafreqoptions-yearly'), value: 'A'} ]; $scope.freqOptions = [ - {text: "DAILY", value:'DAILY'}, - {text: "MONTHLY", value: 'MONTHLY'}, - {text: "YEARLY", value: 'YEARLY'} + {text: $translate.instant('metrics.freqoptions-daily'), value:'DAILY'}, + {text: $translate.instant('metrics.freqoptions-monthly'), value: 'MONTHLY'}, + {text: $translate.instant('metrics.freqoptions-yearly'), value: 'YEARLY'} ]; var getAvgDataFromMetrics = function(metrics) { var mode_bins = {}; @@ -961,19 +963,19 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.changeWeekday = function(stringSetFunction, target) { var weekdayOptions = [ - {text: "All", value: null}, - {text: "Monday", value: 0}, - {text: "Tuesday", value: 1}, - {text: "Wednesday", value: 2}, - {text: "Thursday", value: 3}, - {text: "Friday", value: 4}, - {text: "Saturday", value: 5}, - {text: "Sunday", value: 6} + {text: $translate.instant('weekdays-all'), value: null}, + {text: moment.weekdays(1), value: 0}, + {text: moment.weekdays(2), value: 1}, + {text: moment.weekdays(3), value: 2}, + {text: moment.weekdays(4), value: 3}, + {text: moment.weekdays(5), value: 4}, + {text: moment.weekdays(6), value: 5}, + {text: moment.weekdays(0), value: 6} ]; $ionicActionSheet.show({ buttons: weekdayOptions, - titleText: "Select day of the week", - cancelText: "Cancel", + titleText: $translate.instant('weekdays-select'), + cancelText: $translate.instant('metrics.cancel'), buttonClicked: function(index, button) { stringSetFunction(button.text); if (target === 'from') { @@ -990,8 +992,8 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.changeFreq = function() { $ionicActionSheet.show({ buttons: $scope.freqOptions, - titleText: "Select summary freqency", - cancelText: "Cancel", + titleText: $translate.instant('metrics.select-frequency'), + cancelText: $translate.instant('metrics.cancel'), buttonClicked: function(index, button) { $scope.selectCtrl.freqString = button.text; $scope.selectCtrl.freq = button.value; @@ -1003,8 +1005,8 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.changePandaFreq = function() { $ionicActionSheet.show({ buttons: $scope.pandaFreqOptions, - titleText: "Select summary freqency", - cancelText: "Cancel", + titleText: $translate.instant('metrics.select-pandafrequency'), + cancelText: $translate.instant('metrics.cancel'), buttonClicked: function(index, button) { $scope.selectCtrl.pandaFreqString = button.text; $scope.selectCtrl.pandaFreq = button.value; @@ -1027,9 +1029,9 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date var now = moment().utc(); var weekAgoFromNow = moment().utc().subtract(7, 'd'); $scope.selectCtrl.freq = 'DAILY'; - $scope.selectCtrl.freqString = "DAILY"; + $scope.selectCtrl.freqString = $translate.instant('metrics.freqoptions-daily'); $scope.selectCtrl.pandaFreq = 'D'; - $scope.selectCtrl.pandaFreqString = "DAILY"; + $scope.selectCtrl.pandaFreqString = $translate.instant('metrics.pandafreqoptions-daily'); // local_date saved as localdate $scope.selectCtrl.fromDateLocalDate = moment2Localdate(weekAgoFromNow); $scope.selectCtrl.toDateLocalDate = moment2Localdate(now); @@ -1037,8 +1039,8 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.selectCtrl.fromDateTimestamp= weekAgoFromNow; $scope.selectCtrl.toDateTimestamp = now; - $scope.selectCtrl.fromDateWeekdayString = "All" - $scope.selectCtrl.toDateWeekdayString = "All" + $scope.selectCtrl.fromDateWeekdayString = $translate.instant('weekdays-all'); + $scope.selectCtrl.toDateWeekdayString = $translate.instant('weekdays-all'); $scope.selectCtrl.fromDateWeekdayValue = null; $scope.selectCtrl.toDateWeekdayValue = null; @@ -1104,9 +1106,9 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date title: '', scope: $scope, buttons: [ - { text: 'Cancel' }, + { text: $translate.instant('metrics.cancel') }, { - text: 'Confirm', + text: ''+ $translate.instant('metrics.confirm') +'', type: 'button-positive', onTap: function(e) { if (!($scope.userData.gender != -1 && $scope.userData.age && $scope.userData.weight && $scope.userData.height)) { @@ -1123,34 +1125,36 @@ angular.module('emission.main.metrics',['nvd3', 'emission.services', 'ionic-date $scope.datepickerObjFrom = { callback: $scope.setCurDayFrom, inputDate: $scope.selectCtrl.fromDateTimestamp.toDate(), - setLabel: 'Set', - todayLabel: 'Today', - closeLabel: 'Close', + todayLabel: $translate.instant('list-datepicker-today'), //Optional + closeLabel: $translate.instant('list-datepicker-close'), //Optional + setLabel: $translate.instant('list-datepicker-set'), //Optional + titleLabel: $translate.instant('metrics.pick-a-date'), mondayFirst: false, - weeksList: ["S", "M", "T", "W", "T", "F", "S"], - monthsList: ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"], + weeksList: moment.weekdaysMin(), + monthsList: moment.monthsShort(), templateType: 'popup', from: new Date(2015, 1, 1), to: new Date(), showTodayButton: true, - dateFormat: 'MMM dd yyyy', + dateFormat: 'dd/MM/yyyy', closeOnSelect: false, disableWeekdays: [6] }; $scope.datepickerObjTo = { callback: $scope.setCurDayTo, inputDate: $scope.selectCtrl.toDateTimestamp.toDate(), - setLabel: 'Set', - todayLabel: 'Today', - closeLabel: 'Close', + todayLabel: $translate.instant('list-datepicker-today'), //Optional + closeLabel: $translate.instant('list-datepicker-close'), //Optional + setLabel: $translate.instant('list-datepicker-set'), //Optional + titleLabel: $translate.instant('metrics.pick-a-date'), mondayFirst: false, - weeksList: ["S", "M", "T", "W", "T", "F", "S"], - monthsList: ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"], + weeksList: moment.weekdaysMin(), + monthsList: moment.monthsShort(), templateType: 'popup', from: new Date(2015, 1, 1), to: new Date(), showTodayButton: true, - dateFormat: 'MMM dd yyyy', + dateFormat: 'dd/MM/yyyy', closeOnSelect: false, // add this instruction if you want to exclude a particular weekday, e.g. Saturday disableWeekdays: [6] }; diff --git a/www/js/recent.js b/www/js/recent.js index db2bc3bc0..a3af09464 100644 --- a/www/js/recent.js +++ b/www/js/recent.js @@ -81,7 +81,7 @@ angular.module('emission.main.recent', ['ngCordova', 'emission.services']) $scope.refreshEntries(); }) -.controller('sensedDataCtrl', function($scope, $cordovaEmailComposer, $ionicActionSheet) { +.controller('sensedDataCtrl', function($scope, $cordovaEmailComposer, $ionicActionSheet, $translate) { var currentStart = 0; /* Let's keep a reference to the database for convenience */ @@ -109,7 +109,7 @@ angular.module('emission.main.recent', ['ngCordova', 'emission.services']) $cordovaEmailComposer.isAvailable().then(function() { // is available }, function () { - alert("Email account is not configured, cannot send email"); + alert($translate.instant('recent.email-account-not-configured')); return; }); @@ -117,7 +117,7 @@ angular.module('emission.main.recent', ['ngCordova', 'emission.services']) parentDir = "app://databases"; } if (ionic.Platform.isIOS()) { - alert("You must have the mail app on your phone configured with an email address. Otherwise, this won't work"); + alert($translate.instant('recent.email-account-mail-app')); parentDir = cordova.file.dataDirectory+"../LocalDatabase"; } @@ -125,7 +125,7 @@ angular.module('emission.main.recent', ['ngCordova', 'emission.services']) window.Logger.log(window.Logger.LEVEL_INFO, "Going to export logs to "+parentDir); */ - alert("Going to email database from "+parentDir+"/userCacheDB"); + alert($translate.instant('recent.going-to-email', {parentDir: parentDirs})); var email = { to: ['shankari@eecs.berkeley.edu'], diff --git a/www/js/tripconfirm/post-trip-map-display.js b/www/js/tripconfirm/post-trip-map-display.js index e363617e8..f0bebb486 100644 --- a/www/js/tripconfirm/post-trip-map-display.js +++ b/www/js/tripconfirm/post-trip-map-display.js @@ -10,7 +10,8 @@ angular.module('emission.tripconfirm.posttrip.map',['ui-leaflet', 'ng-walkthroug $stateParams, $ionicLoading, leafletData, leafletMapEvents, nzTour, KVStore, Logger, DiaryHelper, ConfirmHelper, Config, - UnifiedDataLoader, $ionicSlideBoxDelegate, $ionicPopup) { + UnifiedDataLoader, $ionicSlideBoxDelegate, $ionicPopup, + $translate) { Logger.log("controller PostTripMapDisplay called with params = "+ JSON.stringify($stateParams)); var MODE_CONFIRM_KEY = "manual/mode_confirm"; @@ -74,7 +75,7 @@ angular.module('emission.tripconfirm.posttrip.map',['ui-leaflet', 'ng-walkthroug }; Logger.log("About to query buffer for "+JSON.stringify(tq)); $ionicLoading.show({ - template: 'Loading...' + template: $translate.instant('loading') }); UnifiedDataLoader.getUnifiedSensorDataForInterval(LOC_KEY, tq) .then(function(resultList) { diff --git a/www/js/tripconfirm/post-trip-prompt.js b/www/js/tripconfirm/post-trip-prompt.js index 1df0c8429..4131e4819 100644 --- a/www/js/tripconfirm/post-trip-prompt.js +++ b/www/js/tripconfirm/post-trip-prompt.js @@ -2,7 +2,7 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger']) .factory("PostTripAutoPrompt", function($window, $ionicPlatform, $rootScope, $state, - $ionicPopup, Logger) { + $ionicPopup, Logger, $translate) { var ptap = {}; var REPORT = 737678; // REPORT on the phone keypad var TRIP_CONFIRM_TEXT = 'TRIP_CONFIRM'; @@ -10,12 +10,12 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' var reportMessage = function(platform) { var platformSpecificMessage = { - "ios": "Swipe left or tap to add information about this trip.", - "android": "See options or tap to add information about this trip." + "ios": $translate.instant('post-trip-prompt.platform-specific-message-ios'), + "android": $translate.instant('post-trip-prompt.platform-specific-message-android') }; var selMessage = platformSpecificMessage[platform]; if (!angular.isDefined(selMessage)) { - selMessage = "Tap to add information about this trip."; + selMessage = $translate.instant('post-trip-prompt.platform-specific-message-other'); } return selMessage; }; @@ -23,21 +23,21 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' var getTripEndReportNotification = function() { var actions = [{ identifier: 'MUTE', - title: 'Mute', + title: $translate.instant('post-trip-prompt.notification-option-mute'), icon: 'res://ic_moreoptions', activationMode: 'background', destructive: false, authenticationRequired: false }, { identifier: 'SNOOZE', - title: 'Snooze', + title: $translate.instant('post-trip-prompt.notification-option-snooze'), icon: 'res://ic_moreoptions', activationMode: 'background', destructive: false, authenticationRequired: false }, { identifier: 'CHOOSE', - title: 'Choose', + title: $translate.instant('post-trip-prompt.notification-option-choose'), icon: 'res://ic_signin', activationMode: 'foreground', destructive: false, @@ -46,7 +46,7 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' var reportNotifyConfig = { id: REPORT, - title: "How and why did you come here?", + title: $translate.instant('post-trip-prompt.notification-title'), text: reportMessage(ionic.Platform.platform()), icon: 'file://img/icon.png', smallIcon: 'res://ic_mood_question.png', @@ -93,14 +93,14 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' scope: newScope, template: "{{getFormattedTime(start_ts)}} -> {{getFormattedTime(end_ts)}}", buttons: [{ - text: 'Choose Mode', + text: $translate.instant('post-trip-prompt.choose-mode'), type: 'button-positive', onTap: function(e) { // e.preventDefault() will stop the popup from closing when tapped. return true; } }, { - text: 'Skip', + text: $translate.instant('post-trip-prompt.skip'), type: 'button-positive', onTap: function(e) { return false; @@ -149,8 +149,8 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' $window.cordova.plugins.notification.local.schedule([after_30_mins_prompt]); if ($ionicPlatform.is('android')) { $ionicPopup.alert({ - title: "Snoozed reminder", - template: "Will reappear in 30 mins" + title: $translate.instant('post-trip-prompt.snoozed-reminder'), + template: $translate.instant('post-trip-prompt.snoozed-reapper-message') }); } } else if (data.identifier === 'MUTE') { @@ -161,23 +161,23 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' if ($ionicPlatform.is('ios')) { $window.cordova.plugins.notification.local.schedule([{ id: REPORT, - title: "Notifications for TRIP_END incident report muted", - text: "Can be re-enabled from the Profile -> Developer Zone screen. Select to re-enable now, clear to ignore", + title: $translate.instant('post-trip-prompt.notifications-muted'), + text: $translate.instant('post-trip-prompt.notifications-reenabled'), at: _1_min_from_now, data: {redirectTo: "root.main.control"} }]); } else if ($ionicPlatform.is('android')) { $ionicPopup.show({ - title: "Muted", - template: "Notifications for TRIP_END incident report muted", + title: $translate.instant('post-trip-prompt.muted'), + template: $translate.instant('post-trip-prompt.notifications-muted'), buttons: [{ - text: 'Unmute', + text: $translate.instant('post-trip-prompt.unmute'), type: 'button-positive', onTap: function(e) { return true; } }, { - text: 'Keep muted', + text: $translate.instant('post-trip-prompt.keep-muted'), type: 'button-positive', onTap: function(e) { return false; diff --git a/www/js/tripconfirm/trip-confirm-services.js b/www/js/tripconfirm/trip-confirm-services.js index d155a495b..11d7fa4bc 100644 --- a/www/js/tripconfirm/trip-confirm-services.js +++ b/www/js/tripconfirm/trip-confirm-services.js @@ -1,5 +1,5 @@ angular.module('emission.tripconfirm.services', ['ionic', "emission.plugin.logger"]) -.factory("ConfirmHelper", function($http, $ionicPopup, Logger) { +.factory("ConfirmHelper", function($http, $ionicPopup, $translate, Logger) { var ch = {}; ch.otherModes = []; ch.otherPurposes = []; @@ -53,17 +53,17 @@ angular.module('emission.tripconfirm.services', ['ionic', "emission.plugin.logge ch.checkOtherOption = function(choice, onTapFn, $scope) { if(choice.value == 'other_mode' || choice.value == 'other_purpose') { var text = choice.value == 'other_mode' ? "mode" : "purpose"; - $ionicPopup.show({title: "Please fill in the " + text + " not listed.", + $ionicPopup.show({title: $translate.instant("trip-confirm.services-please-fill-in",{text: text}), scope: $scope, template: '', buttons: [ - { text: 'Cancel', + { text: $translate.instant('trip-confirm.services-cancel'), onTap: function(e) { $scope.selected.mode = ''; $scope.selected.purpose = ''; } }, { - text: 'Save', + text: '' + $translate.instant('trip-confirm.services-save') + '', type: 'button-positive', onTap: onTapFn($scope, choice) } diff --git a/www/templates/caloriePopup.html b/www/templates/caloriePopup.html index f22d740a4..c35e839fa 100644 --- a/www/templates/caloriePopup.html +++ b/www/templates/caloriePopup.html @@ -1,10 +1,10 @@ -
Gender
+
{{'user-gender'}}
-
Male
-
Female
+
{{'gender-male'}}
+
{{'gender-female'}}
-
Height
+
{{'user-height'}}
@@ -12,7 +12,7 @@
ft
-
Weight
+
{{'user-weight'}}
@@ -20,5 +20,5 @@
lb
-
Age
+
{{'user-age'}}
diff --git a/www/templates/common/map.html b/www/templates/common/map.html index 4a14f2bb9..df10b2fdb 100644 --- a/www/templates/common/map.html +++ b/www/templates/common/map.html @@ -8,9 +8,9 @@ -->
Refresh
+ ng-click="refreshMap()" translate>{{'map-refresh'}}
Fix Map
+ ng-click="refreshTiles()" translate>{{'map-fixmap'}}
+
{{settings.auth.email}}
-
Tracking
+
{{'.tracking'}}