Skip to content

Commit

Permalink
Server-side localization fixes, better speech api use (nightscout#3724)
Browse files Browse the repository at this point in the history
* Adds API to plugin manager that calls plugins to visualize alarms

* Refactoring how the translation object is managed after discovering every server-side plugin had it's own instance of the translations and the language code wasn't propagated to any code that generated alarms

* Add more missing translations

* Some more localization fixes
Update Finnish to 100% localized
Change Mongo connection to not stop retrying connecting

* Better scaling for mmol
Fix bug in detecting new BG values

* Delta calculation was the wrong way round :D

* add missing dutch translations

* Have tests bail early & tell Mocha to exit at the end of the run

* Try if Travis likes running tests one by one better

* Enable blocking IO for Travis
  • Loading branch information
sulkaharo committed Jul 27, 2018
1 parent ea83415 commit cb33193
Show file tree
Hide file tree
Showing 30 changed files with 271 additions and 113 deletions.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@ report:
YOURPACKAGE_COVERAGE=1 ./node_modules/codacy-coverage/bin/codacy-coverage.js) || echo "NO COVERAGE"

test:
${MONGO_SETTINGS} ${MOCHA} --timeout 30000 -R tap ${TESTS}
python -c 'import os,sys,fcntl; flags = fcntl.fcntl(sys.stdout, fcntl.F_GETFL); fcntl.fcntl(sys.stdout, fcntl.F_SETFL, flags&~os.O_NONBLOCK);'
$(foreach var,$(wildcard tests/*.js),${MONGO_SETTINGS} ${MOCHA} --timeout 30000 --exit --bail -R tap $(var);)

test_all:
${MONGO_SETTINGS} ${MOCHA} --timeout 30000 --exit --bail -R tap ${TESTS}

travis:
python -c 'import os,sys,fcntl; flags = fcntl.fcntl(sys.stdout, fcntl.F_GETFL); fcntl.fcntl(sys.stdout, fcntl.F_SETFL, flags&~os.O_NONBLOCK);'
NODE_ENV=test ${MONGO_SETTINGS} \
${ISTANBUL} cover ${MOCHA} --report lcovonly -- --timeout 5000 -R tap ${TESTS}

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs.htm
Integration with Amazon Alexa, [detailed setup instructions](lib/plugins/alexa-plugin.md)

##### `speech` (Speech)
Speech synthesis plugin. When enabled, speaks out the blood glucose values, IOB and alarms.
Speech synthesis plugin. When enabled, speaks out the blood glucose values, IOB and alarms. Note you have to set the LANGUAGE setting on the server to get all translated alarms.

##### `cors` (CORS)
Enabled [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) so other websites can make request to your Nightscout site, uses these extended settings:
Expand Down
44 changes: 29 additions & 15 deletions lib/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ client.load = function load(serverSettings, callback) {
, currentAnnouncement
, alarmSound = 'alarm.mp3'
, urgentAlarmSound = 'alarm2.mp3'
, previousNotifyTimestamp
;

client.entryToDate = function entryToDate (entry) { return new Date(entry.mills); };
Expand Down Expand Up @@ -167,6 +168,10 @@ client.load = function load(serverSettings, callback) {
, pluginBase: client.plugins.base(majorPills, minorPills, statusPills, bgStatus, client.tooltip, Storages.localStorage)
};

client.ctx.language = language;
levels.translate = language.translate;
client.ctx.levels = levels;

client.sbx = sandbox.clientInit(client.ctx, client.now);
client.renderer = require('./renderer')(client, d3, $);

Expand Down Expand Up @@ -571,16 +576,19 @@ client.load = function load(serverSettings, callback) {
return range;
}

function setAlarmMessage (notify) {
function formatAlarmMessage(notify) {
var announcementMessage = notify && notify.isAnnouncement && notify.message && notify.message.length > 1;

if (announcementMessage) {
alarmMessage = levels.toDisplay(notify.level) + ': ' + notify.message;
return levels.toDisplay(notify.level) + ': ' + notify.message;
} else if (notify) {
alarmMessage = notify.title;
} else {
alarmMessage = null;
return notify.title;
}
return null;
}

function setAlarmMessage (notify) {
alarmMessage = formatAlarmMessage(notify);
}

function generateAlarm (file, notify) {
Expand All @@ -597,15 +605,8 @@ client.load = function load(serverSettings, callback) {
$(this).addClass('playing');
});

//TODO: temporary disabled becaused it throws Uncaught TypeError: Cannot read property 'speech' of undefined if speech is not in ENABLE, https://github.com/nightscout/cgm-remote-monitor/pull/3709
//var speechEnabled = client.plugins.isEnabled('speech') ;
//if (speechEnabled) {
// var speechPlugin = client.plugins.enabledPlugins['speech'];
// if (speechPlugin) {
// speechPlugin.say(alarmMessage);
// }
//}

console.log('Asking plugins to visualize alarms');
client.plugins.visualizeAlarm(client.sbx, notify, alarmMessage);
}

container.addClass('alarming').addClass(file === urgentAlarmSound ? 'urgent' : 'warning');
Expand Down Expand Up @@ -773,8 +774,9 @@ client.load = function load(serverSettings, callback) {
console.info('generating timeAgoAlarm', alarm);
container.addClass('alarming-timeago');
var display = client.timeago.calcDisplay(client.sbx.lastSGVEntry(), client.sbx.time);
var translate = client.translate;
var notify = {
title: 'Last data received ' + [display.value, display.label].join(' ')
title: translate('Last data received') + ' ' + display.value + ' ' + translate(display.label)
, level: status === 'urgent' ? 2 : 1
, group: 'Time Ago'
};
Expand Down Expand Up @@ -988,6 +990,18 @@ client.load = function load(serverSettings, callback) {
return client.latestSGV && client.latestSGV.mgdl <= client.settings.thresholds.bgTargetTop;
}

socket.on('notification', function (notify) {
console.log('notification from server:',notify);

if (notify.timestamp && previousNotifyTimestamp != notify.timestamp)
{
previousNotifyTimestamp = notify.timestamp;
client.plugins.visualizeAlarm(client.sbx, notify, notify.title + ' ' + notify.message);
} else {
console.log('No timestamp found for notify, not passing to plugins');
}
});

socket.on('announcement', function (notify) {
console.info('announcement received from server');
console.log('notify:',notify);
Expand Down
101 changes: 74 additions & 27 deletions lib/language.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
var _ = require('lodash');

function init() {
var lang;

language.speechCode;

function language() {
return language;
}

language.speechCode = 'en-US';
language.lang = 'en';

language.languages = [
{ code: 'bg', language: 'Български', speechCode: 'bg-BG' }
, { code: 'cs', language: 'Čeština', speechCode: 'cs-CZ' }
Expand Down Expand Up @@ -1310,12 +1310,14 @@ function init() {
nl: 'netIOB stats'
,sv: 'netIOB statistik'
,de: 'netIOB Statistiken'
,fi: 'netIOB tilasto'
}
,'temp basals must be rendered to display this report': { //hourlystats.js
nl: 'tijdelijk basaal moet zichtbaar zijn voor dit rapport'
,sv: 'temp basal måste vara synlig för denna rapport'
,de: 'temporäre Basalraten müssen für diesen Report sichtbar sein'
}
,fi: 'tämä raportti vaatii, että basaalien piirto on päällä'
}
,'Weekly success' : {
cs: 'Statistika po týdnech'
,de: 'Wöchentlicher Erfolg'
Expand Down Expand Up @@ -5152,16 +5154,19 @@ function init() {
nl: 'Pompbatterij vervangen'
,sv: 'Byte av pumpbatteri'
,de: 'Pumpenbatterie wechseln'
,fi: 'Pumpun patterin vaihto'
}
,'Pump Battery Low Alarm' : {
nl: 'Pompbatterij bijna leeg Alarm'
,sv: 'Pumpbatteri lågt Alarm'
,de: 'Pumpenbatterie niedrig Alarm'
,fi: 'Varoitus! Pumpun patteri loppumassa'
}
,'Pump Battery change overdue!' : { // batteryage.js
nl: 'Pompbatterij moet vervangen worden!'
,sv: 'Pumpbatteriet måste bytas!'
,de: 'Pumpenbatterie Wechsel überfällig!'
,fi: 'Pumpun patterin vaihto myöhässä!'
}
,'When enabled an alarm may sound.' : {
cs: 'Při povoleném alarmu zní zvuk'
Expand Down Expand Up @@ -11435,60 +11440,70 @@ function init() {
, de: 'Der Akku deines Uploader Handys ist bei %1'
, nl: 'De batterij van je mobiel is bij %l'
, sv: 'Din uppladdares batteri är %1'
, fi: 'Lähettimen paristoa jäljellä %1'
},
'alexaReservoir': {
en: 'You have %1 units remaining'
, de: 'Du hast %1 Einheiten übrig'
, nl: 'Je hebt nog %l eenheden in je reservoir'
, sv: 'Du har %1 enheter kvar'
, fi: '%1 yksikköä insuliinia jäljellä'
},
'alexaPumpBattery': {
en: 'Your pump battery is at %1 %2'
, de: 'Der Batteriestand deiner Pumpe ist bei %1 %2'
, nl: 'Je pomp batterij is bij %1 %2'
, sv: 'Din pumps batteri är %1 %2'
, fi: 'Pumppu on %1 %2'
},
'alexaLastLoop': {
en: 'The last successful loop was %1'
, de: 'Der letzte erfolgreiche Loop war %1'
, nl: 'De meest recente goede loop was %1'
, sv: 'Senaste lyckade loop var %1'
, fi: 'Viimeisin onnistunut loop oli %1'
},
'alexaLoopNotAvailable': {
en: 'Loop plugin does not seem to be enabled'
, de: 'Das Loop Plugin scheint nicht aktiviert zu sein'
, nl: 'De Loop plugin is niet geactiveerd'
, sv: 'Loop plugin verkar inte vara aktiverad'
, fi: 'Loop plugin ei ole aktivoitu'
},
'alexaLoopForecast': {
en: 'According to the loop forecast you are expected to be %1 over the next %2'
, de: 'Entsprechend der Loop Vorhersage landest du bei %1 während der nächsten %2'
, nl: 'Volgens de Loop voorspelling is je waarde %1 over de volgnede %2'
, sv: 'Enligt Loops förutsägelse förväntas du bli %1 inom %2'
, fi: 'Ennusteen mukaan olet %1 seuraavan %2 ajan'
},
'alexaForecastUnavailable': {
en: 'Unable to forecast with the data that is available',
de: 'Mit den verfügbaren Daten ist eine Loop Vorhersage nicht möglich',
nl: 'Niet mogelijk om een voorspelling te doen met de data die beschikbaar is'
,sv: 'Förutsägelse ej möjlig med tillgänlig data'
en: 'Unable to forecast with the data that is available'
, de: 'Mit den verfügbaren Daten ist eine Loop Vorhersage nicht möglich'
, nl: 'Niet mogelijk om een voorspelling te doen met de data die beschikbaar is'
, sv: 'Förutsägelse ej möjlig med tillgänlig data'
, fi: 'Ennusteet eivät ole toiminnassa puuttuvan tiedon vuoksi'
},
'alexaRawBG': {
en: 'Your raw bg is %1'
, de: 'Dein Rohblutzucker ist %1'
, nl: 'Je raw bloedwaarde is %1'
, sv: 'Ditt raw blodsocker är %1'
, fi: 'Suodattamaton verensokeriarvo on %1'
},
'alexaOpenAPSForecast': {
en: 'The OpenAPS Eventual BG is %1'
, de: 'Der von OpenAPS vorhergesagte Blutzucker ist %1'
, nl: 'OpenAPS uiteindelijke bloedglucose van %1'
, sv: 'OpenAPS slutgiltigt blodsocker är %1'
, fi: 'OpenAPS verensokeriarvio on %1'
},
'alexaCOB': {
en: '%1 %2 carbohydrates on board'
, de: '%1 %2 Gramm Kohlenhydrate wirkend.'
, nl: '%1 %2 actieve koolhydraten'
, sv: '%1 %2 gram aktiva kolhydrater'
, fi: '%1 %2 aktiivista hiilihydraattia'
},
'Fat [g]': {
cs: 'Tuk [g]'
Expand Down Expand Up @@ -11543,73 +11558,105 @@ function init() {
,nl: 'Klok'
,sv: 'Klocka'
,de: 'Uhr'
,fi: 'Kello'
},
'Color': {
fr: 'Couleur'
,nl: 'Kleur'
,sv: 'Färg'
,de: 'Farbe'
,fi: 'Väri'
},
'Simple': {
fr: 'Simple'
,nl: 'Simpel'
,sv: 'Simpel'
,de: 'Einfach'
}
,
,fi: 'Yksinkertainen'
},
'TDD average': {
cs: 'Průměrná denní dávka'
, fi: 'Päivän kokonaisinsuliinin keskiarvo'
, nl: 'Gemiddelde dagelijkse insuline (TDD)'
, sv: 'Genomsnittlig daglig mängd insulin'
, de: 'durchschnittliches Insulin pro Tag (TDD)'
}
,
},
'Carbs average': {
cs: 'Průměrné množství sacharidů'
, fi: 'Hiilihydraatit keskiarvo'
, nl: 'Gemiddelde koolhydraten per dag'
, sv: 'Genomsnittlig mängd kolhydrater per dag'
, de: 'durchschnittliche Kohlenhydrate pro Tag'
}
,
},
'Eating Soon': {
fi: 'Ruokailu pian'
, nl: 'Pre-maaltijd modus'
, sv: 'Äter snart'
, de: 'Bald Essen'
}
,
},
'Last entry {0} minutes ago': {
fi: 'Edellinen verensokeri {0} minuuttia sitten'
, nl: 'Laatste waarde {0} minuten geleden'
, sv: 'Senaste värde {0} minuter sedan'
, de: 'Letzter Eintrag vor {0} Minuten'
}
,
},
'change': {
fi: 'muutos'
, nl: 'wijziging'
, sv: 'byta'
, de: 'verändern'
}
,
},
'Speech': {
fi: 'Puhe'
, nl: 'Spraak'
, sv: 'Tal'
, de: 'Sprache'
},
'Target Top': {
fi: 'Tavoite ylä'
, nl: 'Hoog tijdelijk doel'
},
'Target Bottom': {
fi: 'Tavoite ala'
, nl: 'Laag tijdelijk doel'
},
'Canceled': {
fi: 'Peruutettu'
, nl: 'Geannuleerd'
},
'Meter BG': {
fi: 'Mittarin VS'
, nl: 'Bloedglucosemeter waarde'
},
'predicted': {
fi: 'ennuste'
, nl: 'verwachting'
},
'future': {
fi: 'tulevaisuudessa'
, nl: 'toekomstig'
},
'ago': {
fi: 'sitten'
, nl: 'geleden'
},
'min ago': {
fi: 'minuuttia sitten'
, nl: 'minuten geleden'
},
'Last data received': {
fi: 'Tietoa vastaanotettu viimeksi'
, nl: 'Laatste gegevens ontvangen'
}

};

language.translations = translations;


// case sensitive
language.translateCS = function translateCaseSensitive(text) {
if (translations[text] && translations[text][lang]) {
return translations[text][lang];
if (translations[text] && translations[text][language.lang]) {
return translations[text][language.lang];
}
return text;
};
Expand All @@ -11619,8 +11666,8 @@ function init() {
var utext = text.toUpperCase();
_.forEach(translations, function (ts, key) {
var ukey = key.toUpperCase();
if (ukey === utext && ts[lang]) {
text = ts[lang];
if (ukey === utext && ts[language.lang]) {
text = ts[language.lang];
}
});
return text;
Expand Down Expand Up @@ -11655,10 +11702,10 @@ function init() {
};

language.set = function set(newlang) {
lang = newlang;
language.lang = newlang;

language.languages.forEach(function (l) {
if (l.code == lang && l.speechCode) language.speechCode = l.speechCode;
if (l.code == language.lang && l.speechCode) language.speechCode = l.speechCode;
});

return language();
Expand Down
Loading

0 comments on commit cb33193

Please sign in to comment.