Browse Source

Improved dashboard display and translations

keplyx 4 years ago
parent
commit
98e820473e
4 changed files with 222 additions and 77 deletions
  1. 206
    68
      screens/HomeScreen.js
  2. 2
    3
      screens/Proxiwash/ProxiwashScreen.js
  3. 8
    4
      translations/en.json
  4. 6
    2
      translations/fr.json

+ 206
- 68
screens/HomeScreen.js View File

2
 
2
 
3
 import * as React from 'react';
3
 import * as React from 'react';
4
 import {Image, Linking, TouchableOpacity, View} from 'react-native';
4
 import {Image, Linking, TouchableOpacity, View} from 'react-native';
5
-import {Body, Button, Card, CardItem, Left, Right, Text, Thumbnail, H1, H3, Content} from 'native-base';
5
+import {Body, Button, Card, CardItem, Left, Text, Thumbnail, H1, H3} from 'native-base';
6
 import i18n from "i18n-js";
6
 import i18n from "i18n-js";
7
 import CustomMaterialIcon from '../components/CustomMaterialIcon';
7
 import CustomMaterialIcon from '../components/CustomMaterialIcon';
8
 import FetchedDataSectionList from "../components/FetchedDataSectionList";
8
 import FetchedDataSectionList from "../components/FetchedDataSectionList";
12
 import HTML from 'react-native-render-html';
12
 import HTML from 'react-native-render-html';
13
 import {LinearGradient} from 'expo-linear-gradient';
13
 import {LinearGradient} from 'expo-linear-gradient';
14
 
14
 
15
+import DATA from '../data_test'
16
+
15
 
17
 
16
 const ICON_AMICALE = require('../assets/amicale.png');
18
 const ICON_AMICALE = require('../assets/amicale.png');
17
 const NAME_AMICALE = 'Amicale INSA Toulouse';
19
 const NAME_AMICALE = 'Amicale INSA Toulouse';
22
     'news_feed'
24
     'news_feed'
23
 ];
25
 ];
24
 
26
 
27
+const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
28
+
25
 
29
 
26
 /**
30
 /**
27
  * Opens a link in the device's browser
31
  * Opens a link in the device's browser
37
 export default class HomeScreen extends FetchedDataSectionList {
41
 export default class HomeScreen extends FetchedDataSectionList {
38
 
42
 
39
     constructor() {
43
     constructor() {
40
-        super(DATA_URL, 0);
44
+        super('DATA_URL', REFRESH_TIME);
41
     }
45
     }
42
 
46
 
43
     getHeaderTranslation() {
47
     getHeaderTranslation() {
53
     }
57
     }
54
 
58
 
55
     createDataset(fetchedData: Object) {
59
     createDataset(fetchedData: Object) {
60
+        fetchedData = DATA;
56
         let newsData = [];
61
         let newsData = [];
57
         let dashboardData = [];
62
         let dashboardData = [];
58
         if (fetchedData['news_feed'] !== undefined)
63
         if (fetchedData['news_feed'] !== undefined)
81
         let dataset = [
86
         let dataset = [
82
             {
87
             {
83
                 id: 'top',
88
                 id: 'top',
84
-                content: {}
89
+                content: undefined
85
             },
90
             },
86
             {
91
             {
87
                 id: 'middle',
92
                 id: 'middle',
89
             },
94
             },
90
             {
95
             {
91
                 id: 'bottom',
96
                 id: 'bottom',
92
-                content: {}
97
+                content: undefined
93
             },
98
             },
94
 
99
 
95
         ];
100
         ];
152
             return this.getDashboardBottomItem(content);
157
             return this.getDashboardBottomItem(content);
153
     }
158
     }
154
 
159
 
155
-    getDisplayEvent(events: Array<Object>): Object {
156
-        let displayEvent = undefined;
160
+    /**
161
+     * Convert the date string given by in the event list json to a date object
162
+     * @param dateString
163
+     * @return {Date}
164
+     */
165
+    stringToDate(dateString: ?string): ?Date {
166
+        let date = new Date();
167
+        if (dateString === undefined || dateString === null)
168
+            date = undefined;
169
+        else if (dateString.split(' ').length > 1) {
170
+            let timeStr = dateString.split(' ')[1];
171
+            date.setHours(parseInt(timeStr.split(':')[0]), parseInt(timeStr.split(':')[1]), 0);
172
+        } else
173
+            date = undefined;
174
+        return date;
175
+    }
157
 
