mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
Merge branch 'dev' into dev
This commit is contained in:
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
node-version: [14.x, 16.x, 20, lts/*]
|
||||
mongodb-version: [4.4, 5.0, 6.0]
|
||||
|
||||
steps:
|
||||
@@ -87,4 +87,4 @@ jobs:
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
tags: |
|
||||
${{ env.DOCKER_IMAGE }}:${{ steps.package-version.outputs.current-version }}
|
||||
${{ env.DOCKER_IMAGE }}:latest
|
||||
${{ env.DOCKER_IMAGE }}:latest
|
||||
|
||||
@@ -112,7 +112,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
- [`override` (Override Mode)](#override-override-mode)
|
||||
- [`xdripjs` (xDrip-js)](#xdripjs-xdrip-js)
|
||||
- [`alexa` (Amazon Alexa)](#alexa-amazon-alexa)
|
||||
- [`googlehome` (Google Home/DialogFLow)](#googlehome-google-homedialogflow)
|
||||
- [`googlehome` (Google Home/DialogFLow)](#googlehome-google-homedialogflow) [broken]
|
||||
- [`speech` (Speech)](#speech-speech)
|
||||
- [`cors` (CORS)](#cors-cors)
|
||||
- [Extended Settings](#extended-settings)
|
||||
@@ -229,7 +229,7 @@ Once you've installed Nightscout, you can access API documentation by loading `/
|
||||
* Boluses over 2U: `http://localhost:1337/api/v1/treatments.json?find[insulin][$gte]=2`
|
||||
|
||||
The API is Swagger enabled, so you can generate client code to make working with the API easy.
|
||||
To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or review [swagger.yaml](swagger.yaml).
|
||||
To learn more about the Nightscout API, visit https://YOUR-SITE.com/api-docs/ or review [swagger.yaml](lib/server/swagger.yaml).
|
||||
|
||||
## Environment
|
||||
|
||||
@@ -525,7 +525,7 @@ To synchronize from Dexcom Share use the following variables.
|
||||
Optional, `CONNECT_SHARE_REGION` and `CONNECT_SHARE_SERVER` do the same thing, only specify one.
|
||||
* `CONNECT_SHARE_REGION=` `ous` or `us`. `us` is the default if nothing is
|
||||
provided. Selecting `us` sets `CONNECT_SHARE_SERVER` to `share2.dexcom.com`.
|
||||
Selecting `ous` here sets `CONNECT_SHARE_SERVER` to `shareous2.dexcom.com`.
|
||||
Selecting `ous` here sets `CONNECT_SHARE_SERVER` to `shareous1.dexcom.com`.
|
||||
* `CONNECT_SHARE_SERVER=` set the server domain to use.
|
||||
|
||||
|
||||
@@ -666,9 +666,11 @@ For remote overrides, the following extended settings must be configured:
|
||||
##### `alexa` (Amazon Alexa)
|
||||
Integration with Amazon Alexa, [detailed setup instructions](docs/plugins/alexa-plugin.md)
|
||||
|
||||
##### `googlehome` (Google Home/DialogFLow)
|
||||
##### `googlehome` (Google Home/DialogFLow) [broken]
|
||||
Integration with Google Home (via DialogFlow), [detailed setup instructions](docs/plugins/googlehome-plugin.md)
|
||||
|
||||
Unfortunately this integration broke when [Google discontinued conversational actions](https://developers.google.com/assistant/ca-sunset). We'll keep this here for reference, in case it can be revived at some point in the future.
|
||||
|
||||
##### `speech` (Speech)
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# The Google Assistant integration is broken!
|
||||
Unfortunately this integration broke when [Google discontinued conversational actions](https://developers.google.com/assistant/ca-sunset). We'll keep this here for reference, in case it can be revived at some point in the future.
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
|
||||
|
||||
+63
-17
@@ -46,9 +46,11 @@ function AlarmSocket (app, env, ctx) {
|
||||
socket.on('subscribe', function onSubscribe (message, returnCallback) {
|
||||
self.subscribe(socket, message, returnCallback);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Turns all notifications on the event bus back into events to be
|
||||
// broadcast to clients.
|
||||
ctx.bus.on('notification', self.emitNotification);
|
||||
};
|
||||
|
||||
@@ -65,7 +67,7 @@ function AlarmSocket (app, env, ctx) {
|
||||
self.subscribe = function subscribe (socket, message, returnCallback) {
|
||||
const shouldCallBack = typeof(returnCallback) === 'function';
|
||||
|
||||
// Native client
|
||||
// Native client
|
||||
if (message && message.accessToken) {
|
||||
return ctx.authorization.resolveAccessToken(message.accessToken, function resolveFinishForToken (err, auth) {
|
||||
if (err) {
|
||||
@@ -76,13 +78,14 @@ function AlarmSocket (app, env, ctx) {
|
||||
}
|
||||
return err;
|
||||
} else {
|
||||
// Subscribe for acking alarms
|
||||
socket.on('ack', function onAck (level, group, silenceTime) {
|
||||
ctx.notifications.ack(level, group, silenceTime, true);
|
||||
console.info(LOG + 'ack received ' + level + ' ' + group + ' ' + silenceTime);
|
||||
});
|
||||
// Subscribe for acking alarms
|
||||
// Client sends ack, which sends a notificaiton through our internal bus
|
||||
socket.on('ack', function onAck (level, group, silenceTime) {
|
||||
ctx.notifications.ack(level, group, silenceTime, true);
|
||||
console.info(LOG + 'ack received ' + level + ' ' + group + ' ' + silenceTime);
|
||||
});
|
||||
|
||||
var okResponse = { success: true, message: 'Subscribed for alarms' }
|
||||
var okResponse = { success: true, message: 'Subscribed for alarms' }
|
||||
if (shouldCallBack) {
|
||||
returnCallback(okResponse);
|
||||
}
|
||||
@@ -90,10 +93,32 @@ function AlarmSocket (app, env, ctx) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Web client (jwt access token or api_hash)
|
||||
if (message && (message.jwtToken || message.secret)) {
|
||||
|
||||
if (!message) { message = {}; }
|
||||
// Web client (jwt access token or api_hash)
|
||||
/*
|
||||
* On the web: a client may have saved a secret or using a jwtToken, or may have none.
|
||||
* Some pages will automatically prompt for authorization, when needed.
|
||||
* To make the main homepage require authorization as well, set
|
||||
* AUTHENTICATION_PROMPT_ON_LOAD=true.
|
||||
*
|
||||
* If there is missing authorization when authorization is required,
|
||||
* rejecting the attempt in order to trigger a prompt on the client.
|
||||
* If there is no authorization required, or there are available
|
||||
* credentials, attempt to resolve the available permissions.
|
||||
* When processing ACK messages that dismiss alarms, Authorization should be
|
||||
* required.
|
||||
*/
|
||||
var shouldTry = true;
|
||||
if (env.settings.authenticationPromptOnLoad) {
|
||||
if (!message.jwtToken && !message.secret) {
|
||||
shouldTry = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (message && shouldTry) {
|
||||
return ctx.authorization.resolve({ api_secret: message.secret, token: message.jwtToken, ip: getRemoteIP(socket.request) }, function resolveFinish (err, auth) {
|
||||
|
||||
if (err) {
|
||||
console.log(`${LOG_ERROR} Authorization failed for jwtToken:`, message.jwtToken);
|
||||
|
||||
@@ -102,13 +127,34 @@ function AlarmSocket (app, env, ctx) {
|
||||
}
|
||||
return err;
|
||||
} else {
|
||||
// Subscribe for acking alarms
|
||||
socket.on('ack', function onAck (level, group, silenceTime) {
|
||||
ctx.notifications.ack(level, group, silenceTime, true);
|
||||
console.info(LOG + 'ack received ' + level + ' ' + group + ' ' + silenceTime);
|
||||
});
|
||||
var perms = {
|
||||
read: ctx.authorization.checkMultiple('api:*:read', auth.shiros)
|
||||
, ack: ctx.authorization.checkMultiple('notifications:*:ack', auth.shiros)
|
||||
};
|
||||
// Subscribe for acking alarms
|
||||
// TODO: does this produce double ACK after the authorizing? Only if reconnecting?
|
||||
// TODO: how will perms get updated after authorizing?
|
||||
socket.on('ack', function onAck (level, group, silenceTime) {
|
||||
if (perms.ack) {
|
||||
// This goes through the server-wide event bus.
|
||||
ctx.notifications.ack(level, group, silenceTime, true);
|
||||
console.info(LOG + 'ack received ' + level + ' ' + group + ' ' + silenceTime);
|
||||
} else {
|
||||
// TODO: send a message to client to silence locally, but not
|
||||
// globally, and request authorization.
|
||||
// This won't go through th event bus.
|
||||
// var acked = { silenceTime, group, level };
|
||||
// socket.emit('authorization_needed', acked);
|
||||
}
|
||||
});
|
||||
/* TODO: need to know when to update the permissions.
|
||||
// Can we use
|
||||
socket.on('resubscribe', function update_permissions ( ) {
|
||||
// perms = { ... };
|
||||
});
|
||||
*/
|
||||
|
||||
var okResponse = { success: true, message: 'Subscribed for alarms' }
|
||||
var okResponse = { success: true, message: 'Subscribed for alarms', ...perms };
|
||||
if (shouldCallBack) {
|
||||
returnCallback(okResponse);
|
||||
}
|
||||
|
||||
@@ -103,9 +103,7 @@ function parseFilter (opCtx) {
|
||||
}
|
||||
|
||||
return [
|
||||
{ field: 'srvModified', operator: operator, value: lastModified.getTime() },
|
||||
{ field: 'created_at', operator: operator, value: lastModified.toISOString() },
|
||||
{ field: 'date', operator: operator, value: lastModified.getTime() }
|
||||
{ field: 'srvModified', operator: operator, value: lastModified.getTime() }
|
||||
];
|
||||
}
|
||||
|
||||
@@ -116,9 +114,7 @@ function parseFilter (opCtx) {
|
||||
*/
|
||||
function prepareSort () {
|
||||
return {
|
||||
srvModified: 1,
|
||||
created_at: 1,
|
||||
date: 1
|
||||
srvModified: 1
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+29
-9
@@ -1146,15 +1146,13 @@ client.load = function load (serverSettings, callback) {
|
||||
}
|
||||
|
||||
console.log('Subscribed for alarms', data);
|
||||
if (client.settings.authenticationPromptOnLoad && !data.success) {
|
||||
client.hashauth.requestAuthentication(function afterRequest () {
|
||||
client.hashauth.updateSocketAuth();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else if (callback) {
|
||||
callback();
|
||||
var shouldAuthenticationPromptOnLoad = client.settings.authenticationPromptOnLoad ;
|
||||
if (!data.success) {
|
||||
if (!data.read || !hasRequiredPermission() || shouldAuthenticationPromptOnLoad) {
|
||||
return client.hashauth.requestAuthentication(function afterRequest () {
|
||||
return client.hashauth.updateSocketAuth();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1235,6 +1233,28 @@ client.load = function load (serverSettings, callback) {
|
||||
stopAlarm(false, null, notify);
|
||||
}
|
||||
});
|
||||
/*
|
||||
*
|
||||
// TODO: When an unauthorized client attempts to silence an alarm, we should
|
||||
// allow silencing locally, request for authorization, and if the
|
||||
// authorization succeeds even republish the ACK notification. something like...
|
||||
alarmSocket.on('authorization_needed', function(details) {
|
||||
if (alarmInProgress) {
|
||||
console.log('clearing alarm');
|
||||
stopAlarm(true, details.silenceTime, currentNotify);
|
||||
}
|
||||
client.hashauth.requestAuthentication(function afterRequest () {
|
||||
console.log("SUCCESSFULLY AUTHORIZED, REPUBLISHED ACK?");
|
||||
// easiest way to update permission set on server side is to send another message.
|
||||
alarmSocket.emit('resubscribe', currentNotify, details);
|
||||
|
||||
if (isClient && currentNotify) {
|
||||
alarmSocket.emit('ack', currentNotify.level, currentNotify.group, details.silenceTime);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
$('#testAlarms').click(function(event) {
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ function init (fs) {
|
||||
, { code: 'sl', file: 'sl_SL', language: 'Slovenščina', speechCode: 'sl-SL' }
|
||||
, { code: 'sv', file: 'sv_SE', language: 'Svenska', speechCode: 'sv-SE' }
|
||||
, { code: 'tr', file: 'tr_TR', language: 'Türkçe', speechCode: 'tr-TR' }
|
||||
, { code: 'uk', file: 'uk_UA', language: 'українська', speechCode: 'uk-UA' }
|
||||
, { code: 'zh_cn', file: 'zh_CN', language: '中文(简体)', speechCode: 'cmn-Hans-CN' }
|
||||
// , { code: 'zh_tw', file: 'zh_TW', language: '中文(繁體)', speechCode: 'cmn-Hant-TW' }
|
||||
];
|
||||
|
||||
@@ -185,6 +185,10 @@ function init (env, ctx) {
|
||||
notifications.ack(1, group, time);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: modify with a local clear, this will clear all connected clients,
|
||||
* globally
|
||||
*/
|
||||
if (sendClear) {
|
||||
var notify = {
|
||||
clear: true
|
||||
@@ -192,6 +196,8 @@ function init (env, ctx) {
|
||||
, message: group + ' - ' + ctx.levels.toDisplay(level) + ' was ack\'d'
|
||||
, group: group
|
||||
};
|
||||
// When web client sends ack, this translates the websocket message into
|
||||
// an event on our internal bus.
|
||||
ctx.bus.emit('notification', notify);
|
||||
logEmitEvent(notify);
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ function init (ctx) {
|
||||
function addSuggestion () {
|
||||
if (prop.lastSuggested) {
|
||||
var bg = prop.lastSuggested.bg;
|
||||
var units = sbx.data.profile.getUnits();
|
||||
var units = sbx.settings.units;
|
||||
|
||||
if (units === 'mmol') {
|
||||
bg = Math.round(bg / consts.MMOL_TO_MGDL * 10) / 10;
|
||||
@@ -478,9 +478,15 @@ function init (ctx) {
|
||||
|
||||
if ('enacted' === prop.status.code) {
|
||||
var canceled = prop.lastEnacted.rate === 0 && prop.lastEnacted.duration === 0;
|
||||
var bg = prop.lastEnacted.bg;
|
||||
var units = sbx.settings.units;
|
||||
|
||||
if (units === 'mmol') {
|
||||
bg = Math.round(bg / consts.MMOL_TO_MGDL * 10) / 10;
|
||||
}
|
||||
|
||||
var valueParts = [
|
||||
valueString('BG: ', prop.lastEnacted.bg)
|
||||
valueString('BG: ', bg)
|
||||
, ', <b>Temp Basal' + (canceled ? ' Canceled' : ' Started') + '</b>'
|
||||
, canceled ? '' : ' ' + prop.lastEnacted.rate.toFixed(2) + ' for ' + prop.lastEnacted.duration + 'm'
|
||||
, valueString(', ', prop.lastEnacted.reason)
|
||||
|
||||
@@ -18,6 +18,7 @@ var init = function init () {
|
||||
|
||||
client.init(function loaded () {
|
||||
|
||||
console.log("LOADING CLIENT INIT");
|
||||
if (c_profile !== null) {
|
||||
return; // already loaded so don't load again
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ function bootError(env, ctx) {
|
||||
return '<dt><b>' + obj.desc + '</b></dt><dd>' + message.replace(/\\n/g, '<br/>') + '</dd>';
|
||||
}).join(' ');
|
||||
|
||||
res.render('error.html', {
|
||||
res.status(500).render('error.html', {
|
||||
errors,
|
||||
locals
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ function boot (env, language) {
|
||||
|
||||
const isLTS = process.release.lts ? true : false;
|
||||
|
||||
if (isLTS && (semver.satisfies(nodeVersion, '^20.0.0') || semver.satisfies(nodeVersion, '^18.0.0') || semver.satisfies(nodeVersion, '^16.0.0') || semver.satisfies(nodeVersion, '^14.0.0'))) {
|
||||
if (isLTS || (semver.satisfies(nodeVersion, '^20.0.0') || semver.satisfies(nodeVersion, '^18.0.0') || semver.satisfies(nodeVersion, '^16.0.0') || semver.satisfies(nodeVersion, '^14.0.0'))) {
|
||||
//Latest Node 14 LTS and Node 16 LTS are recommended and supported.
|
||||
//Require at least Node 14 without known security issues
|
||||
console.debug('Node LTS version ' + nodeVersion + ' is supported');
|
||||
|
||||
+25
-3
@@ -130,14 +130,36 @@ function init (env, ctx) {
|
||||
notification.payload = payload;
|
||||
notification.interruptionLevel = "time-sensitive"
|
||||
|
||||
provider.send(notification, [loopSettings.deviceToken]).then( (response) => {
|
||||
provider.send(notification, [loopSettings.deviceToken]).then((response) => {
|
||||
if (response.sent && response.sent.length > 0) {
|
||||
completion();
|
||||
} else {
|
||||
console.log("APNs delivery failed:", response.failed)
|
||||
completion("APNs delivery failed: " + response.failed[0].response.reason);
|
||||
console.log("APNs delivery failed:", response.failed);
|
||||
|
||||
// Check if response.failed and response.failed[0] are defined
|
||||
if (response.failed && response.failed.length > 0) {
|
||||
const failedResponse = response.failed[0];
|
||||
const reason = failedResponse.response && failedResponse.response.reason
|
||||
? failedResponse.response.reason
|
||||
: 'Unknown reason';
|
||||
|
||||
// Provide detailed debugging information
|
||||
const errorMessage = `APNs delivery failed: ${reason}`;
|
||||
console.error(errorMessage, failedResponse);
|
||||
completion(errorMessage);
|
||||
} else {
|
||||
// Handle the case where response.failed is undefined or empty
|
||||
const errorMessage = 'APNs delivery failed: No failure details available.';
|
||||
console.error(errorMessage, response);
|
||||
completion(errorMessage);
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
// Catch any other unexpected errors
|
||||
console.error('Unexpected error during APNs delivery:', error);
|
||||
completion(`APNs delivery failed: ${error.message || 'Unknown error'}`);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return loop();
|
||||
|
||||
@@ -75,7 +75,9 @@ function init (env, ctx, server) {
|
||||
'log level': 0
|
||||
}).listen(server, {
|
||||
//these only effect the socket.io.js file that is sent to the client, but better than nothing
|
||||
'browser client minification': true
|
||||
// compat with v2 client
|
||||
allowEIO3: true
|
||||
, 'browser client minification': true
|
||||
, 'browser client etag': true
|
||||
, 'browser client gzip': false
|
||||
, 'perMessageDeflate': {
|
||||
|
||||
Generated
+7
-7
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nightscout",
|
||||
"version": "15.0.0",
|
||||
"version": "15.0.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -6367,9 +6367,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"nightscout-connect": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/nightscout-connect/-/nightscout-connect-0.0.11.tgz",
|
||||
"integrity": "sha512-O7wMMG6BgW7Wxm0hr4Fj9SO1IH/7f29obKSnN8V9I2Ko4v5XxL5FqoONpmvlgI6So0MwksoMCcedSCiCL6Lj4A==",
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/nightscout-connect/-/nightscout-connect-0.0.12.tgz",
|
||||
"integrity": "sha512-y4Dc+shzkmGQqJG2w2zNp1Jnu4Yzc4VtSCoBiinrssjy+7ksjmOenxVDyh0Xw2UCWMkqr4A4o+iJ28KvrHWcvw==",
|
||||
"requires": {
|
||||
"axios": "^1.3.4",
|
||||
"axios-cookiejar-support": "^4.0.6",
|
||||
@@ -6380,9 +6380,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
|
||||
"integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nightscout",
|
||||
"version": "15.0.0",
|
||||
"version": "15.0.4",
|
||||
"description": "Nightscout acts as a web-based CGM (Continuous Glucose Montinor) to allow multiple caregivers to remotely view a patients glucose data in realtime.",
|
||||
"license": "AGPL-3.0",
|
||||
"author": "Nightscout Team",
|
||||
@@ -116,7 +116,7 @@
|
||||
"mongo-url-parser": "^1.0.2",
|
||||
"mongodb": "^3.6.0",
|
||||
"mongomock": "^0.1.2",
|
||||
"nightscout-connect": "^0.0.11",
|
||||
"nightscout-connect": "^0.0.12",
|
||||
"node-cache": "^4.2.1",
|
||||
"parse-duration": "^0.1.3",
|
||||
"process": "^0.11.10",
|
||||
|
||||
+14
-14
@@ -329,15 +329,15 @@
|
||||
"Edit treatment": "تعديل المعالجة",
|
||||
"Duration": "المدة",
|
||||
"Duration in minutes": "المدة بالدقائق",
|
||||
"Temp Basal": "درجة الحرارة القاعدية",
|
||||
"Temp Basal Start": "بداية درجة الحرارة القاعدية",
|
||||
"Temp Basal End": "نهاية درجة الحرارة القاعدية",
|
||||
"Temp Basal": "الجرعة القاعدية المؤقتة",
|
||||
"Temp Basal Start": "بداية الجرعة القاعدية المؤقتة",
|
||||
"Temp Basal End": "نهاية الجرعة القاعدية المؤقتة",
|
||||
"Percent": "بالمائة",
|
||||
"Basal change in %": "التغيير الأساسي بالمائة",
|
||||
"Basal value": "القيمة الأساسية",
|
||||
"Absolute basal value": "القيمة الأساسية المطلقة",
|
||||
"Announcement": "إعلان",
|
||||
"Loading temp basal data": "تحميل درجة حرارة البيانات القاعدية",
|
||||
"Loading temp basal data": "جارٍ تحميل بيانات الجرعة القاعدية المؤقتة",
|
||||
"Save current record before changing to new?": "حفظ السجل الحالي قبل التغيير إلى جديد؟",
|
||||
"Profile Switch": "تبديل الملف الشخصي",
|
||||
"Profile": "الملف الشخصي",
|
||||
@@ -413,8 +413,8 @@
|
||||
"Targets": "الأهداف",
|
||||
"Bolus insulin:": "جرعة أنسولين:",
|
||||
"Base basal insulin:": "الأنسولين القاعدي الأساسي:",
|
||||
"Positive temp basal insulin:": "الأنسولين القاعدي ذو درجة الحرارة الإيجابية:",
|
||||
"Negative temp basal insulin:": "الأنسولين القاعدي ذو درجة الحرارة السلبية:",
|
||||
"Positive temp basal insulin:": "الأنسولين القاعدي المؤقت الإيجابي:",
|
||||
"Negative temp basal insulin:": "الأنسولين القاعدي المؤقت السلبي:",
|
||||
"Total basal insulin:": "إجمالي الأنسولين القاعدي:",
|
||||
"Total daily insulin:": "إجمالي الأنسولين اليومي:",
|
||||
"Unable to save Role": "تعذر حفظ الدور",
|
||||
@@ -452,10 +452,10 @@
|
||||
"Current Carb Ratio": "نسبة الكربوهيدرات الحالية",
|
||||
"Basal timezone": "المنطقة الزمنية القاعدية",
|
||||
"Active profile": "ملف نشط",
|
||||
"Active temp basal": "درجة الحرارة القاعدية النشطة",
|
||||
"Active temp basal start": "بداية درجة الحرارة القاعدية النشطة",
|
||||
"Active temp basal duration": "مدة درجة الحرارة القاعدية النشطة",
|
||||
"Active temp basal remaining": "درجة الحرارة القاعدية النشطة المتبقية",
|
||||
"Active temp basal": "الجرعة القاعدية المؤقتة النشطة",
|
||||
"Active temp basal start": "بداية الجرعة القاعدية المؤقتة النشطة",
|
||||
"Active temp basal duration": "مدة الجرعة القاعدية المؤقتة النشطة",
|
||||
"Active temp basal remaining": "الوقت المتبقي للجرعة القاعدية المؤقتة النشطة",
|
||||
"Basal profile value": "قيمة الملف القاعدي",
|
||||
"Active combo bolus": "جرعة تركيبة نشطة",
|
||||
"Active combo bolus start": "بداية جرعة تركيبة نشطة",
|
||||
@@ -492,8 +492,8 @@
|
||||
"or adjust basal": "أو ضبط القاعدية",
|
||||
"Check BG using glucometer before correcting!": "-> تحقق من نسبة السكر في الدم باستخدام مقياس السكر قبل التصحيح!",
|
||||
"Basal reduction to account %1 units:": "التخفيض القاعدي لحساب%1 وحدة:",
|
||||
"30m temp basal": "30 متر من درجة الحرارة القاعدية",
|
||||
"1h temp basal": "ساعة واحدة من درجة الحرارة القاعدية",
|
||||
"30m temp basal": "جرعة قاعدية مؤقتة لمدة 30 دقيقة",
|
||||
"1h temp basal": "جرعة قاعدية مؤقتة لمدة ساعة واحدة",
|
||||
"Cannula change overdue!": "تغيير قنية متأخر!",
|
||||
"Time to change cannula": "ميعاد تغيير القنية الطبية",
|
||||
"Change cannula soon": "تغيير القنية الطبية قريبا",
|
||||
@@ -578,7 +578,7 @@
|
||||
"virtAsstTitleDelta": "دلتا جلوكوز الدم",
|
||||
"virtAsstStatus": "%1 و%2 اعتبارًا من %3.",
|
||||
"virtAsstBasal": "%1 القاعدي الحالي هو %2 وحدة في الساعة",
|
||||
"virtAsstBasalTemp": "%1 درجة الحرارة القاعدية من %2 وحدة في الساعة ستنتهي %3",
|
||||
"virtAsstBasalTemp": "%1 جرعة قاعدية مؤقتة من %2 وحدة في الساعة ستنتهي %3",
|
||||
"virtAsstIob": "ولديك %1 من الأنسولين النشط.",
|
||||
"virtAsstIobIntent": "لديك %1 من الأنسولين النشط",
|
||||
"virtAsstIobUnits": "%1 وحدة من",
|
||||
@@ -682,7 +682,7 @@
|
||||
"Previous day": "اليوم السابق",
|
||||
"Next day": "اليوم التالي",
|
||||
"Next": "التالي",
|
||||
"Temp basal delta": "درجة حرارة دلتا الأساسية",
|
||||
"Temp basal delta": "تغير الجرعة القاعدية المؤقتة",
|
||||
"Authorized by token": "مصرح به من قبل رمز",
|
||||
"Auth role": "دور المصادقة",
|
||||
"view without token": "عرض بدون رمز",
|
||||
|
||||
+37
-37
@@ -617,8 +617,8 @@
|
||||
"Fat [g]": "Λιπαρά [g]",
|
||||
"Protein [g]": "Πρωτεΐνη [g]",
|
||||
"Energy [kJ]": "Ενέργεια [kJ]",
|
||||
"Clock Views:": "Clock Views:",
|
||||
"Clock": "Clock",
|
||||
"Clock Views:": "Εμφανίσεις ρολογιού:",
|
||||
"Clock": "Ρολόι",
|
||||
"Color": "Χρώμα",
|
||||
"Simple": "Απλή",
|
||||
"TDD average": "Μέσος όρος Συνολικής πρόσληψης ημερήσιας ινσουλίνης",
|
||||
@@ -627,18 +627,18 @@
|
||||
"Base basal average:": "Μέσος όρος βασικού ρυθμού:",
|
||||
"Carbs average": "Μέσος όρος υδατανθράκων",
|
||||
"Eating Soon": "Eating Soon",
|
||||
"Last entry {0} minutes ago": "Last entry {0} minutes ago",
|
||||
"change": "change",
|
||||
"Speech": "Speech",
|
||||
"Target Top": "Target Top",
|
||||
"Target Bottom": "Target Bottom",
|
||||
"Last entry {0} minutes ago": "Τελευταία καταχώρηση πριν από {0} λεπτά",
|
||||
"change": "αλλαγή",
|
||||
"Speech": "Εκφώνηση",
|
||||
"Target Top": "Υψηλός στόχος",
|
||||
"Target Bottom": "Χαμηλός στόχος",
|
||||
"Canceled": "Canceled",
|
||||
"Meter BG": "Meter BG",
|
||||
"predicted": "predicted",
|
||||
"future": "future",
|
||||
"ago": "ago",
|
||||
"Last data received": "Last data received",
|
||||
"Clock View": "Clock View",
|
||||
"predicted": "προβλεπόμενο",
|
||||
"future": "μέλλον",
|
||||
"ago": "πριν",
|
||||
"Last data received": "Τελευταία λήψη δεδομένων",
|
||||
"Clock View": "Εμφάνιση ρολογιού",
|
||||
"Protein": "Πρωτεΐνες",
|
||||
"Fat": "Λιπαρά",
|
||||
"Protein average": "Μέσος όρος πρωτεϊνών",
|
||||
@@ -646,30 +646,30 @@
|
||||
"Total carbs": "Σύνολο υδατανθράκων",
|
||||
"Total protein": "Σύνολο πρωτεϊνών",
|
||||
"Total fat": "Σύνολο λιπαρών",
|
||||
"Database Size": "Database Size",
|
||||
"Database Size near its limits!": "Database Size near its limits!",
|
||||
"Database size is %1 MiB out of %2 MiB. Please backup and clean up database!": "Database size is %1 MiB out of %2 MiB. Please backup and clean up database!",
|
||||
"Database file size": "Database file size",
|
||||
"%1 MiB of %2 MiB (%3%)": "%1 MiB of %2 MiB (%3%)",
|
||||
"Data size": "Data size",
|
||||
"virtAsstDatabaseSize": "%1 MiB. That is %2% of available database space.",
|
||||
"virtAsstTitleDatabaseSize": "Database file size",
|
||||
"Database Size": "Μέγεθος βάσης δεδομένων",
|
||||
"Database Size near its limits!": "Μέγεθος βάσης δεδομένων κοντά στα όριά της!",
|
||||
"Database size is %1 MiB out of %2 MiB. Please backup and clean up database!": "Το μέγεθος της βάσης δεδομένων είναι %1 MiB από %2 MiB. Παρακαλώ δημιουργήστε αντίγραφα ασφαλείας και καθαρίστε τη!",
|
||||
"Database file size": "Μέγεθος αρχείου βάσης δεδομένων",
|
||||
"%1 MiB of %2 MiB (%3%)": "%1 MiB από %2 MiB (%3%)",
|
||||
"Data size": "Μέγεθος δεδομένων",
|
||||
"virtAsstDatabaseSize": "%1 MiB. Αυτό είναι %2% του διαθέσιμου χώρου βάσης δεδομένων.",
|
||||
"virtAsstTitleDatabaseSize": "Μέγεθος αρχείου βάσης δεδομένων",
|
||||
"Carbs/Food/Time": "Υδατάνθρακες/Φαγητό/Χρόνος",
|
||||
"You have administration messages": "You have administration messages",
|
||||
"You have administration messages": "Έχετε μηνύματα διαχείρισης",
|
||||
"Admin messages in queue": "Διαθέσιμα μηνύματα διαχειριστή",
|
||||
"Queue empty": "Σειρά μηνυμάτων κενή",
|
||||
"There are no admin messages in queue": "Δεν υπάρχουν αδιάβαστα μηνύματα διαχείρισης",
|
||||
"Please sign in using the API_SECRET to see your administration messages": "Παρακαλούμε συνδεθείτε χρησιμοποιώντας το API_SECRET για να δείτε τα μηνύματα διαχείρισης",
|
||||
"Reads enabled in default permissions": "Reads enabled in default permissions",
|
||||
"Data reads enabled": "Data reads enabled",
|
||||
"Data writes enabled": "Data writes enabled",
|
||||
"Data writes not enabled": "Data writes not enabled",
|
||||
"Reads enabled in default permissions": "Οι αναγνώσεις είναι ενεργοποιημένες με προεπιλεγμένα δικαιώματα",
|
||||
"Data reads enabled": "Ανάγνωση δεδομένων ενεργή",
|
||||
"Data writes enabled": "Εγγραφή δεδομένων ενεργή",
|
||||
"Data writes not enabled": "Εγγραφή δεδομένων ανενεργή",
|
||||
"Color prediction lines": "Γραμμές πρόβλεψης με χρωματικό κώδικα",
|
||||
"Release Notes": "Σημειώσεις έκδοσης",
|
||||
"Check for Updates": "Έλεγχος για ενημερώσεις",
|
||||
"Open Source": "Ανοικτός κώδικας",
|
||||
"Nightscout Info": "Πληροφορίες Nightscout",
|
||||
"The primary purpose of Loopalyzer is to visualise how the Loop closed loop system performs. It may work with other setups as well, both closed and open loop, and non loop. However depending on which uploader you use, how frequent it is able to capture your data and upload, and how it is able to backfill missing data some graphs may have gaps or even be completely empty. Always ensure the graphs look reasonable. Best is to view one day at a time and scroll through a number of days first to see.": "The primary purpose of Loopalyzer is to visualise how the Loop closed loop system performs. It may work with other setups as well, both closed and open loop, and non loop. However depending on which uploader you use, how frequent it is able to capture your data and upload, and how it is able to backfill missing data some graphs may have gaps or even be completely empty. Always ensure the graphs look reasonable. Best is to view one day at a time and scroll through a number of days first to see.",
|
||||
"The primary purpose of Loopalyzer is to visualise how the Loop closed loop system performs. It may work with other setups as well, both closed and open loop, and non loop. However depending on which uploader you use, how frequent it is able to capture your data and upload, and how it is able to backfill missing data some graphs may have gaps or even be completely empty. Always ensure the graphs look reasonable. Best is to view one day at a time and scroll through a number of days first to see.": "Ο κύριος σκοπός του Loopalyzer είναι να απεικονίσει την επίδοση του συστήματος κλειστού κυκλώματος. Μπορεί να λειτουργήσει είστε με τη λειτουργία κλειστού κυκλώματος, ανοιχτού κυκλώματος, ή και χωρίς κύκλωμα καθόλου. Ανάλογα με τον uploader που χρησιμοποιείτε, το πόσο συχνά καταγράφει και ανεβάζει τα δεδομένα σας, και το πώς μπορεί να συμπληρώσει προηγούμενα δεδομένα, ενδέχεται μερικά γραφήματα να έχουν κενά ή να είναι εντελώς άδεια. Πάντα να σιγουρεύεστε πως το γράφημα απεικονίζει λογικές πληροφορίες. Καλό θα ήταν αρχικά να κοιτάξετε δεδομένα μια μέρα τη φορά για μερικές ημέρες.",
|
||||
"Loopalyzer includes a time shift feature. If you for example have breakfast at 07:00 one day and at 08:00 the day after your average blood glucose curve these two days will most likely look flattened and not show the actual response after a breakfast. Time shift will compute the average time these meals were eaten and then shift all data (carbs, insulin, basal etc.) during both days the corresponding time difference so that both meals align with the average meal start time.": "Loopalyzer includes a time shift feature. If you for example have breakfast at 07:00 one day and at 08:00 the day after your average blood glucose curve these two days will most likely look flattened and not show the actual response after a breakfast. Time shift will compute the average time these meals were eaten and then shift all data (carbs, insulin, basal etc.) during both days the corresponding time difference so that both meals align with the average meal start time.",
|
||||
"In this example all data from first day is pushed 30 minutes forward in time and all data from second day 30 minutes backward in time so it appears as if you had had breakfast at 07:30 both days. This allows you to see your actual average blood glucose response from a meal.": "In this example all data from first day is pushed 30 minutes forward in time and all data from second day 30 minutes backward in time so it appears as if you had had breakfast at 07:30 both days. This allows you to see your actual average blood glucose response from a meal.",
|
||||
"Time shift highlights the period after the average meal start time in gray, for the duration of the DIA (Duration of Insulin Action). As all data points the entire day are shifted the curves outside the gray area may not be accurate.": "Time shift highlights the period after the average meal start time in gray, for the duration of the DIA (Duration of Insulin Action). As all data points the entire day are shifted the curves outside the gray area may not be accurate.",
|
||||
@@ -678,23 +678,23 @@
|
||||
"Show profiles table": "Show profiles table",
|
||||
"Show predictions": "Εμφάνιση προβλέψεων",
|
||||
"Timeshift on meals larger than %1 g carbs consumed between %2 and %3": "Χρονική μετατόπιση για γεύματα μεγαλύτερα από %1 γρ. υδατανθράκων που καταναλώνονται μεταξύ %2 και %3",
|
||||
"Previous": "Previous",
|
||||
"Previous day": "Previous day",
|
||||
"Next day": "Next day",
|
||||
"Next": "Next",
|
||||
"Temp basal delta": "Temp basal delta",
|
||||
"Previous": "Προηγούμενο",
|
||||
"Previous day": "Προηγούμενη ημέρα",
|
||||
"Next day": "Επόμενη ημέρα",
|
||||
"Next": "Επόμενο",
|
||||
"Temp basal delta": "Μεταβολή προσωρινού βασικού ρυθμού",
|
||||
"Authorized by token": "Πιστοποίηση από Token",
|
||||
"Auth role": "Πιστοποίηση ρόλου",
|
||||
"view without token": "view without token",
|
||||
"view without token": "προβολή χωρίς συνθηματικό",
|
||||
"Remove stored token": "Αφαίρεση αποθηκευμένου token",
|
||||
"Weekly Distribution": "Εβδομαδιαία Κατανομή",
|
||||
"Failed authentication": "Αποτυχία ταυτοποίησης στοιχείων",
|
||||
"A device at IP address %1 attempted authenticating with Nightscout with wrong credentials. Check if you have an uploader setup with wrong API_SECRET or token?": "Έγινε προσπάθεια πιστοποίησης στο Nightscout μια συσκευής από τη διεύθυνση IP %1 με λάθος διαπιστευτήρια. Ελέγξτε αν έχετε ρυθμίσει τον uploader με λάθος API_SECRET ή token.",
|
||||
"Default (with leading zero and U)": "Default (with leading zero and U)",
|
||||
"Concise (with U, without leading zero)": "Concise (with U, without leading zero)",
|
||||
"Minimal (without leading zero and U)": "Minimal (without leading zero and U)",
|
||||
"Small Bolus Display": "Small Bolus Display",
|
||||
"Large Bolus Display": "Large Bolus Display",
|
||||
"Default (with leading zero and U)": "Προεπιλογή (με αρχικό μηδέν και U)",
|
||||
"Concise (with U, without leading zero)": "Συνοπτική (με U, χωρίς μηδενικό προβάδισμα)",
|
||||
"Minimal (without leading zero and U)": "Ελάχιστη (χωρίς μηδενικό προβάδισμα και U)",
|
||||
"Small Bolus Display": "Απεικόνιση μικρού Bolus",
|
||||
"Large Bolus Display": "Απεικόνιση μεγάλου Bolus",
|
||||
"Bolus Display Threshold": "Bolus Display Threshold",
|
||||
"%1 U and Over": "%1 U and Over",
|
||||
"Event repeated %1 times.": "Η ενέργεια επανλήφθηκε %1 φορές.",
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
"View all treatments": "Visualizar todos los tratamientos",
|
||||
"Enable Alarms": "Activar las alarmas",
|
||||
"Pump Battery Change": "Cambio batería bomba",
|
||||
"Pump Battery Age": "Edad de la batería en la bomba",
|
||||
"Pump Battery Age": "Edad de la batería de la bomba",
|
||||
"Pump Battery Low Alarm": "Alarma de Bomba Baja",
|
||||
"Pump Battery change overdue!": "Cambio de batería de bomba atrasado!",
|
||||
"When enabled an alarm may sound.": "Cuando estén activas, una alarma podrá sonar",
|
||||
@@ -702,6 +702,7 @@
|
||||
"Last recorded %1 %2 ago.": "Última grabación hace %1 %2.",
|
||||
"Security issue": "Problema de seguridad",
|
||||
"Weak API_SECRET detected. Please use a mix of small and CAPITAL letters, numbers and non-alphanumeric characters such as !#%&/ to reduce the risk of unauthorized access. The minimum length of the API_SECRET is 12 characters.": "Detectada API_SECRET débil. Por favor, utilice una mezcla de letras en minúscula y en mayúscula, números y caracteres no alfanuméricos como !#%&/ para reducir el riesgo de acceso no autorizado. La longitud mínima de la API_SECRET es de 12 caracteres.",
|
||||
"less than 1": "menos que 1",
|
||||
"less than 1": "menos de 1",
|
||||
"MongoDB password and API_SECRET match. This is a really bad idea. Please change both and do not reuse passwords across the system.": "La contraseña de MongoDB y la API_SECRET coinciden. Esto es una muy mala idea. Por favor, cambie ambas contraseñas y no reutilice contraseñas en el sistema."
|
||||
"virtAsstLaunch":"¿Qué quieres saber de Nightscout?"
|
||||
}
|
||||
|
||||
+16
-16
@@ -102,9 +102,9 @@
|
||||
"Move to the top": "Spostare verso l'alto",
|
||||
"Hidden": "Nascosto",
|
||||
"Hide after use": "Nascondi dopo l'uso",
|
||||
"Your API secret must be at least 12 characters long": "Il tuo API segreto deve essere lungo almeno 12 caratteri",
|
||||
"Bad API secret": "API segreto non corretto",
|
||||
"API secret hash stored": "Hash API segreto memorizzato",
|
||||
"Your API secret must be at least 12 characters long": "Il tuo \"API secret\" deve essere lungo almeno 12 caratteri",
|
||||
"Bad API secret": "\"API secret\" non corretto",
|
||||
"API secret hash stored": "Hash \"API secret\" memorizzato",
|
||||
"Status": "Stato",
|
||||
"Not loaded": "Non caricato",
|
||||
"Food Editor": "Database Alimenti",
|
||||
@@ -115,8 +115,8 @@
|
||||
"Record": "Registro",
|
||||
"Quick picks": "Scelta rapida",
|
||||
"Show hidden": "Mostra nascosto",
|
||||
"Your API secret or token": "Il tuo API segreto o token",
|
||||
"Remember this device. (Do not enable this on public computers.)": "Ricorda questo dispositivo. (Da non abilitare su computer condivisi con altri.)",
|
||||
"Your API secret or token": "Il tuo token \"API secret\"",
|
||||
"Remember this device. (Do not enable this on public computers.)": "Ricorda questo dispositivo. (Da non abilitare su computer condivisi con altri)",
|
||||
"Treatments": "Somministrazioni",
|
||||
"Time": "Tempo",
|
||||
"Event Type": "Tipo di evento",
|
||||
@@ -128,7 +128,7 @@
|
||||
"Event Time": "Ora Evento",
|
||||
"Please verify that the data entered is correct": "Verificare che i dati inseriti siano corretti",
|
||||
"BG": "Glicemie",
|
||||
"Use BG correction in calculation": "Utilizza la correzione delle Glicemia nel calcolo",
|
||||
"Use BG correction in calculation": "Utilizza la correzione delle Glicemie nel calcolo",
|
||||
"BG from CGM (autoupdated)": "Glicemie da sensore (aggiornamento automatico)",
|
||||
"BG from meter": "Glicemie da glucometro",
|
||||
"Manual BG": "Inserisci Glicemia",
|
||||
@@ -424,7 +424,7 @@
|
||||
"admin, school, family, etc": "amministrazione, scuola, famiglia, etc",
|
||||
"Permissions": "Permessi",
|
||||
"Are you sure you want to delete: ": "Sei sicuro di voler eliminare:",
|
||||
"Each role will have a 1 or more permissions. The <em>*</em> permission is a wildcard, permissions are a hierarchy using <em>:</em> as a separator.": "Ogni ruolo avrà un 1 o più autorizzazioni. Il <em>*</em> il permesso è un jolly, i permessi sono una gerarchia utilizzando <em>:</em> come separatore.",
|
||||
"Each role will have a 1 or more permissions. The <em>*</em> permission is a wildcard, permissions are a hierarchy using <em>:</em> as a separator.": "Ogni ruolo avrà 1 o più autorizzazioni. Il permesso <em>*</em> è un jolly, i permessi sono una gerarchia utilizzando <em>:</em> come separatore.",
|
||||
"Add new Role": "Aggiungere un nuovo ruolo",
|
||||
"Roles - Groups of People, Devices, etc": "Ruoli - gruppi di persone, dispositivi, etc",
|
||||
"Edit this role": "Modifica questo ruolo",
|
||||
@@ -470,7 +470,7 @@
|
||||
"Warning": "Avviso",
|
||||
"Info": "Informazioni",
|
||||
"Lowest": "Minore",
|
||||
"Snoozing high alarm since there is enough IOB": "Addormenta allarme alto poiché non vi è sufficiente Insulina attiva",
|
||||
"Snoozing high alarm since there is enough IOB": "Silenzia allarme alto poiché non vi è sufficiente Insulina attiva",
|
||||
"Check BG, time to bolus?": "Controllare Glicemia, ora di bolo?",
|
||||
"Notice": "Preavviso",
|
||||
"required info missing": "richiesta informazioni mancanti",
|
||||
@@ -479,9 +479,9 @@
|
||||
"Expected effect": "Effetto Previsto",
|
||||
"Expected outcome": "Risultato previsto",
|
||||
"Carb Equivalent": "Carb equivalenti",
|
||||
"Excess insulin equivalent %1U more than needed to reach low target, not accounting for carbs": "L'eccesso d'insulina equivalente %1U più che necessari per raggiungere l'obiettivo basso, non rappresentano i carboidrati.",
|
||||
"Excess insulin equivalent %1U more than needed to reach low target, MAKE SURE IOB IS COVERED BY CARBS": "L' eccesso d'insulina equivale a %1U in più di quanto necessario per raggiungere l'obiettivo basso, ASSICURARSI CHE L'INSULINA ATTIVA SIA COPERTA DAI CARBOIDRATI",
|
||||
"%1U reduction needed in active insulin to reach low target, too much basal?": "Riduzione %1U necessaria dell'insulina attiva per raggiungere l'obiettivo basso, troppa basale?",
|
||||
"Excess insulin equivalent %1U more than needed to reach low target, not accounting for carbs": "Eccesso di insulina equivalente a %1U, più che necessaria per raggiungere l'obiettivo basso, non contando i carboidrati",
|
||||
"Excess insulin equivalent %1U more than needed to reach low target, MAKE SURE IOB IS COVERED BY CARBS": "Eccesso di insulina equivalente a %1U in più di quanto necessario per raggiungere l'obiettivo basso, ASSICURARSI CHE L'INSULINA ATTIVA SIA COPERTA DAI CARBOIDRATI",
|
||||
"%1U reduction needed in active insulin to reach low target, too much basal?": "Riduzione %1U necessaria all'insulina attiva per raggiungere l'obiettivo basso, troppa basale?",
|
||||
"basal adjustment out of range, give carbs?": "regolazione basale fuori intervallo, dare carboidrati?",
|
||||
"basal adjustment out of range, give bolus?": "regolazione basale fuori campo, dare bolo?",
|
||||
"above high": "sopra alto",
|
||||
@@ -505,7 +505,7 @@
|
||||
"IAGE": "Età Insulina",
|
||||
"Insulin reservoir change overdue!": "Cambio serbatoio d'insulina in ritardo!",
|
||||
"Time to change insulin reservoir": "Momento di cambiare serbatoio d'insulina",
|
||||
"Change insulin reservoir soon": "Cambiare serbatoio d'insulina prossimamente",
|
||||
"Change insulin reservoir soon": "Cambiare serbatoio d'insulina a breve",
|
||||
"Insulin reservoir age %1 hours": "IAGE - Durata Serbatoio d'insulina %1 ore",
|
||||
"Changed": "Cambiato",
|
||||
"IOB": "Insulina Attiva",
|
||||
@@ -521,7 +521,7 @@
|
||||
"RETRO": "RETRO",
|
||||
"SAGE": "Età Sensore",
|
||||
"Sensor change/restart overdue!": "Cambio/riavvio del sensore in ritardo!",
|
||||
"Time to change/restart sensor": "Tempo di cambiare/riavvio sensore",
|
||||
"Time to change/restart sensor": "Tempo di cambiare/riavviare sensore",
|
||||
"Change/restart sensor soon": "Modifica/riavvio sensore prossimamente",
|
||||
"Sensor age %1 days %2 hours": "Durata Sensore %1 giorni %2 ore",
|
||||
"Sensor Insert": "SAGE - inserimento sensore",
|
||||
@@ -659,7 +659,7 @@
|
||||
"Admin messages in queue": "Messaggi di amministrazione in coda",
|
||||
"Queue empty": "Coda vuota",
|
||||
"There are no admin messages in queue": "Non ci sono messaggi di amministrazione in coda",
|
||||
"Please sign in using the API_SECRET to see your administration messages": "Effettua il login utilizzando API_SECRET per vedere i messaggi di amministrazione",
|
||||
"Please sign in using the API_SECRET to see your administration messages": "Effettua il login utilizzando \"API secret\" per vedere i messaggi di amministrazione",
|
||||
"Reads enabled in default permissions": "Letture abilitate nelle autorizzazioni predefinite",
|
||||
"Data reads enabled": "Lettura dati abilitata",
|
||||
"Data writes enabled": "Scrittura dati abilitata",
|
||||
@@ -701,7 +701,7 @@
|
||||
"minutes": "minuti",
|
||||
"Last recorded %1 %2 ago.": "Ultima registrazione %1 %2 fa.",
|
||||
"Security issue": "Problema di sicurezza",
|
||||
"Weak API_SECRET detected. Please use a mix of small and CAPITAL letters, numbers and non-alphanumeric characters such as !#%&/ to reduce the risk of unauthorized access. The minimum length of the API_SECRET is 12 characters.": "Rilevata API_SECRET debole. Si prega di utilizzare lettere minuscole e maiuscole, numeri e caratteri non alfanumerici come !#%&/ per ridurre il rischio di accesso non autorizzato. La lunghezza minima dell'API_SECRET è di 12 caratteri.",
|
||||
"Weak API_SECRET detected. Please use a mix of small and CAPITAL letters, numbers and non-alphanumeric characters such as !#%&/ to reduce the risk of unauthorized access. The minimum length of the API_SECRET is 12 characters.": "Rilevata \"API secret\" debole. Si prega di utilizzare lettere minuscole e maiuscole, numeri e caratteri non alfanumerici come !#%&/ per ridurre il rischio di accesso non autorizzato. La lunghezza minima dell'API_SECRET è di 12 caratteri.",
|
||||
"less than 1": "meno di 1",
|
||||
"MongoDB password and API_SECRET match. This is a really bad idea. Please change both and do not reuse passwords across the system.": "La password di MongoDB e API_SECRET coincidono. Questa è una cattiva idea. Cambiale entrambe e non riutilizzare le password in tutto il sistema."
|
||||
"MongoDB password and API_SECRET match. This is a really bad idea. Please change both and do not reuse passwords across the system.": "La password di MongoDB e \"API secret\" coincidono. Questa è una cattiva idea. Cambiale entrambe e non riutilizzare le password in tutto il sistema."
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
"Pump Battery Age": "Idade Bateria da Bomba",
|
||||
"Pump Battery Low Alarm": "Alarme de Bateria Fraca da Bomba",
|
||||
"Pump Battery change overdue!": "Troca de Bateria da Bomba atrasada!",
|
||||
"When enabled an alarm may sound.": "Quando activado um alarme pode soar.",
|
||||
"When enabled an alarm may sound.": "Quando ativado um alarme pode soar.",
|
||||
"Urgent High Alarm": "Alarme Muito Alto",
|
||||
"High Alarm": "Alarme Hiper",
|
||||
"Low Alarm": "Alarme Hipo",
|
||||
|
||||
@@ -402,7 +402,7 @@
|
||||
"Loading profile switch data": "Загрузка данных нового профиля",
|
||||
"Redirecting you to the Profile Editor to create a new profile.": "Переход к редактору профиля для создания нового",
|
||||
"Pump": "Помпа",
|
||||
"Sensor Age": "Сенсору",
|
||||
"Sensor Age": "Сенсор проработал",
|
||||
"Insulin Age": "Инсулину",
|
||||
"Temporary target": "Временная цель",
|
||||
"Reason": "Основание",
|
||||
@@ -519,11 +519,11 @@
|
||||
"%1h ago": "%1 час назад",
|
||||
"%1d ago": "%1d назад",
|
||||
"RETRO": "ПРОШЛОЕ",
|
||||
"SAGE": "Сенсор работает",
|
||||
"SAGE": "СЕНСОРУ",
|
||||
"Sensor change/restart overdue!": "Рестарт сенсора пропущен",
|
||||
"Time to change/restart sensor": "Время замены/рестарта сенсора",
|
||||
"Change/restart sensor soon": "Приближается срок замены/рестарта сенсора",
|
||||
"Sensor age %1 days %2 hours": "Сенсору %1 дн %2 час",
|
||||
"Sensor age %1 days %2 hours": "Сенсор отработал %1 дн %2 час",
|
||||
"Sensor Insert": "Сенсор установлен",
|
||||
"Sensor Start": "Старт сенсора",
|
||||
"days": "дней",
|
||||
|
||||
@@ -557,8 +557,8 @@
|
||||
"virtAsstUnknown": "Bu değer şu anda bilinmiyor. Daha fazla ayrıntı için lütfen Nightscout sitenize bakın.",
|
||||
"virtAsstTitleAR2Forecast": "AR2 Tahmini",
|
||||
"virtAsstTitleCurrentBasal": "Geçerli Bazal",
|
||||
"virtAsstTitleCurrentCOB": "Geçerli AKRB",
|
||||
"virtAsstTitleCurrentIOB": "Geçerli AİNS",
|
||||
"virtAsstTitleCurrentCOB": "Mevcut AKRB",
|
||||
"virtAsstTitleCurrentIOB": "Mevcut AİNS",
|
||||
"virtAsstTitleLaunch": "Nightscout'a hoş geldiniz",
|
||||
"virtAsstTitleLoopForecast": "Döngü Tahmini",
|
||||
"virtAsstTitleLastLoop": "Son Döngü",
|
||||
|
||||
+12
-12
@@ -55,8 +55,8 @@
|
||||
"Percentile Chart": "百分位图形",
|
||||
"Distribution": "分布",
|
||||
"Hourly stats": "每小时状态",
|
||||
"netIOB stats": "netIOB stats",
|
||||
"temp basals must be rendered to display this report": "temp basals must be rendered to display this report",
|
||||
"netIOB stats": "IOB净值",
|
||||
"temp basals must be rendered to display this report": "要显示本报表必须先生成“日到日报表”",
|
||||
"No data available": "无可用数据",
|
||||
"Low": "低血糖",
|
||||
"In Range": "范围内",
|
||||
@@ -91,7 +91,7 @@
|
||||
"No API secret hash stored yet. You need to enter API secret.": "没有已存储的API密钥,请输入API密钥。",
|
||||
"Database loaded": "数据库已载入",
|
||||
"Error: Database failed to load": "错误:数据库载入失败",
|
||||
"Error": "Error",
|
||||
"Error": "出错了!",
|
||||
"Create new record": "新增记录",
|
||||
"Save record": "保存记录",
|
||||
"Portions": "部分",
|
||||
@@ -225,7 +225,7 @@
|
||||
"Pump Battery Change": "更换泵电池",
|
||||
"Pump Battery Age": "泵电池使用时间",
|
||||
"Pump Battery Low Alarm": "胰岛素泵电量低",
|
||||
"Pump Battery change overdue!": "Pump Battery change overdue!",
|
||||
"Pump Battery change overdue!": "泵电池更换超时!",
|
||||
"When enabled an alarm may sound.": "启用后可发出声音报警",
|
||||
"Urgent High Alarm": "血糖过高报警",
|
||||
"High Alarm": "高血糖报警",
|
||||
@@ -300,7 +300,7 @@
|
||||
"Record %1 removed ...": "%1条记录已清除",
|
||||
"Error removing record %1": "%1条记录清除出错",
|
||||
"Deleting records ...": "正在删除记录...",
|
||||
"%1 records deleted": "%1 records deleted",
|
||||
"%1 records deleted": "%1的记录已被删除",
|
||||
"Clean Mongo status database": "清除状态数据库",
|
||||
"Delete all documents from devicestatus collection": "从设备状态采集删除所有文档",
|
||||
"This task removes all documents from devicestatus collection. Useful when uploader battery status is not properly updated.": "此功能从设备状态采集中删除所有文档。适用于上传设备电量信息不能正常同步时使用。",
|
||||
@@ -309,15 +309,15 @@
|
||||
"Database contains %1 records": "数据库包含%1条记录",
|
||||
"All records removed ...": "所有记录已经被清除",
|
||||
"Delete all documents from devicestatus collection older than 30 days": "删除30天以前的设备数据",
|
||||
"Number of Days to Keep:": "Number of Days to Keep:",
|
||||
"This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.": "This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.",
|
||||
"Delete old documents from devicestatus collection?": "Delete old documents from devicestatus collection?",
|
||||
"Clean Mongo entries (glucose entries) database": "Clean Mongo entries (glucose entries) database",
|
||||
"Delete all documents from entries collection older than 180 days": "Delete all documents from entries collection older than 180 days",
|
||||
"This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.": "This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.",
|
||||
"Number of Days to Keep:": "保留天数:",
|
||||
"This task removes all documents from devicestatus collection that are older than 30 days. Useful when uploader battery status is not properly updated.": "此功能将删除所有30天以前的设备状态采集数据。适用于上传设备的电池状态不能正常更新的情况。",
|
||||
"Delete old documents from devicestatus collection?": "删除旧的设备状态数据?",
|
||||
"Clean Mongo entries (glucose entries) database": "清空Mongo数据库的葡萄糖条目数据库。",
|
||||
"Delete all documents from entries collection older than 180 days": "删除所有超过180天的条目数据",
|
||||
"This task removes all documents from entries collection that are older than 180 days. Useful when uploader battery status is not properly updated.": "此功能将删除所有180天以前的设备状态采集数据。适用于上传设备的电池状态不能正常更新的情况。",
|
||||
"Delete old documents": "删除历史数据",
|
||||
"Delete old documents from entries collection?": "从血糖数据集合内删除旧数据?",
|
||||
"%1 is not a valid number": "%1 is not a valid number",
|
||||
"%1 is not a valid number": "%1 不是有效的数字",
|
||||
"%1 is not a valid number - must be more than 2": "%1 is not a valid number - must be more than 2",
|
||||
"Clean Mongo treatments database": "Clean Mongo treatments database",
|
||||
"Delete all documents from treatments collection older than 180 days": "Delete all documents from treatments collection older than 180 days",
|
||||
|
||||
+583
-583
File diff suppressed because it is too large
Load Diff
@@ -92,6 +92,25 @@
|
||||
window.addEventListener('click', function() {
|
||||
showClose();
|
||||
});
|
||||
|
||||
// This fixes the issue of a "stale" CGM value displaying indefinately.
|
||||
// It displays "Internet offline." until internet is restored.
|
||||
function uOffline() {
|
||||
document.body.innerHTML =
|
||||
'Internet offline.'
|
||||
}
|
||||
// Return to normal as soon as internet connectivity is restored.
|
||||
function uOnline() {
|
||||
location.reload()
|
||||
}
|
||||
if(window.addEventListener) {
|
||||
window.addEventListener('offline', uOffline);
|
||||
window.addEventListener('online', uOnline);
|
||||
} else {
|
||||
document.body.attachEvent('onoffline', uOffline);
|
||||
document.body.attachEvent('ononline', uOnline);
|
||||
}
|
||||
|
||||
<% } %>
|
||||
</script>
|
||||
<%if (face == 'config') { %>
|
||||
|
||||
Reference in New Issue
Block a user