diff --git a/custom_components/choreops/dashboards/dashboard_registry.json b/custom_components/choreops/dashboards/dashboard_registry.json
index 748cfcc..3d6ad91 100644
--- a/custom_components/choreops/dashboards/dashboard_registry.json
+++ b/custom_components/choreops/dashboards/dashboard_registry.json
@@ -1,6 +1,6 @@
{
"schema_version": 1,
- "release_version": "1.1.0",
+ "release_version": "1.1.1",
"repo": "ccpk1/ChoreOps-Dashboards",
"title": "ChoreOps Dashboard Registry",
"description": "Registry manifest for ChoreOps dashboard templates",
diff --git a/custom_components/choreops/dashboards/templates/shared/button_card_template_chore_row_v1.yaml b/custom_components/choreops/dashboards/templates/shared/button_card_template_chore_row_v1.yaml
index 913326d..a457f5d 100644
--- a/custom_components/choreops/dashboards/templates/shared/button_card_template_chore_row_v1.yaml
+++ b/custom_components/choreops/dashboards/templates/shared/button_card_template_chore_row_v1.yaml
@@ -146,7 +146,7 @@ chore_row_v1:
},
"custom_fields":
{
- "due": '[[[ const getLabels = () => { const directLabels = (typeof variables !== ''undefined'' && variables && typeof variables.ui_labels === ''object'') ? variables.ui_labels : null; if (directLabels) return directLabels; const sensorId = (typeof variables !== ''undefined'' && variables && typeof variables.translation_sensor_eid === ''string'') ? variables.translation_sensor_eid.trim() : ''''; const sensorState = sensorId && typeof hass !== ''undefined'' && hass && hass.states ? hass.states[sensorId] : null; const sensorLabels = sensorState && sensorState.attributes && typeof sensorState.attributes.ui_translations === ''object'' ? sensorState.attributes.ui_translations : null; return sensorLabels; }; const i18n = (key, fallback) => { const labels = getLabels(); const value = labels && typeof labels[key] === ''string'' ? labels[key].trim() : ''''; return value.length > 0 ? value : ((typeof fallback === ''string'' && fallback.startsWith(''err-'')) ? fallback : `err-${key}`); }; const statusMap = { pending: i18n(''pending'', ''err-pending''), due: i18n(''due'', ''err-due''), claimed: i18n(''claimed'', ''err-claimed''), claimed_in_part: i18n(''claimed_in_part'', ''err-claimed_in_part''), completed: i18n(''completed'', ''err-completed''), completed_in_part: i18n(''completed_in_part'', ''err-completed_in_part''), overdue: i18n(''overdue'', ''err-overdue''), waiting: i18n(''waiting'', ''err-waiting''), missed: i18n(''missed'', ''err-missed''), completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), paused: i18n(''paused'', ''err-paused''), blocked_paused: i18n(''paused'', ''err-paused''), already_approved: i18n(''completed'', ''err-completed''), pending_claim: i18n(''claimed'', ''err-claimed''), missed_locked: i18n(''missed_locked'', ''err-missed_locked''), blocked_completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), blocked_already_approved: i18n(''completed'', ''err-completed''), blocked_pending_claim: i18n(''claimed'', ''err-claimed''), blocked_waiting_window: i18n(''waiting'', ''err-waiting''), blocked_not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), blocked_missed_locked: i18n(''missed_locked'', ''err-missed_locked''), steal_available: i18n(''steal_available'', ''err-steal_available''), standby: i18n(''standby'', ''err-standby''), blocked_standby: i18n(''standby'', ''err-standby''), standby_available: i18n(''standby'', ''err-standby'') }; const rawState = entity.state; let status = (rawState === ''approved'' || rawState === ''already_approved'') ? ''completed'' : (rawState === ''approved_in_part'' ? ''completed_in_part'' : rawState); const claimMode = entity.attributes.claim_mode || null; if (claimMode === ''steal_available'') status = ''steal_available''; else if (entity.attributes.can_claim === false && claimMode && ![''completed'', ''completed_in_part'', ''overdue''].includes(status)) status = claimMode; const formatDateWithOrdinal = (value) => { if (!value) return ''--''; const dt = new Date(value); if (Number.isNaN(dt.getTime())) return ''--''; const day = dt.getDate(); const mod10 = day % 10; const mod100 = day % 100; let suffix = ''th''; if (mod10 === 1 && mod100 !== 11) suffix = ''st''; else if (mod10 === 2 && mod100 !== 12) suffix = ''nd''; else if (mod10 === 3 && mod100 !== 13) suffix = ''rd''; const month = dt.toLocaleString(undefined, { month: ''short'' }); const time = dt.toLocaleString(undefined, { hour: ''numeric'', minute: ''2-digit'' }); return `${month} ${day}${suffix}, ${time}`; }; const normalizeText = (value) => { if (typeof value !== ''string'') return ''''; const text = value.trim(); return text.length > 0 ? text : ''''; }; const formatFreqText = (value) => value.split('' '').filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('' ''); const value = entity.attributes.due_date || entity.attributes.due_window_start; const dateText = formatDateWithOrdinal(value); const statusLabel = statusMap[status] || status; const dueLabel = i18n(''date'', ''err-date''); const freqRaw = normalizeText(entity.attributes.recurring_frequency) || normalizeText(entity.attributes.frequency) || normalizeText(entity.attributes.recurrence) || normalizeText(entity.attributes.recurrence_text); const freqKey = freqRaw.toLowerCase().replace(/ /g, ''_''); const freqLocalizedMap = { daily: i18n(''daily'', ''err-daily''), daily_multi: i18n(''daily_multi'', ''err-daily_multi''), weekly: i18n(''weekly'', ''err-weekly''), biweekly: i18n(''biweekly'', ''err-biweekly''), monthly: i18n(''monthly'', ''err-monthly''), quarterly: i18n(''quarterly'', ''err-quarterly''), yearly: i18n(''yearly'', ''err-yearly''), custom: i18n(''custom'', ''err-custom''), custom_from_complete: i18n(''custom_from_complete'', ''err-custom_from_complete''), custom_from_complete_date_only: i18n(''custom_from_complete_date_only'', ''err-custom_from_complete_date_only''), custom_1_week: i18n(''custom_1_week'', ''err-custom_1_week''), custom_1_month: i18n(''custom_1_month'', ''err-custom_1_month''), custom_1_quarter: i18n(''custom_1_quarter'', ''err-custom_1_quarter''), custom_1_year: i18n(''custom_1_year'', ''err-custom_1_year'') }; const isKnownNone = [''none'', ''unknown'', ''unavailable'', ''null''].includes(freqKey); const hasFreq = freqKey.length > 0 && !isKnownNone; const freqText = freqLocalizedMap[freqKey] || formatFreqText(freqRaw.toLowerCase().replace(/_/g, '' '')); const rText = hasFreq ? ` • ${freqText}` : ''''; return `${String(statusLabel).toUpperCase()} • ${dueLabel}: ${dateText}${rText}`; ]]]',
+ "due": '[[[ const getLabels = () => { const directLabels = (typeof variables !== ''undefined'' && variables && typeof variables.ui_labels === ''object'') ? variables.ui_labels : null; if (directLabels) return directLabels; const sensorId = (typeof variables !== ''undefined'' && variables && typeof variables.translation_sensor_eid === ''string'') ? variables.translation_sensor_eid.trim() : ''''; const sensorState = sensorId && typeof hass !== ''undefined'' && hass && hass.states ? hass.states[sensorId] : null; const sensorLabels = sensorState && sensorState.attributes && typeof sensorState.attributes.ui_translations === ''object'' ? sensorState.attributes.ui_translations : null; return sensorLabels; }; const i18n = (key, fallback) => { const labels = getLabels(); const value = labels && typeof labels[key] === ''string'' ? labels[key].trim() : ''''; return value.length > 0 ? value : ((typeof fallback === ''string'' && fallback.startsWith(''err-'')) ? fallback : `err-${key}`); }; const statusMap = { pending: i18n(''pending'', ''err-pending''), due: i18n(''due'', ''err-due''), claimed: i18n(''claimed'', ''err-claimed''), claimed_in_part: i18n(''claimed_in_part'', ''err-claimed_in_part''), completed: i18n(''completed'', ''err-completed''), completed_in_part: i18n(''completed_in_part'', ''err-completed_in_part''), overdue: i18n(''overdue'', ''err-overdue''), waiting: i18n(''waiting'', ''err-waiting''), missed: i18n(''missed'', ''err-missed''), completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), paused: i18n(''paused'', ''err-paused''), blocked_paused: i18n(''paused'', ''err-paused''), already_approved: i18n(''completed'', ''err-completed''), pending_claim: i18n(''claimed'', ''err-claimed''), missed_locked: i18n(''missed_locked'', ''err-missed_locked''), blocked_completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), blocked_already_approved: i18n(''completed'', ''err-completed''), blocked_pending_claim: i18n(''claimed'', ''err-claimed''), blocked_waiting_window: i18n(''waiting'', ''err-waiting''), blocked_not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), blocked_missed_locked: i18n(''missed_locked'', ''err-missed_locked''), steal_available: i18n(''steal_available'', ''err-steal_available''), standby: i18n(''standby'', ''err-standby''), blocked_standby: i18n(''standby'', ''err-standby''), standby_available: i18n(''standby'', ''err-standby'') }; const rawState = entity.state; let status = (rawState === ''approved'' || rawState === ''already_approved'') ? ''completed'' : (rawState === ''approved_in_part'' ? ''completed_in_part'' : rawState); const claimMode = entity.attributes.claim_mode || null; if (claimMode === ''steal_available'') status = ''steal_available''; else if (entity.attributes.can_claim === false && claimMode && ![''completed'', ''completed_in_part'', ''overdue''].includes(status)) status = claimMode; const formatDateWithOrdinal = (value) => { if (!value) return ''--''; const dt = new Date(value); if (Number.isNaN(dt.getTime())) return ''--''; const day = dt.getDate(); const mod10 = day % 10; const mod100 = day % 100; let suffix = ''th''; if (mod10 === 1 && mod100 !== 11) suffix = ''st''; else if (mod10 === 2 && mod100 !== 12) suffix = ''nd''; else if (mod10 === 3 && mod100 !== 13) suffix = ''rd''; const month = dt.toLocaleString(undefined, { month: ''short'' }); const time = dt.toLocaleString(undefined, { hour: ''numeric'', minute: ''2-digit'' }); return `${month} ${day}${suffix}, ${time}`; }; const normalizeText = (value) => { if (typeof value !== ''string'') return ''''; const text = value.trim(); return text.length > 0 ? text : ''''; }; const formatFreqText = (value) => value.split('' '').filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('' ''); const value = entity.attributes.due_date || entity.attributes.due_window_start; const dateText = formatDateWithOrdinal(value); const statusLabel = statusMap[status] || status; const dueLabel = i18n(''date'', ''err-date''); const freqRaw = normalizeText(entity.attributes.recurring_frequency) || normalizeText(entity.attributes.frequency) || normalizeText(entity.attributes.recurrence) || normalizeText(entity.attributes.recurrence_text); const freqKey = freqRaw.toLowerCase().replace(/ /g, ''_''); const freqLocalizedMap = { daily: i18n(''daily'', ''err-daily''), daily_multi: i18n(''daily_multi'', ''err-daily_multi''), weekly: i18n(''weekly'', ''err-weekly''), biweekly: i18n(''biweekly'', ''err-biweekly''), monthly: i18n(''monthly'', ''err-monthly''), quarterly: i18n(''quarterly'', ''err-quarterly''), yearly: i18n(''yearly'', ''err-yearly''), custom: i18n(''custom'', ''err-custom''), custom_from_complete: i18n(''custom_from_complete'', ''err-custom_from_complete''), custom_from_complete_date_only: i18n(''custom_from_complete_date_only'', ''err-custom_from_complete_date_only''), custom_1_week: i18n(''custom_1_week'', ''err-custom_1_week''), custom_1_month: i18n(''custom_1_month'', ''err-custom_1_month''), custom_1_quarter: i18n(''custom_1_quarter'', ''err-custom_1_quarter''), custom_1_year: i18n(''custom_1_year'', ''err-custom_1_year'') }; const isKnownNone = [''none'', ''unknown'', ''unavailable'', ''null''].includes(freqKey); const hasFreq = freqKey.length > 0 && !isKnownNone; const ci = entity.attributes.custom_frequency_interval; const cu = entity.attributes.custom_frequency_unit; const freqText = (ci && cu) ? `${i18n(''every'', ''err-every'')} ${ci} ${cu}` : (freqLocalizedMap[freqKey] || formatFreqText(freqRaw.toLowerCase().replace(/_/g, '' ''))); const rText = hasFreq ? ` • ${freqText}` : ''''; return `${String(statusLabel).toUpperCase()} • ${dueLabel}: ${dateText}${rText}`; ]]]',
"description": "[[[ const prefEnabled = (typeof variables !== 'undefined' && variables && variables.pref_show_chore_description === false) ? false : true; const value = typeof entity.attributes.description === 'string' ? entity.attributes.description.trim() : ''; if (!prefEnabled || value.length === 0) return ''; const escaped = value.replace(/&/g, '&').replace(//g, '>'); return `${escaped}`; ]]]",
"history": '[[[ const getLabels = () => { const directLabels = (typeof variables !== ''undefined'' && variables && typeof variables.ui_labels === ''object'') ? variables.ui_labels : null; if (directLabels) return directLabels; const sensorId = (typeof variables !== ''undefined'' && variables && typeof variables.translation_sensor_eid === ''string'') ? variables.translation_sensor_eid.trim() : ''''; const sensorState = sensorId && typeof hass !== ''undefined'' && hass && hass.states ? hass.states[sensorId] : null; const sensorLabels = sensorState && sensorState.attributes && typeof sensorState.attributes.ui_translations === ''object'' ? sensorState.attributes.ui_translations : null; return sensorLabels; }; const i18n = (key, fallback) => { const labels = getLabels(); const value = labels && typeof labels[key] === ''string'' ? labels[key].trim() : ''''; return value.length > 0 ? value : ((typeof fallback === ''string'' && fallback.startsWith(''err-'')) ? fallback : `err-${key}`); }; const map = { completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), already_approved: i18n(''completed'', ''err-completed''), pending_claim: i18n(''claimed'', ''err-claimed''), waiting: i18n(''waiting'', ''err-waiting''), missed_locked: i18n(''missed'', ''err-missed''), blocked_completed_by_other: i18n(''completed_by_other'', ''err-completed_by_other''), blocked_already_approved: i18n(''completed'', ''err-completed''), blocked_pending_claim: i18n(''claimed'', ''err-claimed''), blocked_waiting_window: i18n(''waiting'', ''err-waiting''), blocked_not_my_turn: i18n(''not_my_turn'', ''err-not_my_turn''), blocked_paused: i18n(''paused'', ''err-paused''), blocked_missed_locked: i18n(''missed'', ''err-missed''), blocked_standby: i18n(''standby'', ''err-standby''), standby: i18n(''standby'', ''err-standby'') }; const toNameList = (raw) => { if (Array.isArray(raw)) { return [...new Set(raw.map((item) => String(item == null ? '''' : item)).map((item) => item.trim()).filter(Boolean))]; } return []; }; const formatPoints = (rawValue) => { const numericValue = Number(rawValue); if (!Number.isFinite(numericValue)) return null; const roundedValue = Math.round(numericValue * 100) / 100; const precision = (typeof variables !== ''undefined'' && variables && typeof variables.pref_points_precision === ''string'') ? variables.pref_points_precision.trim().toLowerCase() : ''fixed_0''; if (precision === ''adaptive'') { if (Math.abs(roundedValue - Math.round(roundedValue)) < 0.001) return String(Math.round(roundedValue)); if (Math.abs(roundedValue - Math.round(roundedValue * 10) / 10) < 0.001) return roundedValue.toFixed(1); return roundedValue.toFixed(2); } if (precision === ''fixed_1'') return roundedValue.toFixed(1); if (precision === ''fixed_2'') return roundedValue.toFixed(2); return String(Math.round(roundedValue)); }; const rawState = entity.state; const state = rawState === ''approved_in_part'' ? ''completed_in_part'' : rawState; const rawGlobalState = entity.attributes.global_state; const globalState = typeof rawGlobalState === ''string'' ? rawGlobalState : state; const claimMode = entity.attributes.claim_mode || null; const claimAccent = (typeof variables !== ''undefined'' && variables && typeof variables.pref_claim_accent === ''string'' && variables.pref_claim_accent.trim().length > 0) ? variables.pref_claim_accent.trim() : ''#a957fa''; const overdueAccent = (typeof variables !== ''undefined'' && variables && typeof variables.pref_overdue_accent === ''string'' && variables.pref_overdue_accent.trim().length > 0) ? variables.pref_overdue_accent.trim() : ''#ff4444''; const stealAccent = (typeof variables !== ''undefined'' && variables && typeof variables.pref_steal_accent === ''string'' && variables.pref_steal_accent.trim().length > 0) ? variables.pref_steal_accent.trim() : ''#F2C94C''; const type = entity.attributes.completion_criteria || ''''; const assigned = toNameList(entity.attributes.assigned_user_names); const completed = toNameList(entity.attributes.completed_by); const claimedRaw = entity.attributes.claimed_by; const claimed = Array.isArray(claimedRaw) ? [...new Set(claimedRaw.map((item) => String(item == null ? '''' : item)).map((item) => item.trim()).filter(Boolean))] : (claimedRaw ? [String(claimedRaw).trim()].filter(Boolean) : []); const progressedBy = [...new Set([...claimed, ...completed])]; const progressedByAssigned = assigned.filter((name) => progressedBy.includes(name)); const missingByAssigned = assigned.filter((name) => !progressedBy.includes(name)); const isRotationType = type.includes(''rotation''); const isSharedAll = type === ''shared_all''; const isSingleCompletion = type === ''shared_first'' || isRotationType; const isSharedType = isSharedAll || isSingleCompletion; const isGlobalFullyCompleted = [''completed'', ''already_approved'', ''completed_by_other''].includes(globalState); const missedLabel = i18n(''missed'', ''err-missed''), overdueLabel = i18n(''overdue'', ''err-overdue''); const stealLabel = i18n(''steal_window_open'', ''err-steal_window_open''); const currentTurnLabel = i18n(''current_turn'', ''err-current_turn''); const currentlyLabel = i18n(''currently'', ''err-currently''); const availableInLabel = i18n(''available_in'', ''err-available_in''); const overdueInLabel = i18n(''overdue_in'', ''err-overdue_in''); const progressLabel = i18n(''progress'', ''err-progress''); const completedLabel = i18n(''completed'', ''err-completed''); const byLabel = i18n(''by'', ''err-by''); const lastLabel = i18n(''last'', ''err-last''); let context = ''''; if (claimMode === ''steal_available'') { const turnName = entity.attributes.turn_user_name; context = turnName ? `${stealLabel} • ${currentTurnLabel}: ${turnName}` : `${stealLabel}`; } else if (isSharedType && (globalState === ''overdue'' || globalState === ''missed'')) { if (isRotationType) { const turnName = entity.attributes.turn_user_name; context = turnName ? `${overdueLabel}: ${turnName}` : `${overdueLabel}`; } else { context = missingByAssigned.length > 0 ? `${overdueLabel}: ${missingByAssigned.join('', '')}` : `${overdueLabel}`; } } else if (state === ''not_my_turn'' && entity.attributes.turn_user_name) { context = `${currentlyLabel}: ${entity.attributes.turn_user_name}`; } else if (isSharedAll) { const totalCount = assigned.length > 0 ? assigned.length : 1; const progressCount = progressedByAssigned.length; const hasProgressSignal = progressCount > 0 || [''claimed'', ''claimed_in_part'', ''approved_in_part'', ''completed'', ''completed_in_part'', ''already_approved'', ''completed_by_other''].includes(globalState); if (hasProgressSignal) { const label = isGlobalFullyCompleted ? completedLabel : progressLabel; if (progressedByAssigned.length > 0) { context = isGlobalFullyCompleted ? `${label}: ${progressCount}/${totalCount} • ${progressedByAssigned.join('', '')}` : `${label}: ${progressCount}/${totalCount} • ${byLabel} ${progressedByAssigned.join('', '')}`; } else { context = `${label}: ${progressCount}/${totalCount}`; } } } else if (isSingleCompletion) { const actorName = progressedByAssigned[0] || progressedBy[0] || ''''; if (actorName) { context = `${completedLabel}: ${actorName}`; } } else if (state === ''waiting'') { const waitText = (() => { const targetValue = entity.attributes.due_window_start || entity.attributes.due_date; if (!targetValue) return ''--''; const targetDate = new Date(targetValue); if (Number.isNaN(targetDate.getTime())) return ''--''; const minutesRemaining = Math.floor((targetDate.getTime() - Date.now()) / 60000); if (minutesRemaining <= 0) return ''0d 0h 0m''; const days = Math.floor(minutesRemaining / 1440); const hours = Math.floor((minutesRemaining % 1440) / 60); const minutes = minutesRemaining % 60; const parts = []; if (days > 0) parts.push(`${days}d`); if (hours > 0) parts.push(`${hours}h`); if (minutes > 0) parts.push(`${minutes}m`); return parts.length > 0 ? parts.join('' '') : ''0d 0h 0m''; })(); context = `${availableInLabel}: ${waitText}`; } else if (state === ''due'') { const overdueInText = (() => { const targetValue = entity.attributes.due_date; if (!targetValue) return ''--''; const targetDate = new Date(targetValue); if (Number.isNaN(targetDate.getTime())) return ''--''; const minutesRemaining = Math.floor((targetDate.getTime() - Date.now()) / 60000); if (minutesRemaining <= 0) return ''0d 0h 0m''; const days = Math.floor(minutesRemaining / 1440); const hours = Math.floor((minutesRemaining % 1440) / 60); const minutes = minutesRemaining % 60; const parts = []; if (days > 0) parts.push(`${days}d`); if (hours > 0) parts.push(`${hours}h`); if (minutes > 0) parts.push(`${minutes}m`); return parts.length > 0 ? parts.join('' '') : ''0d 0h 0m''; })(); context = `${overdueInLabel}: ${overdueInText}`; } else if (entity.attributes.can_claim === false && claimMode) { if (!isSharedType && [''missed_locked'', ''blocked_missed_locked''].includes(claimMode)) { context = ''''; } else { context = map[claimMode] || claimMode; } } const parts = []; if (context) parts.push(context); const rawLastCompleted = entity.attributes.last_completed; const lastCompletedText = typeof rawLastCompleted === ''string'' ? rawLastCompleted.trim().toLowerCase() : ''''; const hasLastCompleted = !!rawLastCompleted && !['''', ''never'', ''unknown'', ''unavailable'', ''none'', ''null''].includes(lastCompletedText); if (hasLastCompleted) { const lastDate = new Date(rawLastCompleted); if (!Number.isNaN(lastDate.getTime())) { const lastText = lastDate.toLocaleDateString(undefined, {month:''short'', day:''numeric''}); parts.push(`${lastLabel}: ${lastText}`); } } const gamificationEnabled = typeof variables !== ''undefined'' && variables && variables.gamification_enabled === true; const formattedPoints = formatPoints(entity.attributes.default_points); const pointsLabel = (typeof variables !== ''undefined'' && variables && typeof variables.points_label === ''string'' && variables.points_label.trim().length > 0) ? variables.points_label.trim() : ''Points''; if (gamificationEnabled && formattedPoints !== null) { parts.push(`${pointsLabel}: ${formattedPoints}`); } return parts.join('' • ''); ]]]',
"points": "[[[ return ''; ]]]",
diff --git a/custom_components/choreops/dashboards/translations/ca_dashboard.json b/custom_components/choreops/dashboards/translations/ca_dashboard.json
index 073c791..7323cf3 100644
--- a/custom_components/choreops/dashboards/translations/ca_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/ca_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Recompte guanyat",
"enable_label_grouping": "Habilita els grups d'etiquetes",
"end_date": "Data de finalització",
+ "every": "Cada",
"false": "Fals",
"fri_short": "divendres",
"future_goal": "Objectiu futur",
diff --git a/custom_components/choreops/dashboards/translations/da_dashboard.json b/custom_components/choreops/dashboards/translations/da_dashboard.json
index a715e68..41f409e 100644
--- a/custom_components/choreops/dashboards/translations/da_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/da_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Optjent antal",
"enable_label_grouping": "Aktivér etiketgrupper",
"end_date": "Slutdato",
+ "every": "Hver",
"false": "falsk",
"fri_short": "Fre",
"future_goal": "Fremtidigt mål",
diff --git a/custom_components/choreops/dashboards/translations/de_dashboard.json b/custom_components/choreops/dashboards/translations/de_dashboard.json
index 107b9c0..ccc302e 100644
--- a/custom_components/choreops/dashboards/translations/de_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/de_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Verdiente Anzahl",
"enable_label_grouping": "Labelgruppen aktivieren",
"end_date": "Enddatum",
+ "every": "Jeder",
"false": "Falsch",
"fri_short": "Fr",
"future_goal": "Zukünftiges Ziel",
diff --git a/custom_components/choreops/dashboards/translations/en_dashboard.json b/custom_components/choreops/dashboards/translations/en_dashboard.json
index ab0d77a..ef81c2e 100644
--- a/custom_components/choreops/dashboards/translations/en_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/en_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Earned Count",
"enable_label_grouping": "Enable Label Groups",
"end_date": "End Date",
+ "every": "Every",
"false": "False",
"fri_short": "Fri",
"future_goal": "Future Goal",
diff --git a/custom_components/choreops/dashboards/translations/es_dashboard.json b/custom_components/choreops/dashboards/translations/es_dashboard.json
index 5ce611e..9e0f5a0 100644
--- a/custom_components/choreops/dashboards/translations/es_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/es_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Conteo ganado",
"enable_label_grouping": "Habilitar grupos de etiquetas",
"end_date": "Fecha de Finalización",
+ "every": "Cada",
"false": "FALSO",
"fri_short": "Vie",
"future_goal": "Meta futura",
diff --git a/custom_components/choreops/dashboards/translations/fi_dashboard.json b/custom_components/choreops/dashboards/translations/fi_dashboard.json
index 3a06c69..c9354b3 100644
--- a/custom_components/choreops/dashboards/translations/fi_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/fi_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Ansaittu määrä",
"enable_label_grouping": "Ota käyttöön tunnisteryhmät",
"end_date": "Päättymispäivä",
+ "every": "Joka",
"false": "Väärä",
"fri_short": "pe",
"future_goal": "Tulevaisuuden tavoite",
diff --git a/custom_components/choreops/dashboards/translations/fr_dashboard.json b/custom_components/choreops/dashboards/translations/fr_dashboard.json
index 6a04b44..e1b29ec 100644
--- a/custom_components/choreops/dashboards/translations/fr_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/fr_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Total gagné",
"enable_label_grouping": "Afficher les groupes d'étiquettes",
"end_date": "Date de fin",
+ "every": "Chaque",
"false": "Faux",
"fri_short": "Ven",
"future_goal": "Objectif futur",
diff --git a/custom_components/choreops/dashboards/translations/it_dashboard.json b/custom_components/choreops/dashboards/translations/it_dashboard.json
index 35a1204..87e0d97 100644
--- a/custom_components/choreops/dashboards/translations/it_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/it_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Conteggio guadagnato",
"enable_label_grouping": "Abilita gruppi di etichette",
"end_date": "Data di fine",
+ "every": "Ogni",
"false": "Falso",
"fri_short": "Ven",
"future_goal": "Obiettivo futuro",
diff --git a/custom_components/choreops/dashboards/translations/nb_dashboard.json b/custom_components/choreops/dashboards/translations/nb_dashboard.json
index 7e002ce..5661ce6 100644
--- a/custom_components/choreops/dashboards/translations/nb_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/nb_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Opptjent antall",
"enable_label_grouping": "Aktiver etikettgrupper",
"end_date": "Sluttdato",
+ "every": "Hver eneste",
"false": "falsk",
"fri_short": "Fre",
"future_goal": "Fremtidig mål",
diff --git a/custom_components/choreops/dashboards/translations/nl_dashboard.json b/custom_components/choreops/dashboards/translations/nl_dashboard.json
index e8ee53a..2246eb3 100644
--- a/custom_components/choreops/dashboards/translations/nl_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/nl_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Verdiende telling",
"enable_label_grouping": "Labelgroepen inschakelen",
"end_date": "Einddatum",
+ "every": "Elk",
"false": "Onwaar",
"fri_short": "vr",
"future_goal": "Toekomstdoel",
diff --git a/custom_components/choreops/dashboards/translations/pl_dashboard.json b/custom_components/choreops/dashboards/translations/pl_dashboard.json
index 72ea787..3d9d8b4 100644
--- a/custom_components/choreops/dashboards/translations/pl_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/pl_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Zdobyta liczba",
"enable_label_grouping": "Włącz grupy etykiet",
"end_date": "Data zakończenia",
+ "every": "Każdy",
"false": "Fałsz",
"fri_short": "Pt",
"future_goal": "Przyszły cel",
diff --git a/custom_components/choreops/dashboards/translations/pt_dashboard.json b/custom_components/choreops/dashboards/translations/pt_dashboard.json
index 27d6c86..a21f697 100644
--- a/custom_components/choreops/dashboards/translations/pt_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/pt_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Contagem de ganhos",
"enable_label_grouping": "Ativar grupos de rótulos",
"end_date": "Data de término",
+ "every": "Cada",
"false": "FALSO",
"fri_short": "sex",
"future_goal": "Meta futura",
diff --git a/custom_components/choreops/dashboards/translations/ro_dashboard.json b/custom_components/choreops/dashboards/translations/ro_dashboard.json
index 534a7e9..eb7f099 100644
--- a/custom_components/choreops/dashboards/translations/ro_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/ro_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Număr câștigat",
"enable_label_grouping": "Activați grupurile de etichete",
"end_date": "Data de încheiere",
+ "every": "Fiecare",
"false": "Fals",
"fri_short": "Vin",
"future_goal": "Scopul viitor",
diff --git a/custom_components/choreops/dashboards/translations/ru_dashboard.json b/custom_components/choreops/dashboards/translations/ru_dashboard.json
index f852810..6f89593 100644
--- a/custom_components/choreops/dashboards/translations/ru_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/ru_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Количество заработанных",
"enable_label_grouping": "Включить группы меток",
"end_date": "Дата окончания",
+ "every": "Каждый",
"false": "ЛОЖЬ",
"fri_short": "Пятница",
"future_goal": "Будущая цель",
diff --git a/custom_components/choreops/dashboards/translations/sk_dashboard.json b/custom_components/choreops/dashboards/translations/sk_dashboard.json
index 703b2c3..2369118 100644
--- a/custom_components/choreops/dashboards/translations/sk_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/sk_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Počet získaných",
"enable_label_grouping": "Povoliť skupiny štítkov",
"end_date": "Dátum ukončenia",
+ "every": "Každý",
"false": "Falošné",
"fri_short": "Pia",
"future_goal": "Budúci cieľ",
diff --git a/custom_components/choreops/dashboards/translations/sl_dashboard.json b/custom_components/choreops/dashboards/translations/sl_dashboard.json
index f35dd78..8b96f4e 100644
--- a/custom_components/choreops/dashboards/translations/sl_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/sl_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Število zasluženih",
"enable_label_grouping": "Omogoči skupine oznak",
"end_date": "Končni datum",
+ "every": "Vsak",
"false": "Napačno",
"fri_short": "pet",
"future_goal": "Prihodnji cilj",
diff --git a/custom_components/choreops/dashboards/translations/sv_dashboard.json b/custom_components/choreops/dashboards/translations/sv_dashboard.json
index 55263e0..3e8955b 100644
--- a/custom_components/choreops/dashboards/translations/sv_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/sv_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Intjänat antal",
"enable_label_grouping": "Aktivera etikettgrupper",
"end_date": "Slutdatum",
+ "every": "Varje",
"false": "Falsk",
"fri_short": "fre",
"future_goal": "Framtida mål",
diff --git a/custom_components/choreops/dashboards/translations/uk_dashboard.json b/custom_components/choreops/dashboards/translations/uk_dashboard.json
index 4e439d7..3472e92 100644
--- a/custom_components/choreops/dashboards/translations/uk_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/uk_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "Зароблена кількість",
"enable_label_grouping": "Увімкнути групи міток",
"end_date": "Дата завершення",
+ "every": "Кожен",
"false": "Хибно",
"fri_short": "Пт",
"future_goal": "Майбутня мета",
diff --git a/custom_components/choreops/dashboards/translations/zh_dashboard.json b/custom_components/choreops/dashboards/translations/zh_dashboard.json
index 98faa5c..32b348f 100644
--- a/custom_components/choreops/dashboards/translations/zh_dashboard.json
+++ b/custom_components/choreops/dashboards/translations/zh_dashboard.json
@@ -103,6 +103,7 @@
"earned_count": "获得计数",
"enable_label_grouping": "启用标签组",
"end_date": "结束日期",
+ "every": "每一个",
"false": "错误的",
"fri_short": "星期五",
"future_goal": "未来目标",
diff --git a/custom_components/choreops/manifest.json b/custom_components/choreops/manifest.json
index 8410c0d..935ea0b 100644
--- a/custom_components/choreops/manifest.json
+++ b/custom_components/choreops/manifest.json
@@ -10,5 +10,5 @@
"issue_tracker": "https://github.com/ccpk1/choreops/issues",
"quality_scale": "platinum",
"requirements": ["python-dateutil>=2.9.0"],
- "version": "1.5.1-beta.1"
+ "version": "1.5.1-beta.2"
}