iobroker.time-tracker 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +386 -0
- package/admin/i18n/de.json +34 -0
- package/admin/i18n/en.json +1 -0
- package/admin/i18n/es.json +34 -0
- package/admin/i18n/fr.json +34 -0
- package/admin/i18n/it.json +34 -0
- package/admin/i18n/nl.json +34 -0
- package/admin/i18n/pl.json +34 -0
- package/admin/i18n/pt.json +34 -0
- package/admin/i18n/ru.json +34 -0
- package/admin/i18n/uk.json +34 -0
- package/admin/i18n/zh-cn.json +34 -0
- package/admin/jsonConfig.json +266 -0
- package/admin/time-tracker.png +0 -0
- package/build/lib/adapter/automation.js +100 -0
- package/build/lib/adapter/automation.js.map +7 -0
- package/build/lib/adapter/commands.js +160 -0
- package/build/lib/adapter/commands.js.map +7 -0
- package/build/lib/adapter/messages.js +207 -0
- package/build/lib/adapter/messages.js.map +7 -0
- package/build/lib/adapter/presence.js +129 -0
- package/build/lib/adapter/presence.js.map +7 -0
- package/build/lib/adapter/states.js +330 -0
- package/build/lib/adapter/states.js.map +7 -0
- package/build/lib/adapter/triggers.js +92 -0
- package/build/lib/adapter/triggers.js.map +7 -0
- package/build/lib/db/database.js +96 -0
- package/build/lib/db/database.js.map +7 -0
- package/build/lib/db/migrations.js +603 -0
- package/build/lib/db/migrations.js.map +7 -0
- package/build/lib/db/repositories/absences.js +432 -0
- package/build/lib/db/repositories/absences.js.map +7 -0
- package/build/lib/db/repositories/audit.js +90 -0
- package/build/lib/db/repositories/audit.js.map +7 -0
- package/build/lib/db/repositories/automations.js +326 -0
- package/build/lib/db/repositories/automations.js.map +7 -0
- package/build/lib/db/repositories/entries.js +335 -0
- package/build/lib/db/repositories/entries.js.map +7 -0
- package/build/lib/db/repositories/holidays.js +156 -0
- package/build/lib/db/repositories/holidays.js.map +7 -0
- package/build/lib/db/repositories/payouts.js +221 -0
- package/build/lib/db/repositories/payouts.js.map +7 -0
- package/build/lib/db/repositories/rfid.js +264 -0
- package/build/lib/db/repositories/rfid.js.map +7 -0
- package/build/lib/db/repositories/rules.js +356 -0
- package/build/lib/db/repositories/rules.js.map +7 -0
- package/build/lib/db/repositories/settings.js +91 -0
- package/build/lib/db/repositories/settings.js.map +7 -0
- package/build/lib/db/repositories/terminals.js +243 -0
- package/build/lib/db/repositories/terminals.js.map +7 -0
- package/build/lib/db/repositories/triggers.js +240 -0
- package/build/lib/db/repositories/triggers.js.map +7 -0
- package/build/lib/db/repositories/users.js +491 -0
- package/build/lib/db/repositories/users.js.map +7 -0
- package/build/lib/db/seed.js +180 -0
- package/build/lib/db/seed.js.map +7 -0
- package/build/lib/domain/avatar.js +63 -0
- package/build/lib/domain/avatar.js.map +7 -0
- package/build/lib/domain/breaks.js +70 -0
- package/build/lib/domain/breaks.js.map +7 -0
- package/build/lib/domain/calculation.js +150 -0
- package/build/lib/domain/calculation.js.map +7 -0
- package/build/lib/domain/holidays.js +113 -0
- package/build/lib/domain/holidays.js.map +7 -0
- package/build/lib/domain/punch.js +99 -0
- package/build/lib/domain/punch.js.map +7 -0
- package/build/lib/domain/target.js +89 -0
- package/build/lib/domain/target.js.map +7 -0
- package/build/lib/errors.js +56 -0
- package/build/lib/errors.js.map +7 -0
- package/build/lib/reports/labels.js +358 -0
- package/build/lib/reports/labels.js.map +7 -0
- package/build/lib/reports/pdf.js +308 -0
- package/build/lib/reports/pdf.js.map +7 -0
- package/build/lib/reports/types.js +32 -0
- package/build/lib/reports/types.js.map +7 -0
- package/build/lib/reports/xls.js +211 -0
- package/build/lib/reports/xls.js.map +7 -0
- package/build/lib/services/aggregation.js +495 -0
- package/build/lib/services/aggregation.js.map +7 -0
- package/build/lib/services/auth.js +381 -0
- package/build/lib/services/auth.js.map +7 -0
- package/build/lib/services/backup.js +372 -0
- package/build/lib/services/backup.js.map +7 -0
- package/build/lib/services/closing.js +106 -0
- package/build/lib/services/closing.js.map +7 -0
- package/build/lib/services/sessionSecret.js +100 -0
- package/build/lib/services/sessionSecret.js.map +7 -0
- package/build/lib/services/sync.js +278 -0
- package/build/lib/services/sync.js.map +7 -0
- package/build/lib/util/time.js +125 -0
- package/build/lib/util/time.js.map +7 -0
- package/build/lib/web/api.js +2589 -0
- package/build/lib/web/api.js.map +7 -0
- package/build/lib/web/cookies.js +80 -0
- package/build/lib/web/cookies.js.map +7 -0
- package/build/lib/web/events.js +50 -0
- package/build/lib/web/events.js.map +7 -0
- package/build/lib/web/pin-guard.js +86 -0
- package/build/lib/web/pin-guard.js.map +7 -0
- package/build/lib/web/problem.js +129 -0
- package/build/lib/web/problem.js.map +7 -0
- package/build/lib/web/rate-limit.js +65 -0
- package/build/lib/web/rate-limit.js.map +7 -0
- package/build/lib/web/router.js +274 -0
- package/build/lib/web/router.js.map +7 -0
- package/build/lib/web/server.js +189 -0
- package/build/lib/web/server.js.map +7 -0
- package/build/lib/web/static.js +151 -0
- package/build/lib/web/static.js.map +7 -0
- package/build/lib/web/stream.js +135 -0
- package/build/lib/web/stream.js.map +7 -0
- package/build/main.js +986 -0
- package/build/main.js.map +7 -0
- package/io-package.json +221 -0
- package/package.json +131 -0
- package/src-pwa/src/i18n/de.json +359 -0
- package/src-pwa/src/i18n/en.json +359 -0
- package/src-pwa/src/i18n/es.json +359 -0
- package/src-pwa/src/i18n/fr.json +359 -0
- package/src-pwa/src/i18n/index.ts +96 -0
- package/src-pwa/src/i18n/it.json +359 -0
- package/src-pwa/src/i18n/nl.json +359 -0
- package/src-pwa/src/i18n/pl.json +359 -0
- package/src-pwa/src/i18n/pt.json +359 -0
- package/src-pwa/src/i18n/ru.json +359 -0
- package/src-pwa/src/i18n/uk.json +359 -0
- package/src-pwa/src/i18n/zh-cn.json +359 -0
- package/www/assets/index-QI3wrEvW.js +119 -0
- package/www/assets/index-QI3wrEvW.js.map +1 -0
- package/www/assets/workbox-window.prod.es5-Bd17z0YL.js +3 -0
- package/www/assets/workbox-window.prod.es5-Bd17z0YL.js.map +1 -0
- package/www/favicon.svg +16 -0
- package/www/icon-192.png +0 -0
- package/www/icon-512.png +0 -0
- package/www/index.html +38 -0
- package/www/manifest.webmanifest +1 -0
- package/www/person.png +0 -0
- package/www/sw.js +3 -0
- package/www/sw.js.map +1 -0
- package/www/workbox-9c191d2f.js +3 -0
- package/www/workbox-9c191d2f.js.map +1 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
{
|
|
2
|
+
"absences.create": "Demander une absence",
|
|
3
|
+
"absences.created": "Absence demandée.",
|
|
4
|
+
"absences.empty": "Aucune absence cette année.",
|
|
5
|
+
"absences.from": "Depuis",
|
|
6
|
+
"absences.portion": "Part du jour",
|
|
7
|
+
"absences.status": "Statut",
|
|
8
|
+
"absences.title": "Absences",
|
|
9
|
+
"absences.to": "À",
|
|
10
|
+
"absences.type": "Type",
|
|
11
|
+
"absences.typeHint": "Code du type d'absence, par ex. F pour les vacances",
|
|
12
|
+
"admin.backup": "Sauvegardes",
|
|
13
|
+
"admin.backup.create": "Créer une sauvegarde maintenant",
|
|
14
|
+
"admin.backup.upload": "Importer une sauvegarde",
|
|
15
|
+
"admin.backup.uploadHint": "Choisir une sauvegarde téléchargée (.sqlite) - elle est vérifiée et appliquée au prochain démarrage.",
|
|
16
|
+
"admin.backup.delete": "Supprimer",
|
|
17
|
+
"admin.backup.deleteTitle": "Supprimer la sauvegarde",
|
|
18
|
+
"admin.backup.deleteConfirm": "La sauvegarde {{name}} est supprimée. Cette action est irréversible.",
|
|
19
|
+
"admin.backup.done": "Sauvegarde {{name}} écrite, {{removed}} anciens fichiers supprimés.",
|
|
20
|
+
"admin.backup.empty": "Aucune sauvegarde pour l'instant.",
|
|
21
|
+
"admin.backup.retention": "Les sauvegardes datant de plus de {{days}} jours sont supprimées, la plus récente est toujours conservée.",
|
|
22
|
+
"admin.forbidden": "Vous n'êtes pas autorisé à ouvrir l'administration.",
|
|
23
|
+
"admin.title": "Administration",
|
|
24
|
+
"admin.user.active": "Actif",
|
|
25
|
+
"admin.user.create": "Ajouter un employé",
|
|
26
|
+
"admin.user.empty": "Pas encore d'employés.",
|
|
27
|
+
"admin.user.inactive": "Désactivé",
|
|
28
|
+
"admin.user.login": "Se connecter",
|
|
29
|
+
"admin.user.name": "Nom",
|
|
30
|
+
"admin.user.newPin": "Nouveau code PIN",
|
|
31
|
+
"admin.user.password": "Mot de passe",
|
|
32
|
+
"admin.user.passwordHint": "Au moins 8 caractères avec majuscules, minuscules et chiffres.",
|
|
33
|
+
"admin.user.pin": "Code PIN",
|
|
34
|
+
"admin.user.pinHint": "4 à 8 chiffres pour le terminal",
|
|
35
|
+
"admin.user.pinTitle": "Code PIN du badge de {{name}}",
|
|
36
|
+
"admin.user.roles": "Rôles",
|
|
37
|
+
"admin.users": "Employés",
|
|
38
|
+
"app.offline": "Hors ligne : les pointages sont mis en file d'attente",
|
|
39
|
+
"app.online": "Connecté",
|
|
40
|
+
"app.title": "Suivi du temps",
|
|
41
|
+
"common.cancel": "Annuler",
|
|
42
|
+
"common.close": "Fermer",
|
|
43
|
+
"common.loading": "Chargement…",
|
|
44
|
+
"common.none": "–",
|
|
45
|
+
"common.refresh": "Rafraîchir",
|
|
46
|
+
"common.retry": "Réessayer",
|
|
47
|
+
"common.save": "Sauvegarder",
|
|
48
|
+
"error.bad_request": "La contribution n'a pas été acceptée.",
|
|
49
|
+
"error.conflict": "La modification entre en conflit avec les données existantes.",
|
|
50
|
+
"error.csrf_rejected": "La demande a été rejetée pour des raisons de sécurité, veuillez réessayer.",
|
|
51
|
+
"error.invalid_credentials": "Le nom d'utilisateur ou le mot de passe n'est pas correct.",
|
|
52
|
+
"error.locked_out": "Trop de tentatives infructueuses. Veuillez réessayer plus tard.",
|
|
53
|
+
"error.network_error": "Le serveur n'est pas accessible.",
|
|
54
|
+
"error.no_session": "Votre session a expiré, veuillez vous reconnecter.",
|
|
55
|
+
"error.not_found": "Pas trouvé.",
|
|
56
|
+
"error.permission_denied": "Vous n'êtes pas autorisé à faire cela.",
|
|
57
|
+
"error.report_font_missing": "Ce rapport nécessite une police Unicode (report_font_path).",
|
|
58
|
+
"error.revision_conflict": "Le pointage a été modifié entre temps, merci de recharger.",
|
|
59
|
+
"error.session_expired": "Votre session a expiré, veuillez vous reconnecter.",
|
|
60
|
+
"error.unknown_error": "Erreur inattendue.",
|
|
61
|
+
"error.user_inactive": "Ce compte est désactivé.",
|
|
62
|
+
"login.failed": "Échec de la connexion",
|
|
63
|
+
"login.login": "Nom d'utilisateur",
|
|
64
|
+
"login.password": "Mot de passe",
|
|
65
|
+
"login.submit": "Se connecter",
|
|
66
|
+
"login.title": "Se connecter",
|
|
67
|
+
"month.absence": "Absence",
|
|
68
|
+
"month.balance": "Équilibre",
|
|
69
|
+
"error.edit_window_closed": "Hors de la fenêtre de correction",
|
|
70
|
+
"admin.profile.pauseRules": "Règles de pause propres",
|
|
71
|
+
"admin.profile.pauseRulesHint": "Règles pour ce collaborateur uniquement : elles remplacent la règle d'entreprise avec le même « à partir de minutes ». Sans règle propre, le barème de l'entreprise s'applique.",
|
|
72
|
+
"report.csv": "Données brutes (CSV)",
|
|
73
|
+
"month.edit": "Corriger",
|
|
74
|
+
"month.editTitle": "Corriger les pointages · {{date}}",
|
|
75
|
+
"month.editHint": "Uniquement dans la fenêtre de correction - les jours plus anciens sont modifiés par l'administration.",
|
|
76
|
+
"month.time": "Heure",
|
|
77
|
+
"month.direction": "Sens",
|
|
78
|
+
"month.directionIn": "Entrée",
|
|
79
|
+
"month.directionOut": "Sortie",
|
|
80
|
+
"month.addPunch": "Ajouter un pointage",
|
|
81
|
+
"month.pause": "Pause",
|
|
82
|
+
"month.paidBreak": "dont payé",
|
|
83
|
+
"month.empty": "Aucun jour ce mois-ci.",
|
|
84
|
+
"month.holiday": "Vacances",
|
|
85
|
+
"month.months": "Mois de l'année",
|
|
86
|
+
"month.next": "Mois prochain",
|
|
87
|
+
"month.open": "en cours",
|
|
88
|
+
"month.previous": "Mois précédent",
|
|
89
|
+
"month.target": "Cible",
|
|
90
|
+
"month.title": "Mois",
|
|
91
|
+
"month.worked": "A travaillé",
|
|
92
|
+
"nav.absences": "Absences",
|
|
93
|
+
"nav.dashboard": "Pointage",
|
|
94
|
+
"nav.logout": "se déconnecter",
|
|
95
|
+
"nav.menu": "Menu",
|
|
96
|
+
"nav.month": "Mois",
|
|
97
|
+
"nav.profile": "Profil",
|
|
98
|
+
"nav.reports": "Rapports",
|
|
99
|
+
"nav.sync": "Synchronisation",
|
|
100
|
+
"profile.changePassword": "Changer le mot de passe",
|
|
101
|
+
"profile.changed": "Mot de passe modifié, veuillez vous reconnecter.",
|
|
102
|
+
"profile.language": "Langue",
|
|
103
|
+
"profile.newPassword": "Nouveau mot de passe",
|
|
104
|
+
"profile.roles": "Autorisations",
|
|
105
|
+
"profile.title": "Profil",
|
|
106
|
+
"profile.user": "Utilisateur",
|
|
107
|
+
"punch.balance": "Solde aujourd'hui",
|
|
108
|
+
"punch.closed": "Non pointé",
|
|
109
|
+
"punch.in": "Pointer l'arrivée",
|
|
110
|
+
"punch.last": "Dernier pointage {{time}}",
|
|
111
|
+
"punch.note": "Note",
|
|
112
|
+
"punch.now": "Pointer",
|
|
113
|
+
"punch.open": "Pointé depuis {{time}}",
|
|
114
|
+
"punch.out": "Pointer le départ",
|
|
115
|
+
"punch.queued": "Enregistré hors ligne – il sera envoyé automatiquement",
|
|
116
|
+
"punch.quick": "Pointage rapide",
|
|
117
|
+
"punch.sent": "Pointage enregistré ({{time}})",
|
|
118
|
+
"punch.target": "Objectif aujourd'hui",
|
|
119
|
+
"punch.worked": "Travaillé aujourd'hui",
|
|
120
|
+
"report.failed": "L'instruction n'a pas pu être créée.",
|
|
121
|
+
"report.pdf": "PDF",
|
|
122
|
+
"report.xls": "Exceller",
|
|
123
|
+
"reports.empty": "Aucune donnée pour cette période.",
|
|
124
|
+
"reports.monthTotals": "Totaux mensuels",
|
|
125
|
+
"reports.overtime": "Heures supplémentaires",
|
|
126
|
+
"reports.paidOut": "Payé : {{minutes}}",
|
|
127
|
+
"reports.title": "Rapports",
|
|
128
|
+
"reports.vacation": "Vacances (prises/droites)",
|
|
129
|
+
"reports.year": "Année",
|
|
130
|
+
"reports.yearTotals": "Totaux annuels",
|
|
131
|
+
"sync.accept": "Conserver la valeur du serveur",
|
|
132
|
+
"sync.conflictOf": "{{date}} · {{time}}",
|
|
133
|
+
"sync.conflicts": "Conflits ouverts",
|
|
134
|
+
"sync.dismiss": "Jeter",
|
|
135
|
+
"sync.done": "Envoyés : {{accepted}}, doublons : {{duplicates}}, conflits : {{conflicts}}",
|
|
136
|
+
"sync.empty": "Pas de conflits ouverts.",
|
|
137
|
+
"sync.flush": "Envoyer maintenant",
|
|
138
|
+
"sync.none": "Rien à envoyer.",
|
|
139
|
+
"sync.pending": "{{count}} point(s) en attente",
|
|
140
|
+
"sync.permission": "Vous n'êtes pas autorisé à résoudre les conflits.",
|
|
141
|
+
"sync.resolved": "Conflit résolu.",
|
|
142
|
+
"sync.title": "Synchronisation",
|
|
143
|
+
"terminal.title": "Terminal",
|
|
144
|
+
"terminal.deviceToken": "Jeton de l'appareil",
|
|
145
|
+
"terminal.connect": "Connecter",
|
|
146
|
+
"terminal.badge": "Badge",
|
|
147
|
+
"terminal.noPin": "Aucun code PIN n'est nécessaire sur ce terminal.",
|
|
148
|
+
"terminal.pin": "Code PIN",
|
|
149
|
+
"terminal.select": "Choisissez votre nom",
|
|
150
|
+
"terminal.disabled": "Le terminal est désactivé dans les paramètres de l'adaptateur.",
|
|
151
|
+
"admin.terminals": "Terminaux",
|
|
152
|
+
"admin.terminal.name": "Nom",
|
|
153
|
+
"admin.terminal.location": "Emplacement",
|
|
154
|
+
"admin.terminal.pinRequired": "Les employés ont besoin de leur code PIN",
|
|
155
|
+
"admin.terminal.create": "Créer un terminal",
|
|
156
|
+
"admin.terminal.tokenOnce": "Copiez le jeton de l'appareil maintenant — il n'est conservé que comme hachage et affiché une seule fois :",
|
|
157
|
+
"admin.terminal.url": "Ouvrez cette adresse sur l'appareil du kiosque :",
|
|
158
|
+
"admin.terminal.revoke": "Révoquer",
|
|
159
|
+
"admin.terminal.revoked": "révoqué",
|
|
160
|
+
"admin.terminal.users": "Employés",
|
|
161
|
+
"admin.terminal.usersHint": "Sans sélection, la borne affiche tous les employés.",
|
|
162
|
+
"admin.terminal.usersAll": "tous les employés",
|
|
163
|
+
"admin.terminal.empty": "Aucun terminal créé pour l'instant.",
|
|
164
|
+
"admin.terminal.confirmRevoke": "Révoquer « {{name}} » ? Son jeton d'appareil cesse immédiatement de fonctionner.",
|
|
165
|
+
"admin.settings": "Paramètres",
|
|
166
|
+
"admin.settings.fontPath": "Fichier de police Unicode pour les relevés PDF (.ttf/.otf)",
|
|
167
|
+
"admin.user.profile": "Profil de travail",
|
|
168
|
+
"admin.user.profileTitle": "Profil de travail · {{name}}",
|
|
169
|
+
"admin.profile.percent": "Taux d'occupation (%)",
|
|
170
|
+
"admin.profile.weeklyHours": "Heures hebdomadaires à 100 %",
|
|
171
|
+
"admin.profile.workdays": "Jours de travail",
|
|
172
|
+
"admin.profile.overtimeModel": "Modèle d'heures supplémentaires",
|
|
173
|
+
"admin.profile.model.monthly": "Mensuel",
|
|
174
|
+
"admin.profile.model.yearly": "Annuel",
|
|
175
|
+
"admin.profile.model.cumulative": "Cumulatif",
|
|
176
|
+
"admin.profile.vacationPerYear": "Jours de vacances par an",
|
|
177
|
+
"admin.profile.vacationCarryover": "Vacances reportées (jours)",
|
|
178
|
+
"admin.profile.overtimeCarryover": "Heures supplémentaires reportées (heures)",
|
|
179
|
+
"admin.profile.vorholzeitPerYear": "« Vorholzeit » par an (heures)",
|
|
180
|
+
"admin.profile.pausePaid": "Minutes de pause payées par jour",
|
|
181
|
+
"admin.profile.pausePaidHint": "Ces minutes de la pause comptent comme temps de travail (0 = la pause n'est pas payée).",
|
|
182
|
+
"admin.settings.pauseMode": "Pauses",
|
|
183
|
+
"admin.settings.pauseModeTitle": "Règle de pause",
|
|
184
|
+
"admin.settings.pauseModeHint": "Comment la pause d'une journée est déterminée.",
|
|
185
|
+
"admin.settings.pauseRules": "Barème des pauses",
|
|
186
|
+
"admin.settings.pauseRulesHint": "S'applique aux jours sans pause pointée : à partir de la durée indiquée (du premier au dernier pointage d'un bloc), les minutes sont déduites.",
|
|
187
|
+
"admin.settings.pauseFrom": "à partir de minutes",
|
|
188
|
+
"admin.settings.pauseTo": "jusqu'à minutes (vide = sans fin)",
|
|
189
|
+
"admin.settings.pauseMinutes": "minutes de pause",
|
|
190
|
+
"admin.settings.pauseActive": "Règle active",
|
|
191
|
+
"admin.settings.pauseAdd": "Ajouter une règle",
|
|
192
|
+
"admin.settings.pauseSave": "Enregistrer le barème",
|
|
193
|
+
"admin.settings.pauseMode.auto": "Pause pointée, sinon le barème",
|
|
194
|
+
"admin.settings.pauseMode.punched": "Uniquement les pauses pointées",
|
|
195
|
+
"admin.settings.pauseMode.staffel": "Uniquement le barème des pauses",
|
|
196
|
+
"admin.settings.fontPathHint": "Nécessaire pour le russe, l'ukrainien et le chinois ; vide = polices intégrées, qui ne couvrent que Latin-1.",
|
|
197
|
+
"admin.settings.advanced": "Tous les paramètres de l'instance (noms techniques, 1/0 pour les commutateurs)",
|
|
198
|
+
"admin.settings.setting.edit_window_days": "Fenêtre de modification (jours)",
|
|
199
|
+
"admin.settings.setting.quick_round_minutes": "Arrondi (min)",
|
|
200
|
+
"admin.settings.setting.absence_calc_until_today": "Absences à ce jour",
|
|
201
|
+
"admin.settings.setting.absence_deduct_worktime": "Déduire les absences",
|
|
202
|
+
"admin.settings.setting.print_limit_days": "Limite d'impression (jours)",
|
|
203
|
+
"admin.settings.setting.holiday_country": "Pays des jours fériés",
|
|
204
|
+
"admin.settings.setting.default_language": "Langue par défaut",
|
|
205
|
+
"admin.settings.setting.session_ttl_minutes": "Durée de session (min)",
|
|
206
|
+
"admin.settings.setting.backup_retention_days": "Sauvegardes (jours)",
|
|
207
|
+
"admin.settings.setting.attendance_list_visible": "Liste de présence",
|
|
208
|
+
"admin.settings.setting.timezone": "Fuseau horaire",
|
|
209
|
+
"admin.settings.saved": "Paramètres enregistrés.",
|
|
210
|
+
"admin.holidays": "Jours fériés",
|
|
211
|
+
"admin.holiday.date": "Date (AAAA-MM-JJ)",
|
|
212
|
+
"admin.holiday.name": "Nom",
|
|
213
|
+
"holiday.newYear": "Nouvel An",
|
|
214
|
+
"holiday.epiphany": "Épiphanie",
|
|
215
|
+
"holiday.goodFriday": "Vendredi saint",
|
|
216
|
+
"holiday.easterMonday": "Lundi de Pâques",
|
|
217
|
+
"holiday.labourDay": "Fête du Travail",
|
|
218
|
+
"holiday.ascension": "Ascension",
|
|
219
|
+
"holiday.whitMonday": "Lundi de Pentecôte",
|
|
220
|
+
"holiday.corpusChristi": "Fête-Dieu",
|
|
221
|
+
"holiday.nationalDay": "Fête nationale",
|
|
222
|
+
"holiday.germanUnity": "Jour de l'unité allemande",
|
|
223
|
+
"holiday.assumption": "Assomption",
|
|
224
|
+
"holiday.allSaints": "Toussaint",
|
|
225
|
+
"holiday.immaculateConception": "Immaculée Conception",
|
|
226
|
+
"holiday.christmas": "Noël",
|
|
227
|
+
"holiday.boxingDay": "Lendemain de Noël",
|
|
228
|
+
"admin.holiday.add": "Ajouter un jour férié",
|
|
229
|
+
"admin.holiday.year": "Année",
|
|
230
|
+
"admin.holiday.region": "Région (facultatif)",
|
|
231
|
+
"admin.holiday.empty": "Aucun jour férié enregistré pour cette année.",
|
|
232
|
+
"admin.tags": "Badges (RFID/NFC)",
|
|
233
|
+
"admin.tag.label": "Libellé",
|
|
234
|
+
"admin.tag.user": "Employé",
|
|
235
|
+
"admin.tag.create": "Créer un badge",
|
|
236
|
+
"admin.tag.linkOnce": "Écrivez ce lien sur le badge ou ouvrez-le sur le téléphone :",
|
|
237
|
+
"admin.tag.delete": "Supprimer",
|
|
238
|
+
"admin.tag.active": "actif",
|
|
239
|
+
"admin.tag.expired": "expiré",
|
|
240
|
+
"admin.tag.revoked": "révoqué",
|
|
241
|
+
"admin.tag.lastUsed": "dernier usage",
|
|
242
|
+
"admin.tag.remove": "Supprimer définitivement",
|
|
243
|
+
"admin.tag.edit": "Modifier",
|
|
244
|
+
"admin.tag.reissue": "Nouveau lien",
|
|
245
|
+
"admin.tag.editTitle": "Modifier le badge",
|
|
246
|
+
"admin.tag.editHint": "Un autre employé ou une nouvelle validité émet un nouveau lien — le lien précédent cesse immédiatement de fonctionner.",
|
|
247
|
+
"admin.tag.validityDays": "Validité (jours)",
|
|
248
|
+
"admin.tag.oldLinkDead": "Le lien précédent ne fonctionne plus.",
|
|
249
|
+
"admin.tag.qrAlt": "Code QR du lien du badge",
|
|
250
|
+
"admin.tag.empty": "Aucun badge créé pour l'instant.",
|
|
251
|
+
"nav.statistics": "Statistiques",
|
|
252
|
+
"statistics.from": "Du",
|
|
253
|
+
"statistics.to": "Au",
|
|
254
|
+
"statistics.employee": "Employé",
|
|
255
|
+
"statistics.worked": "Travaillé",
|
|
256
|
+
"statistics.target": "Objectif",
|
|
257
|
+
"statistics.balance": "Solde",
|
|
258
|
+
"statistics.openDays": "Jours ouverts",
|
|
259
|
+
"statistics.totals": "Tous les employés",
|
|
260
|
+
"scan.title": "Badge",
|
|
261
|
+
"scan.done": "Pointé pour {{name}} à {{time}}",
|
|
262
|
+
"scan.failed": "Le badge n'a pas pu être utilisé : {{reason}}",
|
|
263
|
+
"presence.title": "Présence",
|
|
264
|
+
"presence.present": "Présent",
|
|
265
|
+
"presence.absent": "Absent",
|
|
266
|
+
"presence.tapPin": "Saisissez le code PIN pour pointer",
|
|
267
|
+
"presence.cancel": "Annuler",
|
|
268
|
+
"presence.updated": "{{name}} est maintenant {{state}}",
|
|
269
|
+
"presence.disabled": "Le terminal borne est désactivé dans les paramètres de l'instance.",
|
|
270
|
+
"admin.user.photo": "Photo",
|
|
271
|
+
"admin.user.photoTitle": "Photo de {{name}}",
|
|
272
|
+
"admin.user.photoChoose": "Choisir une image",
|
|
273
|
+
"admin.user.photoRemove": "Supprimer l'image",
|
|
274
|
+
"admin.user.photoHint": "PNG, JPEG, WEBP ou GIF jusqu'à 256 Ko. Sans image, la vignette par défaut s'affiche.",
|
|
275
|
+
"admin.corrections": "Corrections de temps",
|
|
276
|
+
"corrections.employee": "Collaborateur",
|
|
277
|
+
"corrections.previous": "Mois précédent",
|
|
278
|
+
"corrections.next": "Mois suivant",
|
|
279
|
+
"corrections.reason": "Motif",
|
|
280
|
+
"corrections.reasonHint": "Conservé dans le journal (audit)",
|
|
281
|
+
"corrections.add": "Ajouter un pointage ou une journée",
|
|
282
|
+
"corrections.addTitle": "Ajouter un pointage",
|
|
283
|
+
"corrections.addHint": "Laissez « sortie » vide s’il ne manque qu’un pointage",
|
|
284
|
+
"corrections.editTitle": "Modifier le pointage",
|
|
285
|
+
"corrections.remove": "Supprimer le pointage",
|
|
286
|
+
"corrections.date": "Date",
|
|
287
|
+
"corrections.from": "Arrivée",
|
|
288
|
+
"corrections.to": "Départ",
|
|
289
|
+
"corrections.direction": "Sens",
|
|
290
|
+
"corrections.note": "Remarque",
|
|
291
|
+
"corrections.empty": "Aucun pointage ce mois-ci",
|
|
292
|
+
"corrections.byAdmin": "ajouté par l’administration",
|
|
293
|
+
"corrections.history": "Historique",
|
|
294
|
+
"corrections.actor": "Par",
|
|
295
|
+
"corrections.actionCreate": "Ajouté",
|
|
296
|
+
"corrections.actionUpdate": "Modifié",
|
|
297
|
+
"corrections.actionDelete": "Supprimé",
|
|
298
|
+
"keypad.backspace": "Effacer",
|
|
299
|
+
"admin.settings.branding": "Identité visuelle",
|
|
300
|
+
"admin.settings.brandingHint": "Logo, image d'arrière-plan et couleur d'arrière-plan de cette installation. L'écran de connexion et les écrans kiosque les affichent également.",
|
|
301
|
+
"admin.settings.brandLogo": "Choisir le logo",
|
|
302
|
+
"admin.settings.brandBackground": "Choisir l'arrière-plan",
|
|
303
|
+
"admin.brand.imageResized": "Réduite pour l'affichage ({{size}}).",
|
|
304
|
+
"admin.brand.imageTooLarge": "Même réduite, l'image reste trop grande.",
|
|
305
|
+
"admin.brand.imageType": "Seuls PNG, JPEG, WEBP ou GIF sont possibles.",
|
|
306
|
+
"admin.brand.imageUnreadable": "L'image n'a pas pu être lue.",
|
|
307
|
+
"admin.settings.brandColor": "Couleur d'arrière-plan",
|
|
308
|
+
"admin.settings.brandColorHint": "Valeur hexadécimale comme #1a2b3c",
|
|
309
|
+
"admin.settings.brandColorPresets": "Couleurs proposées",
|
|
310
|
+
"admin.settings.brandColorDefault": "Par défaut",
|
|
311
|
+
"admin.backup.download": "Télécharger",
|
|
312
|
+
"admin.backup.restore": "Restaurer",
|
|
313
|
+
"admin.backup.restoreTitle": "Restaurer une sauvegarde",
|
|
314
|
+
"admin.backup.restoreConfirm": "La sauvegarde {{name}} est appliquée au prochain démarrage de l'adaptateur ; la base de données actuelle est conservée à côté sous forme de fichier. Redémarrez ensuite l'instance.",
|
|
315
|
+
"admin.backup.pendingHint": "{{name}} est appliquée au prochain démarrage ({{users}} collaborateurs, {{entries}} pointages) - redémarrez l'instance.",
|
|
316
|
+
"error.backup_invalid": "Ce fichier n'est pas une sauvegarde de cet adaptateur.",
|
|
317
|
+
"admin.settings.brandImageRemove": "Supprimer l'image",
|
|
318
|
+
"admin.settings.brandColorDefaultHint": "Réinitialise la couleur et l'image d'arrière-plan",
|
|
319
|
+
"admin.triggers": "Actions (ioBroker)",
|
|
320
|
+
"admin.triggersHint": "Un état d'un autre adaptateur pointe ou définit la présence — un lecteur d'empreinte, un bouton ou un contact de porte. Il se déclenche uniquement lorsque la valeur change. Comme valeur, vous pouvez saisir `toggle` : il réagit alors à chaque changement (par exemple activé puis désactivé).",
|
|
321
|
+
"admin.trigger.label": "Désignation",
|
|
322
|
+
"admin.trigger.sourceState": "État",
|
|
323
|
+
"admin.trigger.mode": "Déclencheur",
|
|
324
|
+
"admin.trigger.modeCondition": "L'état porte la valeur",
|
|
325
|
+
"admin.trigger.modeUser": "La valeur est l'employé",
|
|
326
|
+
"admin.trigger.condition": "Valeur",
|
|
327
|
+
"admin.trigger.user": "Employé",
|
|
328
|
+
"admin.trigger.action": "Effet",
|
|
329
|
+
"admin.trigger.actionPunch": "Pointer (entrée ou sortie)",
|
|
330
|
+
"admin.trigger.actionQuickPunch": "Pointer avec arrondi rapide",
|
|
331
|
+
"admin.trigger.actionPresent": "Définir comme présent",
|
|
332
|
+
"admin.trigger.actionAbsent": "Définir comme absent",
|
|
333
|
+
"admin.trigger.cooldown": "Blocage (secondes)",
|
|
334
|
+
"admin.trigger.active": "Actif",
|
|
335
|
+
"admin.trigger.add": "Ajouter une action",
|
|
336
|
+
"admin.trigger.lastFired": "Dernier déclenchement",
|
|
337
|
+
"admin.trigger.empty": "Aucune action pour l'instant.",
|
|
338
|
+
"admin.trigger.conditionHint": "Valeur ou `toggle` pour réagir à chaque changement",
|
|
339
|
+
"admin.settings.automations": "Règles (automatiques)",
|
|
340
|
+
"admin.settings.automationsHint": "Ce que l'adaptateur fait seul : pointer la sortie à l'heure locale définie, signaler une sortie manquante ou rappeler après un travail trop long sans pause. Une règle s'exécute au plus une fois par employé et par jour.",
|
|
341
|
+
"admin.automation.kind": "Type",
|
|
342
|
+
"admin.automation.kindClockIn": "Pointer l'arrivée automatiquement",
|
|
343
|
+
"admin.automation.kindClockOut": "Pointer la sortie automatiquement",
|
|
344
|
+
"admin.automation.kindMissingPunch": "Signaler une sortie manquante",
|
|
345
|
+
"admin.automation.kindBreakReminder": "Rappel de pause",
|
|
346
|
+
"admin.automation.at": "Heure",
|
|
347
|
+
"admin.automation.atHint": "Heure locale de l'employé",
|
|
348
|
+
"admin.automation.after": "Après (minutes)",
|
|
349
|
+
"admin.automation.user": "Employé",
|
|
350
|
+
"admin.automation.allUsers": "tous les employés",
|
|
351
|
+
"admin.automation.add": "Ajouter une règle",
|
|
352
|
+
"admin.automation.empty": "Aucune règle pour l'instant.",
|
|
353
|
+
"admin.automation.runs": "Dernières exécutions",
|
|
354
|
+
"admin.automation.weekdays": "Jours de la semaine",
|
|
355
|
+
"admin.automation.repeat": "Répétition",
|
|
356
|
+
"admin.automation.repeatDay": "une fois par jour",
|
|
357
|
+
"admin.automation.repeatWeek": "une fois par semaine",
|
|
358
|
+
"admin.settings.setting.report_font_path": "Police pour PDF"
|
|
359
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translations of the web app.
|
|
3
|
+
*
|
|
4
|
+
* `i18next` with a flat key set; English is the base and the fallback. The language comes from the logged in
|
|
5
|
+
* user (the adapter stores it per user), otherwise from the browser. API errors are translated by their stable
|
|
6
|
+
* code (see `api.client`), never by their message.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import i18n from "i18next";
|
|
10
|
+
import { initReactI18next } from "react-i18next";
|
|
11
|
+
import en from "./en.json";
|
|
12
|
+
import de from "./de.json";
|
|
13
|
+
import ru from "./ru.json";
|
|
14
|
+
import pt from "./pt.json";
|
|
15
|
+
import nl from "./nl.json";
|
|
16
|
+
import fr from "./fr.json";
|
|
17
|
+
import it from "./it.json";
|
|
18
|
+
import es from "./es.json";
|
|
19
|
+
import pl from "./pl.json";
|
|
20
|
+
import uk from "./uk.json";
|
|
21
|
+
import zhCn from "./zh-cn.json";
|
|
22
|
+
|
|
23
|
+
/** Languages the adapter ships. */
|
|
24
|
+
export const SUPPORTED_LANGUAGES = ["en", "de", "ru", "pt", "nl", "fr", "it", "es", "pl", "uk", "zh-cn"] as const;
|
|
25
|
+
|
|
26
|
+
/** A supported language code. */
|
|
27
|
+
export type Language = (typeof SUPPORTED_LANGUAGES)[number];
|
|
28
|
+
|
|
29
|
+
const resources = {
|
|
30
|
+
en: { translation: en },
|
|
31
|
+
de: { translation: de },
|
|
32
|
+
ru: { translation: ru },
|
|
33
|
+
pt: { translation: pt },
|
|
34
|
+
nl: { translation: nl },
|
|
35
|
+
fr: { translation: fr },
|
|
36
|
+
it: { translation: it },
|
|
37
|
+
es: { translation: es },
|
|
38
|
+
pl: { translation: pl },
|
|
39
|
+
uk: { translation: uk },
|
|
40
|
+
"zh-cn": { translation: zhCn },
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Picks the language to start with.
|
|
45
|
+
*
|
|
46
|
+
* @returns language code the app uses until a user is known
|
|
47
|
+
*/
|
|
48
|
+
export function detectLanguage(): Language {
|
|
49
|
+
if (typeof navigator === "undefined") {
|
|
50
|
+
return "en";
|
|
51
|
+
}
|
|
52
|
+
const candidates = [...(navigator.languages ?? []), navigator.language];
|
|
53
|
+
for (const candidate of candidates) {
|
|
54
|
+
const lower = candidate.toLowerCase();
|
|
55
|
+
const exact = SUPPORTED_LANGUAGES.find(language => language === lower);
|
|
56
|
+
if (exact) {
|
|
57
|
+
return exact;
|
|
58
|
+
}
|
|
59
|
+
const base = lower.split("-")[0];
|
|
60
|
+
const match = SUPPORTED_LANGUAGES.find(language => language === base);
|
|
61
|
+
if (match) {
|
|
62
|
+
return match;
|
|
63
|
+
}
|
|
64
|
+
// Chinese is shipped as `zh-cn`
|
|
65
|
+
if (base === "zh") {
|
|
66
|
+
return "zh-cn";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return "en";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Resolves a language code of the adapter (user setting) to one the app ships.
|
|
74
|
+
*
|
|
75
|
+
* @param value - language code from the user record
|
|
76
|
+
* @returns supported language
|
|
77
|
+
*/
|
|
78
|
+
export function normaliseLanguage(value: string | undefined): Language {
|
|
79
|
+
const lower = (value ?? "").toLowerCase();
|
|
80
|
+
const exact = SUPPORTED_LANGUAGES.find(language => language === lower);
|
|
81
|
+
if (exact) {
|
|
82
|
+
return exact;
|
|
83
|
+
}
|
|
84
|
+
const base = lower.split("-")[0];
|
|
85
|
+
return SUPPORTED_LANGUAGES.find(language => language === base) ?? detectLanguage();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void i18n.use(initReactI18next).init({
|
|
89
|
+
resources,
|
|
90
|
+
lng: detectLanguage(),
|
|
91
|
+
fallbackLng: "en",
|
|
92
|
+
interpolation: { escapeValue: false },
|
|
93
|
+
returnNull: false,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export default i18n;
|