176
 
158
-        if (events.length === 1) {
159
-            displayEvent = this.getEventDisplayData(events[0]);
160
-        } else {
161
-            for (let event of events) {
162
-                if (event['date_begin'] === undefined || event['date_end'] === undefined)
163
-                    continue;
164
-
165
-                let date_begin = event['date_begin'].split(' ')[1];
166
-                let date_end = event['date_end'].split(' ')[1];
167
-                let startDate = new Date();
168
-                let endDate = new Date();
169
-                let limit = new Date();
170
-                let now = new Date();
171
-                startDate.setHours(parseInt(date_begin.split(':')[0]), date_begin.split(':')[1], 0);
172
-                endDate.setHours(parseInt(date_end.split(':')[0]), date_end.split(':')[1], 0);
173
-                limit.setHours(18, 0, 0); // Only display events after 18:00 as these are the most important
174
-                if (limit.getTime() < startDate.getTime() && now.getTime() < endDate.getTime()) {
175
-                    displayEvent = this.getEventDisplayData(event);
176
-                    break;
177
-                }
177
+    /**
178
+     * Get the time limit depending on the current day:
179
+     * 17:30 for every day of the week except for thursday 11:30
180
+     * 00:00 on weekends
181
+     */
182
+    getTodayEventTimeLimit() {
183
+        let now = new Date();
184
+        if (now.getDay() === 4) // Thursday
185
+            now.setHours(11, 30, 0);
186
+        else if (now.getDay() === 6 || now.getDay() === 0) // Weekend
187
+            now.setHours(0, 0, 0);
188
+        else
189
+            now.setHours(17, 30, 0);
190
+        return now;
191
+    }
192
+
193
+    /**
194
+     * Get the duration (in milliseconds) of an event
195
+     * @param event {Object}
196
+     * @return {number} The number of milliseconds
197
+     */
198
+    getEventDuration(event: Object): number {
199
+        let start = this.stringToDate(event['date_begin']);
200
+        let end = this.stringToDate(event['date_end']);
201
+        let duration = 0;
202
+        if (start !== undefined && start !== null && end !== undefined && end !== null)
203
+            duration = end - start;
204
+        return duration;
205
+    }
206
+
207
+    /**
208
+     * Get events starting after the limit
209
+     *
210
+     * @param events
211
+     * @param limit
212
+     * @return {Array<Object>}
213
+     */
214
+    getEventsAfterLimit(events: Object, limit: Date): Array<Object> {
215
+        let validEvents = [];
216
+        for (let event of events) {
217
+            let startDate = this.stringToDate(event['date_begin']);
218
+            if (startDate !== undefined && startDate !== null && startDate >= limit) {
219
+                validEvents.push(event);
178
             }
220
             }
179
         }
221
         }
180
-        return displayEvent;
222
+        return validEvents;
223
+    }
224
+
225
+    /**
226
+     * Get the event with the longest duration in the given array.
227
+     * If all events have the same duration, return the first in the array.
228
+     * @param events
229
+     */
230
+    getLongestEvent(events: Array<Object>): Object {
231
+        let longestEvent = events[0];
232
+        let longestTime = 0;
233
+        for (let event of events) {
234
+            let time = this.getEventDuration(event);
235
+            if (time > longestTime) {
236
+                longestTime = time;
237
+                longestEvent = event;
238
+            }
239
+        }
240
+        return longestEvent;
181
     }
241
     }
182
 
242
 
183
-    getEventDisplayData(event: Object): Object {
184
-        let date = '';
185
-        if (event['date_begin'].split(' ').length > 2) {
186
-            date = event['date_begin'].split(' ')[1];
187
-            date = date.split(':')[0] + ':' + date.split(':')[1];
243
+    /**
244
+     * Get events that have not yet ended/started
245
+     *
246
+     * @param events
247
+     */
248
+    getFutureEvents(events: Array<Object>): Array<Object> {
249
+        let validEvents = [];
250
+        let now = new Date();
251
+        for (let event of events) {
252
+            let startDate = this.stringToDate(event['date_begin']);
253
+            let endDate = this.stringToDate(event['date_end']);
254
+            if (startDate !== undefined && startDate !== null) {
255
+                if (startDate > now)
256
+                    validEvents.push(event);
257
+                else if (endDate !== undefined && endDate !== null) {
258
+                    if (endDate > now)
259
+                        validEvents.push(event);
260
+                }
261
+            }
188
         }
262
         }
189
-        return {
190
-            logo: event['logo'],
191
-            title: event['title'],
192
-            date: date,
193
-            description: event['description'],
263
+        return validEvents;
264
+    }
265
+
266
+    /**
267
+     *
268
+     *
269
+     * @param events
270
+     * @return {Object}
271
+     */
272
+    getDisplayEvent(events: Array<Object>): Object {
273
+        let displayEvent = undefined;
274
+        if (events.length > 1) {
275
+            let eventsAfterLimit = this.getEventsAfterLimit(events, this.getTodayEventTimeLimit());
276
+            if (eventsAfterLimit.length > 0) {
277
+                if (eventsAfterLimit.length === 1)
278
+                    displayEvent = eventsAfterLimit[0];
279
+                else
280
+                    displayEvent = this.getLongestEvent(events);
281
+            } else {
282
+                displayEvent = this.getLongestEvent(events);
283
+            }
284
+        } else if (events.length === 1) {
285
+            displayEvent = events[0];
194
         }
286
         }
287
+        return displayEvent;
288
+    }
289
+
290
+    padStr(i: number) {
291
+        return (i < 10) ? "0" + i : "" + i;
292
+    }
293
+
294
+    getFormattedEventTime(event: Object): string {
295
+        let formattedStr = '';
296
+        let startDate = this.stringToDate(event['date_begin']);
297
+        let endDate = this.stringToDate(event['date_end']);
298
+        if (startDate !== undefined && startDate !== null && endDate !== undefined && endDate !== null)
299
+            formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes()) +
300
+                ' - ' + this.padStr(endDate.getHours()) + ':' + this.padStr(endDate.getMinutes());
301
+        else if (startDate !== undefined && startDate !== null)
302
+            formattedStr = this.padStr(startDate.getHours()) + ':' + this.padStr(startDate.getMinutes());
303
+        return formattedStr
195
     }
304
     }
196
 
305
 
197
 
306
 
201
         let title = i18n.t('homeScreen.dashboard.todayEventsTitle');
310
         let title = i18n.t('homeScreen.dashboard.todayEventsTitle');
202
         let isAvailable = content.length > 0;
311
         let isAvailable = content.length > 0;
203
         let subtitle = '';
312
         let subtitle = '';
313
+        let futureEvents = this.getFutureEvents(content);
204
         if (isAvailable) {
314
         if (isAvailable) {
205
             subtitle =
315
             subtitle =
206
                 <Text>
316
                 <Text>
207
-                    <Text style={{fontWeight: "bold"}}>{content.length}</Text>
208
-                    <Text>{i18n.t('homeScreen.dashboard.todayEventsSubtitle')}</Text>
317
+                    <Text style={{fontWeight: "bold"}}>{futureEvents.length}</Text>
318
+                    <Text>
319
+                        {
320
+                            futureEvents.length > 1 ?
321
+                                i18n.t('homeScreen.dashboard.todayEventsSubtitlePlural') :
322
+                                i18n.t('homeScreen.dashboard.todayEventsSubtitle')
323
+                        }
324
+                    </Text>
209
                 </Text>;
325
                 </Text>;
210
         } else
326
         } else
211
             subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA');
327
             subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA');
212
         let clickAction = () => this.props.navigation.navigate('Planning');
328
         let clickAction = () => this.props.navigation.navigate('Planning');
213
 
329
 
214
-        let displayEvent = this.getDisplayEvent(content);
330
+        let displayEvent = this.getDisplayEvent(futureEvents);
215
 
331
 
216
         return (
332
         return (
217
             <Card style={{
333
             <Card style={{
218
                 flex: 0,
334
                 flex: 0,
219
                 marginLeft: 10,
335
                 marginLeft: 10,
220
                 marginRight: 10,
336
                 marginRight: 10,
221
-                borderRadius: 30,
222
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
337
+                marginTop: 10,
338
+                borderRadius: 20,
339
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
340
+                overflow: 'hidden',
223
             }}>
341
             }}>
224
                 <PlatformTouchable
342
                 <PlatformTouchable
225
                     onPress={clickAction}
343
                     onPress={clickAction}
226
                     style={{
344
                     style={{
227
                         zIndex: 100,
345
                         zIndex: 100,
228
-                        borderRadius: 30
229
                     }}
346
                     }}
230
                 >
347
                 >
231
                     <View>
348
                     <View>
232
                         <CardItem style={{
349
                         <CardItem style={{
233
-                            borderRadius: 30,
234
                             backgroundColor: 'transparent',
350
                             backgroundColor: 'transparent',
235
                         }}>
351
                         }}>
236
                             <Left>
352
                             <Left>
265
                             <View>
381
                             <View>
266
                                 <CardItem style={{
382
                                 <CardItem style={{
267
                                     paddingTop: 0,
383
                                     paddingTop: 0,
268
-                                    paddingBottom: 0
384
+                                    paddingBottom: 0,
385
+                                    backgroundColor: 'transparent',
269
                                 }}>
386
                                 }}>
270
                                     <Left>
387
                                     <Left>
271
                                         {displayEvent['logo'] !== '' && displayEvent['logo'] !== null ?
388
                                         {displayEvent['logo'] !== '' && displayEvent['logo'] !== null ?
273
                                             <View/>}
390
                                             <View/>}
274
                                         <Body>
391
                                         <Body>
275
                                             <Text>{displayEvent['title']}</Text>
392
                                             <Text>{displayEvent['title']}</Text>
276
-                                            <Text note>{displayEvent['date']}</Text>
393
+                                            <Text note>{this.getFormattedEventTime(displayEvent)}</Text>
277
                                         </Body>
394
                                         </Body>
278
                                     </Left>
395
                                     </Left>
279
                                 </CardItem>
396
                                 </CardItem>
282
                                     backgroundColor: 'transparent',
399
                                     backgroundColor: 'transparent',
283
                                 }}>
400
                                 }}>
284
                                     <Body style={{
401
                                     <Body style={{
285
-                                        height: 70,
402
+                                        height: displayEvent['description'].length > 50 ? 70 : 20,
286
                                         overflow: 'hidden',
403
                                         overflow: 'hidden',
287
                                     }}>
404
                                     }}>
288
                                         <HTML html={"<div>" + displayEvent['description'] + "</div>"}
405
                                         <HTML html={"<div>" + displayEvent['description'] + "</div>"}
301
                                                 position: 'absolute',
418
                                                 position: 'absolute',
302
                                                 width: '100%',
419
                                                 width: '100%',
303
                                                 height: 60,
420
                                                 height: 60,
304
-                                                bottom: 0
421
+                                                bottom: 0,
305
                                             }}>
422
                                             }}>
306
                                             <View style={{
423
                                             <View style={{
307
                                                 marginLeft: 'auto',
424
                                                 marginLeft: 'auto',
328
         );
445
         );
329
     }
446
     }
330
 
447
 
331
-    getSquareDashboardItem(isAvailable: boolean, icon: string, color: string, title: string, subtitle: string, clickAction: Function, isLeftElement: boolean) {
448
+    getSquareDashboardItem(isAvailable: boolean, icon: string, color: string, title: string, subtitle: React.Node, clickAction: Function, isLeftElement: boolean) {
332
         return (
449
         return (
333
             <Card style={{
450
             <Card style={{
334
                 flex: 0,
451
                 flex: 0,
335
                 width: '48%',
452
                 width: '48%',
336
                 marginLeft: 0,
453
                 marginLeft: 0,
337
                 marginRight: isLeftElement ? '4%' : 0,
454
                 marginRight: isLeftElement ? '4%' : 0,
338
-                borderRadius: 30,
339
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
455
+                borderRadius: 20,
456
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
457
+                overflow: 'hidden',
340
             }}>
458
             }}>
341
                 <PlatformTouchable
459
                 <PlatformTouchable
342
                     onPress={clickAction}
460
                     onPress={clickAction}
343
                     style={{
461
                     style={{
344
                         zIndex: 100,
462
                         zIndex: 100,
345
-                        borderRadius: 30
463
+                        minHeight: 150,
346
                     }}
464
                     }}
347
                 >
465
                 >
348
                     <CardItem style={{
466
                     <CardItem style={{
349
-                        borderRadius: 30,
350
                         backgroundColor: 'transparent'
467
                         backgroundColor: 'transparent'
351
                     }}>
468
                     }}>
352
                         <Body>
469
                         <Body>
398
             proximoSubtitle =
515
             proximoSubtitle =
399
                 <Text>
516
                 <Text>
400
                     <Text style={{fontWeight: "bold"}}>{proximoData}</Text>
517
                     <Text style={{fontWeight: "bold"}}>{proximoData}</Text>
401
-                    <Text>{i18n.t('homeScreen.dashboard.proximoSubtitle')}</Text>
518
+                    <Text>
519
+                        {
520
+                            proximoData > 1 ?
521
+                            i18n.t('homeScreen.dashboard.proximoSubtitlePlural') :
522
+                            i18n.t('homeScreen.dashboard.proximoSubtitle')
523
+                        }
524
+                    </Text>
402
                 </Text>;
525
                 </Text>;
403
         } else
526
         } else
404
             proximoSubtitle = i18n.t('homeScreen.dashboard.proximoSubtitleNA');
527
             proximoSubtitle = i18n.t('homeScreen.dashboard.proximoSubtitleNA');
434
         let title = i18n.t('homeScreen.dashboard.proxiwashTitle');
557
         let title = i18n.t('homeScreen.dashboard.proxiwashTitle');
435
         let isAvailable = parseInt(content['dryers']) > 0 || parseInt(content['washers']) > 0;
558
         let isAvailable = parseInt(content['dryers']) > 0 || parseInt(content['washers']) > 0;
436
         let subtitle;
559
         let subtitle;
560
+        let dryerColor = parseInt(content['dryers']) > 0 ?
561
+            ThemeManager.getCurrentThemeVariables().textColor :
562
+            ThemeManager.getCurrentThemeVariables().listNoteColor;
563
+        let washerColor = parseInt(content['washers']) > 0 ?
564
+            ThemeManager.getCurrentThemeVariables().textColor :
565
+            ThemeManager.getCurrentThemeVariables().listNoteColor;
566
+        let availableDryers = content['dryers'];
567
+        let availableWashers = content['washers'];
437
         if (isAvailable) {
568
         if (isAvailable) {
438
             subtitle =
569
             subtitle =
439
                 <Text>
570
                 <Text>
441
                         fontWeight: parseInt(content['dryers']) > 0 ?
572
                         fontWeight: parseInt(content['dryers']) > 0 ?
442
                             'bold' :
573
                             'bold' :
443
                             'normal',
574
                             'normal',
444
-                        color: parseInt(content['dryers']) > 0 ?
445
-                            ThemeManager.getCurrentThemeVariables().textColor :
446
-                            ThemeManager.getCurrentThemeVariables().listNoteColor
575
+                        color: dryerColor
447
                     }}>
576
                     }}>
448
-                        {content['dryers']}
577
+                        {availableDryers}
578
+                    </Text>
579
+                    <Text>
580
+                        {
581
+                            availableDryers > 1 ?
582
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle1Plural') :
583
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle1')
584
+                        }
449
                     </Text>
585
                     </Text>
450
-                    <Text>{i18n.t('homeScreen.dashboard.proxiwashSubtitle1')}</Text>
451
                     <Text style={{
586
                     <Text style={{
452
                         fontWeight: parseInt(content['washers']) > 0 ?
587
                         fontWeight: parseInt(content['washers']) > 0 ?
453
                             'bold' :
588
                             'bold' :
454
                             'normal',
589
                             'normal',
455
-                        color: parseInt(content['washers']) > 0 ?
456
-                            ThemeManager.getCurrentThemeVariables().textColor :
457
-                            ThemeManager.getCurrentThemeVariables().listNoteColor
590
+                        color: washerColor
458
                     }}>
591
                     }}>
459
-                        {content['washers']}
592
+                        {availableWashers}
593
+                    </Text>
594
+                    <Text>
595
+                        {
596
+                            availableWashers > 1 ?
597
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle2Plural') :
598
+                                i18n.t('homeScreen.dashboard.proxiwashSubtitle2')
599
+                        }
460
                     </Text>
600
                     </Text>
461
-                    <Text>{i18n.t('homeScreen.dashboard.proxiwashSubtitle2')}</Text>
462
                 </Text>;
601
                 </Text>;
463
         } else
602
         } else
464
             subtitle = i18n.t('homeScreen.dashboard.proxiwashSubtitleNA');
603
             subtitle = i18n.t('homeScreen.dashboard.proxiwashSubtitleNA');
468
                 flex: 0,
607
                 flex: 0,
469
                 marginLeft: 10,
608
                 marginLeft: 10,
470
                 marginRight: 10,
609
                 marginRight: 10,
471
-                borderRadius: 50,
472
-                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg
610
+                borderRadius: 20,
611
+                backgroundColor: ThemeManager.getCurrentThemeVariables().cardDefaultBg,
612
+                overflow: 'hidden',
473
             }}>
613
             }}>
474
                 <PlatformTouchable
614
                 <PlatformTouchable
475
                     onPress={clickAction}
615
                     onPress={clickAction}
476
                     style={{
616
                     style={{
477
                         zIndex: 100,
617
                         zIndex: 100,
478
-                        borderRadius: 50
479
                     }}
618
                     }}
480
                 >
619
                 >
481
                     <CardItem style={{
620
                     <CardItem style={{
482
-                        borderRadius: 50,
483
                         backgroundColor: 'transparent'
621
                         backgroundColor: 'transparent'
484
                     }}>
622
                     }}>
485
                         <Left>
623
                         <Left>

+ 2
- 3
screens/Proxiwash/ProxiwashScreen.js View File

28
 let stateIcons = {};
28
 let stateIcons = {};
29
 let stateColors = {};
29
 let stateColors = {};
30
 
30
 
31
+const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
31
 
32
 
32
 /**
33
 /**
33
  * Class defining the app's proxiwash screen. This screen shows information about washing machines and
34
  * Class defining the app's proxiwash screen. This screen shows information about washing machines and
35
  */
36
  */
36
 export default class ProxiwashScreen extends FetchedDataSectionList {
37
 export default class ProxiwashScreen extends FetchedDataSectionList {
37
 
38
 
38
-    refreshInterval: IntervalID;
39
-
40
     /**
39
     /**
41
      * Creates machine state parameters using current theme and translations
40
      * Creates machine state parameters using current theme and translations
42
      */
41
      */
43
     constructor() {
42
     constructor() {
44
-        super(DATA_URL, 1000 * 30); // Refresh every half minute
43
+        super(DATA_URL, REFRESH_TIME);
45
         let colors = ThemeManager.getCurrentThemeVariables();
44
         let colors = ThemeManager.getCurrentThemeVariables();
46
         stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor;
45
         stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor;
47
         stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor;
46
         stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor;

+ 8
- 4
translations/en.json View File

74
     "dashboard": {
74
     "dashboard": {
75
       "todayEventsTitle": "Today's events",
75
       "todayEventsTitle": "Today's events",
76
       "todayEventsSubtitleNA": "No events today",
76
       "todayEventsSubtitleNA": "No events today",
77
-      "todayEventsSubtitle": " events today",
77
+      "todayEventsSubtitle": " event coming today",
78
+      "todayEventsSubtitlePlural": " events coming today",
78
       "proximoTitle": "Proximo",
79
       "proximoTitle": "Proximo",
79
       "proximoSubtitleNA": "No articles available",
80
       "proximoSubtitleNA": "No articles available",
80
-      "proximoSubtitle": " articles available",
81
+      "proximoSubtitle": " article available",
82
+      "proximoSubtitlePlural": " articles available",
81
       "proxiwashTitle": "Available machines",
83
       "proxiwashTitle": "Available machines",
82
       "proxiwashSubtitleNA": "No machines available",
84
       "proxiwashSubtitleNA": "No machines available",
83
-      "proxiwashSubtitle1": " dryers and ",
84
-      "proxiwashSubtitle2": " washers",
85
+      "proxiwashSubtitle1": " dryer and ",
86
+      "proxiwashSubtitle1Plural": " dryers and ",
87
+      "proxiwashSubtitle2": " washer",
88
+      "proxiwashSubtitle2Plural": " washers",
85
       "menuTitle": "Today's menu",
89
       "menuTitle": "Today's menu",
86
       "menuSubtitleNA": "No menu available",
90
       "menuSubtitleNA": "No menu available",
87
       "menuSubtitle": "Click here to see the menu"
91
       "menuSubtitle": "Click here to see the menu"

+ 6
- 2
translations/fr.json View File

74
     "dashboard": {
74
     "dashboard": {
75
       "todayEventsTitle": "Événements aujourd'hui",
75
       "todayEventsTitle": "Événements aujourd'hui",
76
       "todayEventsSubtitleNA": "Pas d'événements",
76
       "todayEventsSubtitleNA": "Pas d'événements",
77
-      "todayEventsSubtitle": " événements aujourd'hui",
77
+      "todayEventsSubtitle": " événement aujourd'hui",
78
+      "todayEventsSubtitlePlural": " événements aujourd'hui",
78
       "proximoTitle": "Proximo",
79
       "proximoTitle": "Proximo",
79
       "proximoSubtitleNA": "pas d'article en vente",
80
       "proximoSubtitleNA": "pas d'article en vente",
80
-      "proximoSubtitle": " articles disponibles",
81
+      "proximoSubtitle": " article disponible",
82
+      "proximoSubtitlePlural": " articles disponibles",
81
       "proxiwashTitle": "Machines disponibles",
83
       "proxiwashTitle": "Machines disponibles",
82
       "proxiwashSubtitleNA": "Pas de machine disponible",
84
       "proxiwashSubtitleNA": "Pas de machine disponible",
83
       "proxiwashSubtitle1": " sèches linges et ",
85
       "proxiwashSubtitle1": " sèches linges et ",
86
+      "proxiwashSubtitle1Plural": " sèche linge et ",
84
       "proxiwashSubtitle2": " laves linges",
87
       "proxiwashSubtitle2": " laves linges",
88
+      "proxiwashSubtitle2Plural": " lave linge",
85
       "menuTitle": "Menu d'aujourd'hui",
89
       "menuTitle": "Menu d'aujourd'hui",
86
       "menuSubtitleNA": "Pas de menu disponible",
90
       "menuSubtitleNA": "Pas de menu disponible",
87
       "menuSubtitle": "Cliquez ici pour voir le menu"
91
       "menuSubtitle": "Cliquez ici pour voir le menu"

Loading…
Cancel
Save