This commit is contained in:
AuroraLS3 2024-04-20 07:26:18 +00:00
parent b165a0168b
commit b5e6985be1
41 changed files with 1308 additions and 1019 deletions

View File

@ -290,6 +290,8 @@ html:
active: "活跃" active: "活跃"
activePlaytime: "活跃时间" activePlaytime: "活跃时间"
activityIndex: "活跃指数" activityIndex: "活跃指数"
addJoinAddressGroup: "添加地址组"
addressGroup: "地址组 {{n}}"
afk: "挂机" afk: "挂机"
afkTime: "挂机时间" afkTime: "挂机时间"
all: "全部" all: "全部"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "查看按国家划分的Ping表" page_network_geolocations_ping_per_country: "查看按国家划分的Ping表"
page_network_join_addresses: "查看加入地址 - 选项卡" page_network_join_addresses: "查看加入地址 - 选项卡"
page_network_join_addresses_graphs: "查看加入地址图表" page_network_join_addresses_graphs: "查看加入地址图表"
page_network_join_addresses_graphs_pie: "查看最新加入地址图表"
page_network_join_addresses_graphs_time: "查看加入地址随时间变化的图表" page_network_join_addresses_graphs_time: "查看加入地址随时间变化的图表"
page_network_overview: "查看网络总览 - 选项卡" page_network_overview: "查看网络总览 - 选项卡"
page_network_overview_graphs: "查看网络总览图表" page_network_overview_graphs: "查看网络总览图表"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "查看按国家划分的延迟表" page_server_geolocations_ping_per_country: "查看按国家划分的延迟表"
page_server_join_addresses: "查看服务器加入地址 - 选项卡" page_server_join_addresses: "查看服务器加入地址 - 选项卡"
page_server_join_addresses_graphs: "查看服务器加入地址图表" page_server_join_addresses_graphs: "查看服务器加入地址图表"
page_server_join_addresses_graphs_pie: "查看最新加入地址图表"
page_server_join_addresses_graphs_time: "查看服务器加入地址随时间变化的图表" page_server_join_addresses_graphs_time: "查看服务器加入地址随时间变化的图表"
page_server_online_activity: "查看在线活动 - 选项卡" page_server_online_activity: "查看在线活动 - 选项卡"
page_server_online_activity_graphs: "查看在线活动图表" page_server_online_activity_graphs: "查看在线活动图表"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`是`" are: "`是`"
label: label:
editQuery: "修改查询"
from: ">从 </label>" from: ">从 </label>"
makeAnother: "进行另一个查询" makeAnother: "进行另一个查询"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Aktivní" active: "Aktivní"
activePlaytime: "Aktivní herní čas" activePlaytime: "Aktivní herní čas"
activityIndex: "Index aktivity" activityIndex: "Index aktivity"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK čas" afkTime: "AFK čas"
all: "Vše" all: "Vše"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "` jsou`" are: "` jsou`"
label: label:
editQuery: "Edit Query"
from: ">od</label>" from: ">od</label>"
makeAnother: "Vytvořit další dotaz" makeAnother: "Vytvořit další dotaz"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Aktiv" active: "Aktiv"
activePlaytime: "Aktive Spielzeit" activePlaytime: "Aktive Spielzeit"
activityIndex: "Aktivitätsindex" activityIndex: "Aktivitätsindex"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK Zeit" afkTime: "AFK Zeit"
all: "Gesamt" all: "Gesamt"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">from</label>" from: ">from</label>"
makeAnother: "Make another query" makeAnother: "Make another query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Active" active: "Active"
activePlaytime: "Active Playtime" activePlaytime: "Active Playtime"
activityIndex: "Activity Index" activityIndex: "Activity Index"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK Time" afkTime: "AFK Time"
all: "All" all: "All"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">from</label>" from: ">from</label>"
makeAnother: "Make another query" makeAnother: "Make another query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Activo" active: "Activo"
activePlaytime: "Tiempo de juego activo" activePlaytime: "Tiempo de juego activo"
activityIndex: "Índice de actividad" activityIndex: "Índice de actividad"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Tiempo AFK" afkTime: "Tiempo AFK"
all: "Todo" all: "Todo"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">de</label>" from: ">de</label>"
makeAnother: "Realiza otra consulta" makeAnother: "Realiza otra consulta"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Aktiivinen" active: "Aktiivinen"
activePlaytime: "Aktiivinen peliaika" activePlaytime: "Aktiivinen peliaika"
activityIndex: "Aktiivisuus Indeksi" activityIndex: "Aktiivisuus Indeksi"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Aika AFK:ina" afkTime: "Aika AFK:ina"
all: "Kaikki" all: "Kaikki"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "Näkee Viive per Maa -taulun" page_network_geolocations_ping_per_country: "Näkee Viive per Maa -taulun"
page_network_join_addresses: "Näkee Liittymäosoitteet osion" page_network_join_addresses: "Näkee Liittymäosoitteet osion"
page_network_join_addresses_graphs: "Näkee Liittymisosoite kaaviot" page_network_join_addresses_graphs: "Näkee Liittymisosoite kaaviot"
page_network_join_addresses_graphs_pie: "Näkee kaavion Viimeisimmistä liittymisosoitteista"
page_network_join_addresses_graphs_time: "Näkee kaavion Liittymisosoitteista ajan yli" page_network_join_addresses_graphs_time: "Näkee kaavion Liittymisosoitteista ajan yli"
page_network_overview: "Näkee Verkoston katsaus osion" page_network_overview: "Näkee Verkoston katsaus osion"
page_network_overview_graphs: "Näkee Verkoston katsaus kaaviot" page_network_overview_graphs: "Näkee Verkoston katsaus kaaviot"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "Näkee Viive per Maa -taulun" page_server_geolocations_ping_per_country: "Näkee Viive per Maa -taulun"
page_server_join_addresses: "Näkee Liittymäosoitteet osion" page_server_join_addresses: "Näkee Liittymäosoitteet osion"
page_server_join_addresses_graphs: "Näkee Liittymisosoite kaaviot" page_server_join_addresses_graphs: "Näkee Liittymisosoite kaaviot"
page_server_join_addresses_graphs_pie: "Näkee kaavion Viimeisimmistä liittymisosoitteista"
page_server_join_addresses_graphs_time: "Näkee kaavion Liittymisosoitteista ajan yli" page_server_join_addresses_graphs_time: "Näkee kaavion Liittymisosoitteista ajan yli"
page_server_online_activity: "Näkee Online Aktiivisuus osion" page_server_online_activity: "Näkee Online Aktiivisuus osion"
page_server_online_activity_graphs: "Näkee Online Aktiivisuus kaaviot" page_server_online_activity_graphs: "Näkee Online Aktiivisuus kaaviot"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`ovat`" are: "`ovat`"
label: label:
editQuery: "Edit Query"
from: ">tästä</label>" from: ">tästä</label>"
makeAnother: "Tee toinen kysely" makeAnother: "Tee toinen kysely"
servers: servers:

View File

@ -24,8 +24,8 @@ command:
description: "Nom de la fonctionnalité à désactiver : ${0}" description: "Nom de la fonctionnalité à désactiver : ${0}"
name: "fonctionnalité" name: "fonctionnalité"
group: group:
description: "Web Permission Group, case sensitive." description: "Groupe de permissions Web, sensible à la casse."
name: "group" name: "groupe"
importKind: "type d'importation" importKind: "type d'importation"
nameOrUUID: nameOrUUID:
description: "Nom ou UUID d'un joueur" description: "Nom ou UUID d'un joueur"
@ -67,16 +67,16 @@ command:
failSameServer: "Impossible de marquer ce serveur comme désinstallé (vous y êtes)." failSameServer: "Impossible de marquer ce serveur comme désinstallé (vous y êtes)."
hotswap: "§eN'oubliez pas de passer à la nouvelle base de données (/plan db hotswap ${0}) & de recharger Plan." hotswap: "§eN'oubliez pas de passer à la nouvelle base de données (/plan db hotswap ${0}) & de recharger Plan."
importers: "Importateurs :" importers: "Importateurs :"
preparing: "Preparing.." preparing: "Préparation..."
progress: "${0} / ${1} traité(s).." progress: "${0} / ${1} traité(s)."
start: "> §2Traitement des données..." start: "> §2Traitement des données..."
success: "> §aSuccès !" success: "> §aSuccès !"
playerRemoval: "Suppression des données de ${0} depuis ${1}.." playerRemoval: "Suppression des données de ${0} depuis ${1}."
removal: "Suppression des données de Plan depuis ${0}.." removal: "Suppression des données de Plan depuis ${0}."
serverUninstalled: "§aSi le serveur est toujours installé, il se définira automatiquement comme dans la base de données." serverUninstalled: "§aSi le serveur est toujours installé, il se définira automatiquement comme dans la base de données."
unregister: "Désenregistrement de '${0}'.." unregister: "Désenregistrement de '${0}'."
warnDbNotOpen: "§eLa base de données est : ${0} - Cela pourrait prendre plus de temps que prévu..." warnDbNotOpen: "§eLa base de données est : ${0} - Cela pourrait prendre plus de temps que prévu."
write: "Écriture à ${0}.." write: "Écriture à ${0}."
fail: fail:
emptyString: "La chaîne de recherche ne peut pas être vide" emptyString: "La chaîne de recherche ne peut pas être vide"
invalidArguments: "Accepte les éléments suivants comme ${0} : ${1}" invalidArguments: "Accepte les éléments suivants comme ${0} : ${1}"
@ -172,7 +172,7 @@ command:
description: "Déconnecter les autres utilisateurs du panel" description: "Déconnecter les autres utilisateurs du panel"
inDepth: "Donnez un nom d'utilisateur à déconnecter du panel, donnez * comme argument pour déconnecter tout le monde." inDepth: "Donnez un nom d'utilisateur à déconnecter du panel, donnez * comme argument pour déconnecter tout le monde."
migrateToOnlineUuids: migrateToOnlineUuids:
description: "Migrate offline uuid data to online uuids" description: "Migrer les données des uuid hors ligne vers les uuids en ligne"
network: network:
description: "Visualiser la page du réseau" description: "Visualiser la page du réseau"
inDepth: "Obtient un lien vers la page /network, uniquement sur les réseaux." inDepth: "Obtient un lien vers la page /network, uniquement sur les réseaux."
@ -189,7 +189,7 @@ command:
description: "Recharger Plan" description: "Recharger Plan"
inDepth: "Désactive et active le plugin pour recharger tout changement dans la configuration." inDepth: "Désactive et active le plugin pour recharger tout changement dans la configuration."
removejoinaddresses: removejoinaddresses:
description: "Remove join addresses of a specified server" description: "Supprimer les adresses de connexion d'un serveur spécifié"
search: search:
description: "Rechercher un joueur" description: "Rechercher un joueur"
inDepth: "Liste tous les noms de joueurs correspondant à une partie donnée d'un nom." inDepth: "Liste tous les noms de joueurs correspondant à une partie donnée d'un nom."
@ -200,8 +200,8 @@ command:
description: "Obtenir la liste des serveurs dans la base de données" description: "Obtenir la liste des serveurs dans la base de données"
inDepth: "Liste les ids, noms et uuids des serveurs de la base de données." inDepth: "Liste les ids, noms et uuids des serveurs de la base de données."
setgroup: setgroup:
description: "Change users web permission group." description: "Changer le groupe de permissions des utilisateur du site web."
inDepth: "Allows you to change a users web permission group to an existing web group. Use /plan groups for list of available groups." inDepth: "Permet de changer un groupe de permissions web d'un utilisateur par un groupe web existant. Utilisez /plan groups pour obtenir la liste des groupes disponibles."
unregister: unregister:
description: "Désenregistrer un utilisateur du site de Plan" description: "Désenregistrer un utilisateur du site de Plan"
inDepth: "Utilisez sans argument pour désenregistrer un utilisateur lié à un joueur, ou avec un nom d'utilisateur pour désenregistrer un autre utilisateur." inDepth: "Utilisez sans argument pour désenregistrer un utilisateur lié à un joueur, ou avec un nom d'utilisateur pour désenregistrer un autre utilisateur."
@ -248,17 +248,17 @@ html:
unique: "Unique :" unique: "Unique :"
description: description:
newPlayerRetention: "Cette valeur est une prédiction basée sur les joueurs précédents." newPlayerRetention: "Cette valeur est une prédiction basée sur les joueurs précédents."
noData24h: "Server has not sent data for over 24 hours." noData24h: "Le serveur n'a pas envoyé de données depuis plus de 24 heures."
noData30d: "Server has not sent data for over 30 days." noData30d: "Le serveur n'a pas envoyé de données depuis plus de 30 jours."
noData7d: "Server has not sent data for over 7 days." noData7d: "Le serveur n'a pas envoyé de données depuis plus de 7 jours."
noGameServers: "Certaines données nécessitent l'installation de Plan sur les serveurs de jeu." noGameServers: "Certaines données nécessitent l'installation de Plan sur les serveurs de jeu."
noGeolocations: "La collecte de la géolocalisation doit être activée dans la configuration (Accepter l'EULA de GeoLite2)." noGeolocations: "La collecte de la géolocalisation doit être activée dans la configuration (Accepter l'EULA de GeoLite2)."
noServerOnlinActivity: "Aucun serveur pour afficher l'activité en ligne." noServerOnlinActivity: "Aucun serveur pour afficher l'activité en ligne."
noServers: "Il n'y a pas de serveur dans la base de données." noServers: "Il n'y a pas de serveur dans la base de données."
noServersLong: 'Il semblerait que Plan ne soit installé sur aucun des serveurs de jeu ou qu'il ne soit pas connecté à la même base de données. Voir <a href="https://github.com/plan-player-analytics/Plan/wiki">wiki</a> pour un tutoriel sur la mise en place d'un Réseau.' noServersLong: 'Il semblerait que Plan ne soit installé sur aucun des serveurs de jeu ou qu''il ne soit pas connecté à la même base de données. Voir <a href="https://github.com/plan-player-analytics/Plan/wiki">wiki</a> pour un tutoriel sur la mise en place d''un Réseau.'
noSpongeChunks: "Chunks indisponibles sur Sponge" noSpongeChunks: "Chunks indisponibles sur Sponge"
noUptimeCalculation: "Server is offline, or has never restarted with Plan installed." noUptimeCalculation: "Le serveur est hors ligne ou n'a jamais redémarré avec Plan installé."
performanceNoGameServers: "TPS, Entity or Chunk data is not gathered from proxy servers since they don't have game tick loop." performanceNoGameServers: "Les données TPS, Entité ou Chunk ne sont pas collectées à partir des serveurs proxy car ils n'ont pas de boucle de tick de jeu."
predictedNewPlayerRetention: "Cette valeur est une prédiction basée sur les anciennes données du joueur." predictedNewPlayerRetention: "Cette valeur est une prédiction basée sur les anciennes données du joueur."
error: error:
401Unauthorized: "Non autorisé." 401Unauthorized: "Non autorisé."
@ -275,173 +275,175 @@ html:
groupNotFound: "Web Permission Group does not exist" groupNotFound: "Web Permission Group does not exist"
loginFailed: "L'utilisateur et le mot de passe ne correspondent pas" loginFailed: "L'utilisateur et le mot de passe ne correspondent pas"
noCookie: "Cookie de l'utilisateur non présent" noCookie: "Cookie de l'utilisateur non présent"
noPermissionGroup: "Registration failed, player did not have any 'plan.webgroup.{name}' permission" noPermissionGroup: "L'enregistrement a échoué, le joueur n'avait pas la permission 'plan.webgroup.{name}'"
registrationFailed: "Enregistrement échoué, veuillez réessayer (Le code expire au bout de 15 minutes)" registrationFailed: "Enregistrement échoué, veuillez réessayer (Le code expire au bout de 15 minutes)"
userNotFound: "Cet utilisateur n'existe pas" userNotFound: "Cet utilisateur n'existe pas"
authFailed: "Authentification échouée." authFailed: "Authentification échouée."
authFailedTips: "- Assurez-vous d'avoir enregistré un utilisateur avec :<b>'/plan register'.</b><br>- Vérifiez que le nom d'utilisateur et le mot de passe soient corrects.<br>- Le nom d'utilisateur et le mot de passe sont sensibles au format majuscule/minuscule.<br><br>Si vous avez oublié votre mot de passe, demandez à un membre du staff de supprimer votre ancien utilisateur puis de vous réinscrire." authFailedTips: "- Assurez-vous d'avoir enregistré un utilisateur avec :<b>'/plan register'.</b><br>- Vérifiez que le nom d'utilisateur et le mot de passe soient corrects.<br>- Le nom d'utilisateur et le mot de passe sont sensibles au format majuscule/minuscule.<br><br>Si vous avez oublié votre mot de passe, demandez à un membre du staff de supprimer votre ancien utilisateur puis de vous réinscrire."
noServersOnline: "Aucun serveur en ligne pour exécuter la demande." noServersOnline: "Aucun serveur en ligne pour exécuter la demande."
playerNotSeen: "Cet utilisateur ne s'est jamais connecté sur ce serveur." playerNotSeen: "Cet utilisateur ne s'est jamais connecté sur ce serveur."
serverNotExported: "Server doesn't exist, its data might not have been exported yet." serverNotExported: "Le serveur n'existe pas, ses données n'ont peut-être pas encore été exportées."
serverNotSeen: "Server doesn't exist" serverNotSeen: "Le serveur n'existe pas"
generic: generic:
none: "Vide" none: "Vide"
label: label:
active: "Actif" active: "Actif"
activePlaytime: "Temps Actif" activePlaytime: "Temps Actif"
activityIndex: "Indice d'Activité" activityIndex: "Indice d'Activité"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Temps AFK" afkTime: "Temps AFK"
all: "Tout" all: "Tout"
allTime: "Tout le Temps" allTime: "Tout le Temps"
allowed: "Allowed" allowed: "Autorisé"
allowlist: "Allowlist" allowlist: "Liste d'autorisés"
allowlistBounces: "Allowlist Bounces" allowlistBounces: "Rebonds de la liste d'autorisés"
alphabetical: "Alphabetical" alphabetical: "Alphabétique"
apply: "Apply" apply: "Appliquer"
asNumbers: "en Chiffres" asNumbers: "en Chiffres"
attempts: "Attempts" attempts: "Tentatives"
average: "Average first session length" average: "Durée moyenne de la première session"
averageActivePlaytime: "Temps Actif moyen" averageActivePlaytime: "Temps Actif moyen"
averageAfkTime: "Temps AFK moyen" averageAfkTime: "Temps AFK moyen"
averageChunks: "Quantité moyenne de Chunks" averageChunks: "Quantité moyenne de Chunks"
averageCpuUsage: "Average CPU Usage" averageCpuUsage: "Utilisation moyenne du CPU"
averageEntities: "Quantité moyenne d'Entités" averageEntities: "Quantité moyenne d'Entités"
averageKdr: "Ratio - Kills / Morts - moyen" averageKdr: "Ratio - Kills / Morts - moyen"
averageMobKdr: "Ratio - Kills / Morts - de Mobs moyen" averageMobKdr: "Ratio - Kills / Morts - de Mobs moyen"
averagePing: "Latence moyenne" averagePing: "Latence moyenne"
averagePlayers: "Average Players" averagePlayers: "Moyenne des joueurs"
averagePlaytime: "Temps de Jeu moyen" averagePlaytime: "Temps de Jeu moyen"
averageRamUsage: "Average RAM Usage" averageRamUsage: "Utilisation moyenne de la RAM"
averageServerDowntime: "Average Downtime / Server" averageServerDowntime: "Temps d'arrêt moyen par serveur"
averageSessionLength: "Durée moyenne d'une Session" averageSessionLength: "Durée moyenne d'une Session"
averageSessions: "Quantité moyenne de Sessions" averageSessions: "Quantité moyenne de Sessions"
averageTps: "TPS moyen" averageTps: "TPS moyen"
averageTps7days: "Average TPS (7 days)" averageTps7days: "TPS moyen (7 days)"
banned: "Banni(e)" banned: "Banni(e)"
bestPeak: "Pic maximal de Joueurs en Ligne" bestPeak: "Pic maximal de Joueurs en Ligne"
bestPing: "Meilleure Latence" bestPing: "Meilleure Latence"
blocked: "Blocked" blocked: "Bloqué"
calendar: " Calendrier" calendar: " Calendrier"
comparing7days: "Comparaison des 7 derniers Jours" comparing7days: "Comparaison des 7 derniers Jours"
connectionInfo: "Renseignements sur la Connexion" connectionInfo: "Renseignements sur la Connexion"
country: "Pays" country: "Pays"
cpu: "CPU" cpu: "CPU"
cpuRam: "CPU & RAM" cpuRam: "CPU & RAM"
cpuUsage: "CPU Usage" cpuUsage: "Utilisation du CPU"
currentPlayerbase: "Base de Joueurs actuelle" currentPlayerbase: "Base de Joueurs actuelle"
currentUptime: "Current Uptime" currentUptime: "Période d'activité actuelle"
currentlyInstalledPlugins: "Currently Installed Plugins" currentlyInstalledPlugins: "Plugins actuellement installés"
dayByDay: "Jour par Jour" dayByDay: "Jour par Jour"
dayOfweek: "Jour de la Semaine" dayOfweek: "Jour de la Semaine"
deadliestWeapon: "1ère Arme de Combat (la plus mortelle)" deadliestWeapon: "1ère Arme de Combat (la plus mortelle)"
deaths: "Morts" deaths: "Morts"
disk: "Espace Disque" disk: "Espace Disque"
diskSpace: "Espace Disque disponible" diskSpace: "Espace Disque disponible"
docs: "Swagger Docs" docs: "Docs Swagger"
downtime: "Temps Hors-Ligne" downtime: "Temps Hors-Ligne"
duringLowTps: "Pendant les pics de TPS bas :" duringLowTps: "Pendant les pics de TPS bas :"
entities: "Entités" entities: "Entités"
errors: "Plan Error Logs" errors: "Journaux d'erreurs de Plan"
export: "Export" export: "Exportation"
exported: "Data export time" exported: "Temps d'exportation des données"
favoriteServer: "Serveur Favori" favoriteServer: "Serveur Favori"
firstSession: "Première session" firstSession: "Première session"
firstSessionLength: firstSessionLength:
average: "Average first session length" average: "Durée moyenne de la première session"
median: "Median first session length" median: "Durée médiane de la première session"
geoProjection: geoProjection:
dropdown: "Select projection" dropdown: "Sélectionner la projection"
equalEarth: "Equal Earth" equalEarth: "Equal Earth"
mercator: "Mercator" mercator: "Mercator"
miller: "Miller" miller: "Miller"
ortographic: "Ortographic" ortographic: "Ortographique"
geolocations: "Géolocalisation" geolocations: "Géolocalisation"
groupPermissions: "Manage Groups" groupPermissions: "Gérer les groupes"
groupUsers: "Manage Group Users" groupUsers: "Gérer les utilisateurs d'un groupe"
help: help:
activityIndexBasis: "Activity index is based on non-AFK playtime in the past 3 weeks (21 days). Each week is considered separately." activityIndexBasis: "L'indice d'activité est basé sur le temps de jeu non-AFK au cours des 3 dernières semaines (21 jours). Chaque semaine est considérée séparément."
activityIndexExample1: "If someone plays as much as threshold every week, they are given activity index ~3." activityIndexExample1: "Si une personne joue autant que le seuil fixé chaque semaine, elle se voit attribuer un indice d'activité de ~3."
activityIndexExample2: "Very active is ~2x the threshold (y ≥ 3.75)." activityIndexExample2: "Très actif est ~2x le seuil (y ≥ 3,75)."
activityIndexExample3: "The index approaches 5 indefinitely." activityIndexExample3: "L'indice se rapproche indéfiniment de 5."
activityIndexVisual: "Here is a visualization of the curve where y = activity index, and x = playtime per week / threshold." activityIndexVisual: "Voici une visualisation de la courbe où y = indice d'activité, et x = temps de jeu par semaine / seuil."
activityIndexWeek: "Week {}" activityIndexWeek: "Semaine {}"
examples: "Examples" examples: "Exemples"
graph: graph:
labels: "You can hide/show a group by clicking on the label at the bottom." labels: "Vous pouvez masquer/afficher un groupe en cliquant sur l'étiquette en bas de page."
title: "Graph" title: "Graphique"
zoom: "You can Zoom in by click + dragging on the graph." zoom: "Vous pouvez zoomer en cliquant sur le graphique et en le faisant glisser."
manage: manage:
groups: groups:
line-1: "This view allows you to modify web group permissions." line-1: "Cette vue vous permet de modifier les autorisations des groupes web."
line-10: "<1>{{permission}}</> permissions determine what parts of the page are visible. These permissions also limit requests to the related data endpoints." line-10: "<1>{{permission}}</> déterminent quelles parties de la page sont visibles. Ces autorisations limitent également les requêtes vers les points d'accès aux données connexes."
line-11: "<1>{{permission1}}</1> permissions are not required for data: <2>{{permission2}}</2> allows request to /v1/network/overview even without <3>{{permission3}}</3>." line-11: "<1>{{permission1}}</1> ne sont pas nécessaires pour les données: <2>{{permission2}}</2> permet de faire une requête à /v1/network/overview même sans <3>{{permission3}}</3>."
line-12: "Saving changes" line-12: "Sauvegarder les modifications"
line-13: "When you add a group or delete a group that action is saved immediately after confirm (no undo)." line-13: "Lorsque vous ajoutez ou supprimez un groupe, l'action est sauvegardée immédiatement après confirmation (pas d'annulation)."
line-14: "When you modify permissions those changes need to be saved by pressing the Save-button" line-14: "Lorsque vous modifiez les autorisations, ces changements doivent être enregistrés en cliquant sur le bouton Enregistrer."
line-15: "Documentation can be found from <1>{{link}}</1>" line-15: "La documentation est disponible à l'adresse suivante <1>{{link}}</1>"
line-2: "User's web group is determined during <1>{{command}}</1> by checking if Player has <2>{{permission}}</2> permission." line-2: "Le groupe web de l'utilisateur est déterminé pendant <1>{{command}}</1> en vérifiant si le joueur a la permission <2>{{permission}}</2>."
line-3: "You can use <1>{{command}}</1> to change permission group after registering." line-3: "Vous pouvez utiliser <1>{{command}}</1> pour changer de groupe d'autorisation après l'enregistrement."
line-4: "<1>{{icon}}</1> If you ever accidentally delete all groups with <2>{{permission}}</2> permission just <3>{{command}}</3>." line-4: "<1>{{icon}}</1> Si vous supprimez accidentellement tous les groupes avec la permission <2>{{permission}}</2> utilisez juste <3>{{command}}</3>."
line-5: "Permission inheritance" line-5: "Héritage de permissions"
line-6: "Permissions follow inheritance model, where higher level permission grants all lower ones, eg. <1>{{permission1}}</1> also gives <2>{{permission2}}</2>, etc." line-6: "Les autorisations suivent le modèle de l'héritage, où l'autorisation de niveau supérieur accorde toutes les autorisations de niveau inférieur, par exemple. <1>{{permission1}}</1> donne également <2>{{permission2}}</2>, etc."
line-7: "Access vs Page -permissions" line-7: "Accès vs. Permissions d'accès aux pages"
line-8: "You need to assign both access and page permissions for users." line-8: "Vous devez attribuer des droits d'accès et des droits de page aux utilisateurs."
line-9: "<1>{{permission1}}</1> permissions allow user make the request to specific address, eg. <2>{{permission2}}</2> allows request to /network." line-9: "<1>{{permission1}}</1> les autorisations permettent à l'utilisateur d'adresser une demande à une adresse spécifique, par exemple. <2>{{permission2}}</2> permet de faire une requête à /network."
playtimeUnit: "hours" playtimeUnit: "heures"
retention: retention:
calculationStep1: "First the data is filtered using '<>' option. Any players with 'registerDate' outside the time range are ignored." calculationStep1: "Les données sont d'abord filtrées à l'aide de l'option '<>'. Tous les joueurs avec 'registerDate' en dehors de l'intervalle de temps sont ignorés."
calculationStep2: "Then it is grouped into groups of players using '<0>' option, eg. With '<1>': All players who registered in January 2023, February 2023, etc" calculationStep2: "Il est ensuite réparti en groupes de joueurs à l'aide de l'option '<0>', par exemple. Avec '<1>': Tous les joueurs qui se sont inscrits en janvier 2023, février 2023, etc."
calculationStep3: "Then the '<0>' and '<1>' options select which visualization to render." calculationStep3: "Les options '<0>' et '<1>' permettent ensuite de sélectionner la visualisation à restituer."
calculationStep4: "'<>' controls how many points the graph has, eg. 'Days' has one point per day." calculationStep4: "'<>' détermine le nombre de points du graphique, par exemple 'Jours' correspond à un point par jour."
calculationStep5: "On each calculated point all players are checked for the condition." calculationStep5: "A chaque point calculé, tous les joueurs sont contrôlés pour la condition."
calculationStep6: "Select X Axis below to see conditions." calculationStep6: "Sélectionnez l'axe X ci-dessous pour voir les conditions."
calculationStepDate: "This visualization shows the different groups of players that are still playing on your server. The visualization uses lastSeen date. If x < lastSeenDate, the player is visible on the graph." calculationStepDate: "Cette visualisation montre les différents groupes de joueurs qui jouent encore sur votre serveur. La visualisation utilise la date lastSeen. Si x < lastSeenDate, le joueur est visible sur le graphique."
calculationStepDeltas: "This visualization is most effective using Player Count as the Y Axis. The visualization shows net gain of players (How many players joined minus players who stopped playing). The visualization uses both registered and lastSeen dates. If registerDate < x < lastSeenDate, the player is visible on the graph." calculationStepDeltas: "Cette visualisation est plus efficace si l'on utilise le nombre de joueurs comme axe des ordonnées. La visualisation montre le gain net de joueurs (combien de joueurs se sont inscrits moins les joueurs qui ont arrêté de jouer). La visualisation utilise les dates d'inscription et de dernière visite. Si registerDate < x < lastSeenDate, le joueur est visible sur le graphique."
calculationStepPlaytime: "This visualization tells how long the gameplay loop keeps players engaged on your server. The visualization uses playtime. If x < playtime, the player is visible on the graph." calculationStepPlaytime: "Cette visualisation indique combien de temps la boucle de gameplay maintient l'attention des joueurs sur votre serveur. La visualisation utilise le temps de jeu. Si x < temps de jeu, le joueur est visible sur le graphique."
calculationStepTime: "This visualization tells how long people keep coming back to play on the server after they join the first time. The visualization uses timeDifference. If x < timeDifference, the player is visible on the graph." calculationStepTime: "Cette visualisation indique combien de temps les gens reviennent jouer sur le serveur après leur première inscription. La visualisation utilise timeDifference. Si x < timeDifference, le joueur est visible sur le graphique."
compareJoinAddress: "Grouping by join address allows measuring advertising campaigns on different sites." compareJoinAddress: "Le regroupement par adresse de jointure permet de mesurer les campagnes publicitaires sur différents sites."
compareMonths: "You can compare different months by changing the '<0>' option to '<1>'" compareMonths: "Vous pouvez comparer plusieurs mois en remplaçant l'option '<0>' par '<1>'"
examples: examples:
adCampaign: "Comparing player gain of different ad campaigns using different Join Addresses (anonymized)" adCampaign: "Comparaison des gains de joueurs de différentes campagnes publicitaires utilisant différentes adresses de jointure (anonymisées)"
deltas: "<> shows net gain of players." deltas: "<> indique le gain net de joueurs."
pattern: "A general pattern emerges when all players start leaving the server at the same time" pattern: "Un schéma général se dessine lorsque tous les joueurs commencent à quitter le serveur en même temps"
plateau: "Comparing player gain of different months. Plateaus suggest there were players Plan doesn't know about. In this example Plan was installed in January 2022." plateau: "Comparaison des gains de joueurs au cours des différents mois. Les plateaux suggèrent qu'il y a des joueurs dont Plan n'a pas connaissance. Dans cet exemple, Plan a été installé en janvier 2022."
playtime: "Playtime tells how long the gameplay loop keeps players engaged on your server." playtime: "Le temps de jeu indique combien de temps la boucle de gameplay maintient l'attention des joueurs sur votre serveur."
stack: "Cumulative player gain can be checked with stacked player count as Y axis" stack: "Le gain cumulatif de joueurs peut être vérifié en utilisant le nombre de joueurs empilés comme axe Y."
howIsItCalculated: "How it is calculated" howIsItCalculated: "Mode de calcul"
howIsItCalculatedData: "The graph is generated from player data:" howIsItCalculatedData: "Le graphique est généré à partir des données des joueurs:"
options: "Select the options to analyze different aspects of Player Retention." options: "Sélectionnez les options pour analyser les différents aspects de la fidélisation des joueurs."
retentionBasis: "New player retention is calculated based on session data. If a registered player has played within latter half of the timespan, they are considered retained." retentionBasis: "La fidélisation des nouveaux joueurs est calculée sur la base des données de session. Si un joueur enregistré a joué dans la seconde moitié de la période, il est considéré comme fidélisé."
testPrompt: "Test it out:" testPrompt: "Testez-le:"
testResult: "Test result" testResult: "Résultat du test"
threshold: "Threshold" threshold: "Seuil"
thresholdUnit: "hours / week" thresholdUnit: "heures / semaine"
tips: "Tips" tips: "Conseils"
usingTheGraph: "Using the Graph" usingTheGraph: "Utilisation du graphique"
hourByHour: "Heure par Heure" hourByHour: "Heure par Heure"
inactive: "Inactif(ve)" inactive: "Inactif(ve)"
indexInactive: "Inactif" indexInactive: "Inactif"
indexRegular: "Régulier" indexRegular: "Régulier"
information: "INFORMATIONS" information: "INFORMATIONS"
insights: "Insights" insights: "Perspectives"
insights30days: "Perspectives sur 30 jours" insights30days: "Perspectives sur 30 jours"
installed: "Installed" installed: "Installé"
irregular: "Irrégulier" irregular: "Irrégulier"
joinAddress: "Join Address" joinAddress: "Adresse de Connexion"
joinAddresses: "Adresses de Connexion" joinAddresses: "Adresses de Connexion"
kdr: "KDR" kdr: "KDR"
killed: "Tué(e)" killed: "Tué(e)"
last24hours: "24 Dernières heures" last24hours: "24 Dernières heures"
last30days: "30 Derniers jours" last30days: "30 Derniers jours"
last7days: "7 Derniers jours" last7days: "7 Derniers jours"
lastAllowed: "Last Allowed" lastAllowed: "Dernier autorisé"
lastBlocked: "Last Blocked" lastBlocked: "Dernier bloqué"
lastConnected: "Dernier Connecté" lastConnected: "Dernier connecté"
lastKnownAttempt: "Last Known Attempt" lastKnownAttempt: "Dernière tentative connue"
lastPeak: "Dernier pic de Joueurs en Ligne" lastPeak: "Dernier pic de Joueurs en Ligne"
lastSeen: "Dernière Connexion" lastSeen: "Dernière Connexion"
latestJoinAddresses: "Latest Join Addresses" latestJoinAddresses: "Dernières adresses d'adhésion"
length: " Longueur" length: " Longueur"
links: "LIENS" links: "LIENS"
loadedChunks: "Chunks Chargés" loadedChunks: "Chunks Chargés"
@ -450,53 +452,53 @@ html:
loneNewbieJoins: "Connexions de Débutants Seuls" loneNewbieJoins: "Connexions de Débutants Seuls"
longestSession: "Session la plus Longue" longestSession: "Session la plus Longue"
lowTpsSpikes: "Pics de TPS bas" lowTpsSpikes: "Pics de TPS bas"
lowTpsSpikes7days: "Low TPS Spikes (7 days)" lowTpsSpikes7days: "Pics de TPS bas (7 jours)"
manage: "Manage" manage: "Gérer"
managePage: managePage:
addGroup: addGroup:
header: "Add group" header: "Ajouter un groupe"
invalidName: "Group name can be 100 characters maximum." invalidName: "Le nom du groupe peut comporter 100 caractères au maximum."
name: "Name of the group" name: "Nom du groupe"
alert: alert:
groupAddFail: "Failed to add group: {{error}}" groupAddFail: "Échec de l'ajout d'un groupe: {{error}}"
groupAddSuccess: "Added group '{{groupName}}'" groupAddSuccess: "Groupe ajouté '{{groupName}}'"
groupDeleteFail: "Failed to delete group: {{error}}" groupDeleteFail: "Échec de la suppression du groupe: {{error}}"
groupDeleteSuccess: "Deleted group '{{groupName}}'" groupDeleteSuccess: "Groupe supprimé '{{groupName}}'"
saveFail: "Failed to save changes: {{error}}" saveFail: "Échec de l'enregistrement des modifications: {{error}}"
saveSuccess: "Changes saved successfully!" saveSuccess: "Les modifications ont été enregistrées avec succès!"
changes: changes:
discard: "Discard Changes" discard: "Rejeter les modifications"
save: "Save" save: "Sauvegarder"
unsaved: "Unsaved changes" unsaved: "Modifications non sauvegardées"
deleteGroup: deleteGroup:
confirm: "Confirm & Delete {{groupName}}" confirm: "Confirmer et supprimer {{groupName}}"
confirmDescription: "This will move all users of '{{groupName}}' to group '{{moveTo}}'. There is no undo!" confirmDescription: "Cette action déplacera tous les utilisateurs de '{{nomdugroupe}}' vers le groupe '{{moveTo}}'. Il n'y a pas d'annulation possible !"
header: "Delete '{{groupName}}'" header: "Supprimer '{{groupName}}'"
moveToSelect: "Move remaining users to group" moveToSelect: "Déplacer les utilisateurs restants vers le groupe"
groupHeader: "Manage Group Permissions" groupHeader: "Gérer les permissions du groupe"
groupPermissions: "Permissions of {{groupName}}" groupPermissions: "Permissions de {{groupName}}"
maxFreeDisk: "Espace Disque MAX disponible" maxFreeDisk: "Espace Disque MAX disponible"
medianSessionLength: "Median Session Length" medianSessionLength: "Durée médiane de la session"
minFreeDisk: "Espace Disque MIN disponible" minFreeDisk: "Espace Disque MIN disponible"
mobDeaths: "Morts causées par un Mob" mobDeaths: "Morts causées par un Mob"
mobKdr: "Ratio - Kills / Morts de Mobs -" mobKdr: "Ratio - Kills / Morts de Mobs -"
mobKills: "Kills de Mobs" mobKills: "Mobs Tués"
modified: "Modified" modified: "Modifié"
mostActiveGamemode: "Mode de Jeu le plus utilisé" mostActiveGamemode: "Mode de Jeu le plus utilisé"
mostPlayedWorld: "Monde le plus Fréquenté" mostPlayedWorld: "Monde le plus Fréquenté"
name: "Nom" name: "Nom"
network: "Réseau" network: "Réseau"
networkAsNumbers: "Réseau en Chiffres" networkAsNumbers: "Réseau en Chiffres"
networkCalendar: "Network Calendar" networkCalendar: "Calendrier du réseau"
networkOnlineActivity: "Activité en Ligne du Réseau" networkOnlineActivity: "Activité en Ligne du Réseau"
networkOverview: "Aperçu du Réseau" networkOverview: "Aperçu du Réseau"
networkPage: "Page du Réseau" networkPage: "Page du Réseau"
new: "Nouveau(elle)" new: "Nouveau(elle)"
newPlayerRetention: "Rétention des nouveaux Joueurs" newPlayerRetention: "Rétention des nouveaux Joueurs"
newPlayers: "Nouveaux Joueurs" newPlayers: "Nouveaux Joueurs"
newPlayers7days: "New Players (7 days)" newPlayers7days: "Nouveaux joueurs (7 jours)"
nickname: "Surnom" nickname: "Surnom"
noDataToDisplay: "No Data to Display" noDataToDisplay: "Pas de données à afficher"
now: "Maintenant" now: "Maintenant"
onlineActivity: "Activité en ligne" onlineActivity: "Activité en ligne"
onlineActivityAsNumbers: "Activité en ligne en Chiffres" onlineActivityAsNumbers: "Activité en ligne en Chiffres"
@ -512,23 +514,23 @@ html:
player: "Joueur" player: "Joueur"
playerDeaths: "Décès causés par le Joueur" playerDeaths: "Décès causés par le Joueur"
playerKills: "Kills de Joueurs" playerKills: "Kills de Joueurs"
playerKillsVictimIndicator: "Player was killed within 24h of first time they were seen (Time since registered: <>)." playerKillsVictimIndicator: "Le joueur a été tué dans les 24 heures suivant sa première apparition (Temps écoulé depuis l'enregistrement : <>)."
playerList: "Liste des Joueurs" playerList: "Liste des Joueurs"
playerOverview: "Aperçu des Joueurs" playerOverview: "Aperçu des Joueurs"
playerPage: "Page du Joueur" playerPage: "Page du Joueur"
playerRetention: "Player Retention" playerRetention: "Fidélisation des joueurs"
playerbase: "Base de Joueurs" playerbase: "Base de Joueurs"
playerbaseDevelopment: "Évolution de la base de Joueurs" playerbaseDevelopment: "Évolution de la base de Joueurs"
playerbaseOverview: "Playerbase Overview" playerbaseOverview: "Aperçu de la base de joueurs"
players: "Joueurs" players: "Joueurs"
playersOnline: "Joueurs en Ligne" playersOnline: "Joueurs en Ligne"
playersOnlineNow: "Players Online (Now)" playersOnlineNow: "Joueurs en ligne (maintenant)"
playersOnlineOverview: "Aperçu de l'Activité en Ligne" playersOnlineOverview: "Aperçu de l'Activité en Ligne"
playtime: "Temps de Jeu" playtime: "Temps de Jeu"
pluginHistory: "Plugin History" pluginHistory: "Historique des plugins"
pluginVersionHistory: "Plugin Version History" pluginVersionHistory: "Historique de la version du plugin"
plugins: "Plugins" plugins: "Plugins"
pluginsOverview: "Plugins Overview" pluginsOverview: "Aperçu des plugins"
punchcard: "Carte Perforée" punchcard: "Carte Perforée"
punchcard30days: "Carte perforée sur 30 jours" punchcard30days: "Carte perforée sur 30 jours"
pvpPve: "PvP & PvE" pvpPve: "PvP & PvE"
@ -547,19 +549,19 @@ html:
regularPlayers: "Joueurs Réguliers" regularPlayers: "Joueurs Réguliers"
relativeJoinActivity: "Activité de Connexion relative" relativeJoinActivity: "Activité de Connexion relative"
retention: retention:
groupByNone: "No grouping" groupByNone: "Pas de regroupement"
groupByTime: "Group registered by" groupByTime: "Groupe enregistré par"
inAnytime: "any time" inAnytime: "à tout moment"
inLast180d: "in the last 6 months" inLast180d: "au cours des 6 derniers mois"
inLast30d: "in the last 30 days" inLast30d: "au cours des 30 derniers jours"
inLast365d: "in the last 12 months" inLast365d: "au cours des 12 derniers mois"
inLast730d: "in the last 24 months" inLast730d: "au cours des 24 derniers mois"
inLast7d: "in the last 7 days" inLast7d: "au cours des 7 derniers jours"
inLast90d: "in the last 3 months" inLast90d: "au cours des 3 derniers mois"
playersRegisteredInTime: "Players who registered" playersRegisteredInTime: "Joueurs inscrits"
retainedPlayersPercentage: "Retained Players %" retainedPlayersPercentage: "Joueurs retenus %"
timeSinceRegistered: "Time since register date" timeSinceRegistered: "Temps écoulé depuis la date d'enregistrement"
timeStep: "Time step" timeStep: "Pas de temps"
secondDeadliestWeapon: "2ᵉ Arme de Combat" secondDeadliestWeapon: "2ᵉ Arme de Combat"
seenNicknames: "Surnoms vus" seenNicknames: "Surnoms vus"
server: "Serveur" server: "Serveur"
@ -582,26 +584,26 @@ html:
sessionMedian: "Session Médiane" sessionMedian: "Session Médiane"
sessionStart: "Début de la Session" sessionStart: "Début de la Session"
sessions: "Sessions" sessions: "Sessions"
sortBy: "Sort By" sortBy: "Trier par"
stacked: "Stacked" stacked: "Empilés"
table: table:
showNofM: "Showing {{n}} of {{m}} entries" showNofM: "Afficher {{n}} de {{m}} entrées"
showPerPage: "Show per page" showPerPage: "Afficher par page"
visibleColumns: "Visible columns" visibleColumns: "Colonnes visibles"
themeSelect: "Sélection du Thème" themeSelect: "Sélection du Thème"
thirdDeadliestWeapon: "3ᵉ Arme de Combat" thirdDeadliestWeapon: "3ᵉ Arme de Combat"
thirtyDays: "30 jours" thirtyDays: "30 jours"
thirtyDaysAgo: "Il y a 30 jours" thirtyDaysAgo: "Il y a 30 jours"
time: time:
date: "Date" date: "Date"
day: "Day" day: "Jour"
days: "Days" days: "Jours"
hours: "Hours" hours: "Heures"
month: "Month" month: "Mois"
months: "Months" months: "Mois"
week: "Week" week: "Semaine"
weeks: "Weeks" weeks: "Seamines"
year: "Year" year: "Année"
timesKicked: "Nombre d'Éjections" timesKicked: "Nombre d'Éjections"
toMainPage: "Retour à la page principale" toMainPage: "Retour à la page principale"
total: "Total" total: "Total"
@ -610,17 +612,17 @@ html:
totalPlayers: "Joueurs Totaux" totalPlayers: "Joueurs Totaux"
totalPlayersOld: "Joueurs Totaux" totalPlayersOld: "Joueurs Totaux"
totalPlaytime: "Temps de Jeu Total" totalPlaytime: "Temps de Jeu Total"
totalServerDowntime: "Total Server Downtime" totalServerDowntime: "Temps d'arrêt total du serveur"
tps: "TPS" tps: "TPS"
trend: "Tendances" trend: "Tendances"
trends30days: "Tendances sur 30 Jours" trends30days: "Tendances sur 30 Jours"
uninstalled: "Uninstalled" uninstalled: "Désinstallé"
uniquePlayers: "Joueurs Uniques" uniquePlayers: "Joueurs Uniques"
uniquePlayers7days: "Unique Players (7 days)" uniquePlayers7days: "Joueurs uniques (7 jours)"
unit: unit:
percentage: "Percentage" percentage: "Pourcentage"
playerCount: "Player Count" playerCount: "Nombre de joueurs"
users: "Manage Users" users: "Gérer les utilisateurs"
version: "Version" version: "Version"
veryActive: "Très Actif" veryActive: "Très Actif"
weekComparison: "Comparaison Hebdomadaire" weekComparison: "Comparaison Hebdomadaire"
@ -645,90 +647,88 @@ html:
manage: manage:
permission: permission:
description: description:
access: "Controls access to pages" access: "Contrôle de l'accès aux pages"
access_docs: "Allows accessing /docs page" access_docs: "Permet d'accéder à la page /docs"
access_errors: "Allows accessing /errors page" access_errors: "Permet d'accéder à la page /erreurs"
access_network: "Allows accessing /network page" access_network: "Permet d'accéder à la page /réseau"
access_player: "Allows accessing any /player pages" access_player: "Permet d'accéder à toutes les pages /player"
access_player_self: "Allows accessing own /player page" access_player_self: "Permet d'accéder à sa propre page /joueur"
access_players: "Allows accessing /players page" access_players: "Permet d'accéder à la page /joueurs"
access_query: "Allows accessing /query and Query results pages" access_query: "Permet d'accéder aux pages /query et Query results"
access_raw_player_data: "Allows accessing /player/{uuid}/raw json data. Follows 'access.player' permissions." access_raw_player_data: "Permet d'accéder aux données json brutes de /player/{uuid}. Suit les permissions 'access.player'."
access_server: "Allows accessing all /server pages" access_server: "Permet d'accéder à toutes les pages /server"
manage_groups: "Allows modifying group permissions & Access to /manage/groups page" manage_groups: "Permet de modifier les permissions des groupes et d'accéder à la page /manage/groups"
manage_users: "Allows modifying what users belong to what group" manage_users: "Permet de modifier quels utilisateurs appartiennent à quel groupe"
page: "Controls what is visible on pages" page: "Contrôle ce qui est visible sur les pages"
page_network: "See all of network page" page_network: "Voir toute la page du réseau"
page_network_geolocations: "See Geolocations tab" page_network_geolocations: "Voir l'onglet Géolocalisations"
page_network_geolocations_map: "See Geolocations Map" page_network_geolocations_map: "Voir la carte des géolocalisations"
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "Voir le tableau Ping par pays"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "Voir les adresses de jointure -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "Voir les graphiques de l'adresse de jonction"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph" page_network_join_addresses_graphs_time: "Voir le graphique des adresses de jointure dans le temps"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_overview: "Voir Aperçu du réseau -tab"
page_network_overview: "See Network Overview -tab" page_network_overview_graphs: "Voir les graphiques de l'aperçu du réseau"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs_calendar: "Voir le calendrier du réseau"
page_network_overview_graphs_calendar: "See Network calendar" page_network_overview_graphs_day_by_day: "Voir le graphique jour par jour"
page_network_overview_graphs_day_by_day: "See Day by Day graph" page_network_overview_graphs_hour_by_hour: "Voir le graphique heure par heure"
page_network_overview_graphs_hour_by_hour: "See Hour by Hour graph" page_network_overview_graphs_online: "Voir le graphique des joueurs en ligne"
page_network_overview_graphs_online: "See Players Online graph" page_network_overview_numbers: "Voir les numéros de l'aperçu du réseau"
page_network_overview_numbers: "See Network Overview numbers" page_network_performance: "Voir l'onglet Performances du réseau"
page_network_performance: "See network Performance tab" page_network_playerbase: "Voir l'onglet Aperçu de la base de joueurs"
page_network_playerbase: "See Playerbase Overview -tab" page_network_playerbase_graphs: "Voir les graphiques de la base de joueurs"
page_network_playerbase_graphs: "See Playerbase Overview graphs" page_network_playerbase_overview: "Voir les chiffres de l'aperçu de la base de joueurs"
page_network_playerbase_overview: "See Playerbase Overview numbers" page_network_players: "Voir la liste des lecteurs -tab"
page_network_players: "See Player list -tab" page_network_plugin_history: "Voir l'historique des plugins sur le réseau"
page_network_plugin_history: "See Plugin History across the network" page_network_plugins: "Voir l'onglet Plugins de Proxy"
page_network_plugins: "See Plugins tab of Proxy" page_network_retention: "Voir l'onglet Rétention des joueurs"
page_network_retention: "See Player Retention -tab" page_network_server_list: "Voir la liste des serveurs"
page_network_server_list: "See list of servers" page_network_sessions: "Voir l'onglet Sessions"
page_network_sessions: "See Sessions tab"
page_network_sessions_list: "See list of sessions" page_network_sessions_list: "See list of sessions"
page_network_sessions_overview: "See Session insights" page_network_sessions_overview: "Voir les perspectives de la session"
page_network_sessions_server_pie: "See Server Pie graph" page_network_sessions_server_pie: "Voir le graphique à secteurs du serveur"
page_network_sessions_world_pie: "See World Pie graph" page_network_sessions_world_pie: "Voir le graphique de la carte du monde"
page_player: "See all of player page" page_player: "Voir toute la page du joueur"
page_player_overview: "See Player Overview -tab" page_player_overview: "Voir l'aperçu des joueurs -tab"
page_player_plugins: "See Plugins -tabs" page_player_plugins: "Voir les plugins -tabs"
page_player_servers: "See Servers -tab" page_player_servers: "Voir les serveurs -tab"
page_player_sessions: "See Player Sessions -tab" page_player_sessions: "Voir les sessions des joueurs -tab"
page_player_versus: "See PvP & PvE -tab" page_player_versus: "Voir PvP & PvE -tab"
page_server: "See all of server page" page_server: "Voir toute la page du serveur"
page_server_allowlist_bounce: "See list of Game allowlist bounces" page_server_allowlist_bounce: "Voir la liste des rebonds de Game allowlist"
page_server_geolocations: "See Geolocations tab" page_server_geolocations: "Voir l'onglet Géolocalisations"
page_server_geolocations_map: "See Geolocations Map" page_server_geolocations_map: "Voir la carte des géolocalisations"
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "Voir le tableau Ping par pays"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "Voir les adresses de jointure -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "Voir les graphiques de l'adresse de connexion"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph" page_server_join_addresses_graphs_time: "Voir le graphique des adresses de connexion dans le temps"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_online_activity: "Voir l'activité en ligne -tab"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity_graphs: "Voir les graphiques de l'activité en ligne"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs_calendar: "Voir Calendrier des serveurs"
page_server_online_activity_graphs_calendar: "See Server calendar" page_server_online_activity_graphs_day_by_day: "Voir le graphique jour par jour"
page_server_online_activity_graphs_day_by_day: "See Day by Day graph" page_server_online_activity_graphs_hour_by_hour: "Voir le graphique heure par heure"
page_server_online_activity_graphs_hour_by_hour: "See Hour by Hour graph" page_server_online_activity_graphs_punchcard: "Voir graphique Punchcard"
page_server_online_activity_graphs_punchcard: "See Punchcard graph" page_server_online_activity_overview: "Voir les numéros d'activité en ligne"
page_server_online_activity_overview: "See Online Activity numbers" page_server_overview: "Voir l'aperçu du serveur -tab"
page_server_overview: "See Server Overview -tab" page_server_overview_numbers: "Voir les numéros de la vue d'ensemble du serveur"
page_server_overview_numbers: "See Server Overview numbers" page_server_overview_players_online_graph: "Voir le graphique des joueurs en ligne"
page_server_overview_players_online_graph: "See Players Online graph" page_server_performance: "Voir l'onglet Performance"
page_server_performance: "See Performance tab" page_server_performance_graphs: "Voir les graphiques de performance"
page_server_performance_graphs: "See Performance graphs" page_server_performance_overview: "Voir les chiffres de performance"
page_server_performance_overview: "See Performance numbers" page_server_player_versus: "Voir PvP & PvE -tab"
page_server_player_versus: "See PvP & PvE -tab" page_server_player_versus_kill_list: "Voir Liste des joueurs tués ou morts"
page_server_player_versus_kill_list: "See Player kill and death lists" page_server_player_versus_overview: "Voir les chiffres de PvP & PvE"
page_server_player_versus_overview: "See PvP & PvE numbers" page_server_playerbase: "Voir l'aperçu de la base de joueurs -tab"
page_server_playerbase: "See Playerbase Overview -tab" page_server_playerbase_graphs: "Voir les graphiques de la base de joueurs"
page_server_playerbase_graphs: "See Playerbase Overview graphs" page_server_playerbase_overview: "Voir les chiffres de l'aperçu de la base de joueurs"
page_server_playerbase_overview: "See Playerbase Overview numbers" page_server_players: "Voir la liste des joueurs -tab"
page_server_players: "See Player list -tab" page_server_plugin_history: "Voir l'historique du plugin"
page_server_plugin_history: "See Plugin History" page_server_plugins: "Voir les onglets Plugins des serveurs"
page_server_plugins: "See Plugins -tabs of servers" page_server_retention: "Voir l'onglet Rétention des joueurs"
page_server_retention: "See Player Retention -tab" page_server_sessions: "Voir l'onglet Sessions"
page_server_sessions: "See Sessions tab" page_server_sessions_list: "Voir la liste des sessions"
page_server_sessions_list: "See list of sessions" page_server_sessions_overview: "Voir les perspectives de la session"
page_server_sessions_overview: "See Session insights" page_server_sessions_world_pie: "Voir le graphique de la carte du monde"
page_server_sessions_world_pie: "See World Pie graph"
modal: modal:
info: info:
bugs: "Rapport de bugs" bugs: "Rapport de bugs"
@ -759,17 +759,17 @@ html:
name: "Statut de Bannissement" name: "Statut de Bannissement"
banned: "Banni(e)" banned: "Banni(e)"
country: country:
text: "have joined from country" text: "a rejoint à partir du pays"
generic: generic:
allPlayers: "Tous les Joueurs" allPlayers: "Tous les Joueurs"
and: "et" and: "et"
start: "des Joueurs qui" start: "des Joueurs qui"
hasPlayedOnServers: hasPlayedOnServers:
name: "Has played on one of servers" name: "A joué sur l'un des serveurs"
text: "have played on at least one of" text: "A joué sur au moins un de"
hasPluginBooleanValue: hasPluginBooleanValue:
name: "Has plugin boolean value" name: "A la valeur booléenne du plugin"
text: "have Plugin boolean value" text: "avoir une valeur booléenne de plugin"
joinAddress: joinAddress:
text: "ont rejoint avec l'adresse" text: "ont rejoint avec l'adresse"
nonOperators: "Non Opérateur(trice)" nonOperators: "Non Opérateur(trice)"
@ -784,24 +784,25 @@ html:
text: "sont dans le groupe {group} de ${plugin}" text: "sont dans le groupe {group} de ${plugin}"
registeredBetween: registeredBetween:
text: "Enregistrés entre" text: "Enregistrés entre"
skipped: "Skipped" skipped: "Sautée"
title: title:
activityGroup: "Groupe d'Activité actuel" activityGroup: "Groupe d'Activité actuel"
view: " Vue :" view: " Vue :"
filters: filters:
add: "Ajouter un filtre.." add: "Ajouter un filtre."
loading: "Chargement des Filtres.." loading: "Chargement des Filtres."
generic: generic:
are: "`sont`" are: "`sont`"
label: label:
editQuery: "Edit Query"
from: ">de</label>" from: ">de</label>"
makeAnother: "Faire une autre Requête" makeAnother: "Faire une autre Requête"
servers: servers:
all: "using data of all servers" all: "en utilisant les données de tous les serveurs"
many: "using data of {number} servers" many: "en utilisant les données de {nombre} serveurs"
single: "using data of 1 server" single: "en utilisant les données d'un serveur"
two: "using data of 2 servers" two: "en utilisant les données de 2 serveurs"
showFullQuery: "Show Full Query" showFullQuery: "Afficher la requête complète"
to: ">à</label>" to: ">à</label>"
view: "Visualiser une vue" view: "Visualiser une vue"
performQuery: "Exécuter la Requête !" performQuery: "Exécuter la Requête !"
@ -821,7 +822,7 @@ html:
completion3: "Utilisez la commande suivante en jeu pour terminer l'enregistrement :" completion3: "Utilisez la commande suivante en jeu pour terminer l'enregistrement :"
completion4: "Ou en utilisant la console :" completion4: "Ou en utilisant la console :"
createNewUser: "Créer un nouvel utilisateur" createNewUser: "Créer un nouvel utilisateur"
disabled: "Registering new users has been disabled in the config." disabled: "L'enregistrement de nouveaux utilisateurs a été désactivé dans la configuration."
error: error:
checkFailed: "La vérification de l'état de l'enregistrement a échoué : " checkFailed: "La vérification de l'état de l'enregistrement a échoué : "
failed: "Enregistrement échoué : " failed: "Enregistrement échoué : "
@ -831,11 +832,11 @@ html:
login: "Vous avez déjà un compte ? Connectez-vous !" login: "Vous avez déjà un compte ? Connectez-vous !"
passwordTip: "Le Mot de Passe devrait comporter plus de 8 caractères, mais il n'y a aucune limite." passwordTip: "Le Mot de Passe devrait comporter plus de 8 caractères, mais il n'y a aucune limite."
register: "Enregistrer" register: "Enregistrer"
success: "Registered a new user successfully! You can now login." success: "Enregistrement réussi d'un nouvel utilisateur ! Vous pouvez maintenant vous connecter."
usernameTip: "Le Nom d'Utilisateur peut comporter jusqu'à 50 caractères." usernameTip: "Le Nom d'Utilisateur peut comporter jusqu'à 50 caractères."
text: text:
click: "Click for more" click: "Cliquez ici pour en savoir plus"
clickAndDrag: "Click and Drag for more" clickAndDrag: "Cliquer et faire glisser pour en savoir plus"
clickToExpand: "Cliquez pour agrandir" clickToExpand: "Cliquez pour agrandir"
comparing15days: "Comparaison des 15 derniers Jours" comparing15days: "Comparaison des 15 derniers Jours"
comparing30daysAgo: "Comparaison des 60 derniers Jours" comparing30daysAgo: "Comparaison des 60 derniers Jours"
@ -866,11 +867,11 @@ plugin:
database: "Traitement des tâches critiques inachevées... (${0})" database: "Traitement des tâches critiques inachevées... (${0})"
disabled: "Plan a été désactivé." disabled: "Plan a été désactivé."
processingComplete: "Traitement complété." processingComplete: "Traitement complété."
savingSessions: "Sauvegarde des sessions inachevées..." savingSessions: "Sauvegarde des sessions inachevées."
savingSessionsTimeout: "Timeout atteint - stockage des sessions non terminées lors du prochain démarrage." savingSessionsTimeout: "Timeout atteint - stockage des sessions non terminées lors du prochain démarrage."
waitingDb: "En attente de la finalisation des requêtes pour éviter que SQLite ne plante la JVM.." waitingDb: "En attente de la finalisation des requêtes pour éviter que SQLite ne plante la JVM."
waitingDbComplete: "Connexion SQLite fermée." waitingDbComplete: "Connexion SQLite fermée."
waitingTransactions: "En attente des transactions non terminées pour éviter la perte de données.." waitingTransactions: "En attente des transactions non terminées pour éviter la perte de données."
waitingTransactionsComplete: "File d'attente des transactions fermée." waitingTransactionsComplete: "File d'attente des transactions fermée."
webserver: "Le serveur Web a été désactivé." webserver: "Le serveur Web a été désactivé."
enable: enable:
@ -887,9 +888,9 @@ plugin:
emptyIP: "L'adresse IP située dans le fichier 'server.properties' est vide et l'option 'Alternative_IP' n'est pas utilisée. Attention, des liens incorrects seront donnés !" emptyIP: "L'adresse IP située dans le fichier 'server.properties' est vide et l'option 'Alternative_IP' n'est pas utilisée. Attention, des liens incorrects seront donnés !"
geoDisabled: "La Géolocalisation n'est pas active. (Data.Geolocations: false)" geoDisabled: "La Géolocalisation n'est pas active. (Data.Geolocations: false)"
geoInternetRequired: "Plan nécessite un accès à Internet lors de sa première utilisation pour télécharger la base de données 'GeoLite2 Geolocation'." geoInternetRequired: "Plan nécessite un accès à Internet lors de sa première utilisation pour télécharger la base de données 'GeoLite2 Geolocation'."
proxyAddress: "Proxy server detected in the database - Proxy Webserver address is '${0}'." proxyAddress: "Serveur proxy détecté dans la base de données - L'adresse du serveur web proxy est '${0}'."
proxyDisabledWebserver: "Disabling Webserver on this server - You can override this behavior by setting '${0}' to false." proxyDisabledWebserver: "Désactivation du serveur web sur ce serveur - Vous pouvez ignorer ce comportement en réglant '${0}' sur false."
settingChange: "Note: Set '${0}' to ${1}" settingChange: "Note : Réglez '${0}' sur ${1}."
storeSessions: "Stockage des sessions ayant été préservées lors de l'arrêt précédent." storeSessions: "Stockage des sessions ayant été préservées lors de l'arrêt précédent."
webserverDisabled: "Le serveur Web n'a pas été initialisé. (WebServer.DisableWebServer: true)" webserverDisabled: "Le serveur Web n'a pas été initialisé. (WebServer.DisableWebServer: true)"
webserver: "Le serveur Web communique à travers le port ${0} ( ${1} )." webserver: "Le serveur Web communique à travers le port ${0} ( ${1} )."
@ -900,16 +901,16 @@ plugin:
dbNotifySQLiteWAL: "Le mode WAL de SQLite n'est pas pris en charge sur cette version du serveur, en utilisant le mode par défaut. Cela peut possiblement affecter les performances." dbNotifySQLiteWAL: "Le mode WAL de SQLite n'est pas pris en charge sur cette version du serveur, en utilisant le mode par défaut. Cela peut possiblement affecter les performances."
dbPatchesAlreadyApplied: "Tous les correctifs pour la base de données ont déjà été appliqués." dbPatchesAlreadyApplied: "Tous les correctifs pour la base de données ont déjà été appliqués."
dbPatchesApplied: "Tous les correctifs pour la base de données ont été appliqués avec succès." dbPatchesApplied: "Tous les correctifs pour la base de données ont été appliqués avec succès."
dbSchemaPatch: "Database: Making sure schema is up to date.." dbSchemaPatch: "Base de données : S'assurer que le schéma est à jour."
loadedServerInfo: "Server identifier loaded: ${0}" loadedServerInfo: "Identifiant de serveur chargé : ${0}"
loadingServerInfo: "Loading server identifying information" loadingServerInfo: "Chargement des informations d'identification du serveur"
no: "Non" no: "Non"
today: "'Aujourd''hui'" today: "Aujourd'hui"
unavailable: "Indisponible" unavailable: "Indisponible"
unknown: "Inconnu" unknown: "Inconnu"
yes: "Oui" yes: "Oui"
yesterday: "'Hier'" yesterday: "'Hier'"
localeReloaded: "Custom locale.yml was modified so it was reloaded and is now in use." localeReloaded: "Le fichier locale.yml personnalisé a été modifié, il a donc été rechargé et est maintenant utilisé."
version: version:
checkFail: "Impossible de vérifier le dernier numéro de la version" checkFail: "Impossible de vérifier le dernier numéro de la version"
checkFailGithub: "Les informations de la version n'ont pas pu être chargées depuis Github/versions.txt" checkFailGithub: "Les informations de la version n'ont pas pu être chargées depuis Github/versions.txt"
@ -926,10 +927,10 @@ plugin:
notify: notify:
authDisabledConfig: "Serveur Web : Authentification d'utilisateur désactivée ! (dans la configuration)" authDisabledConfig: "Serveur Web : Authentification d'utilisateur désactivée ! (dans la configuration)"
authDisabledNoHTTPS: "Serveur Web : Authentification utilisateur désactivée ! (Non sécurisée avec HTTP)" authDisabledNoHTTPS: "Serveur Web : Authentification utilisateur désactivée ! (Non sécurisée avec HTTP)"
certificateExpiresOn: "Webserver: Loaded certificate is valid until ${0}." certificateExpiresOn: "Webserver: Le certificat chargé est valable jusqu'à ${0}."
certificateExpiresPassed: "Webserver: Certificate has expired, consider renewing the certificate." certificateExpiresPassed: "Webserver: Le certificat a expiré, pensez à renouveler le certificat."
certificateExpiresSoon: "Webserver: Certificate expires in ${0}, consider renewing the certificate." certificateExpiresSoon: "Webserver: Le certificat expire dans ${0}, pensez à renouveler le certificat."
certificateNoSuchAlias: "Webserver: Certificate with alias '${0}' was not found inside the keystore file '${1}'." certificateNoSuchAlias: "Webserver: Le certificat avec l'alias '${0}' n'a pas été trouvé dans le fichier keystore '${1}'."
http: "Serveur Web : Aucun certificat -> Utilisation du serveur HTTP pour la visualisation." http: "Serveur Web : Aucun certificat -> Utilisation du serveur HTTP pour la visualisation."
ipWhitelist: "Serveur Web : La liste blanche d'adresses IP n'est pas activée." ipWhitelist: "Serveur Web : La liste blanche d'adresses IP n'est pas activée."
ipWhitelistBlock: "Serveur Web : ${0} n'a pas pu accéder à '${1}'. (pas sur la liste blanche)" ipWhitelistBlock: "Serveur Web : ${0} n'a pas pu accéder à '${1}'. (pas sur la liste blanche)"

View File

@ -290,6 +290,8 @@ html:
active: "Attivo" active: "Attivo"
activePlaytime: "Active Playtime" activePlaytime: "Active Playtime"
activityIndex: "Indice Inattività" activityIndex: "Indice Inattività"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Tempo AFK" afkTime: "Tempo AFK"
all: "Tutto" all: "Tutto"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">from</label>" from: ">from</label>"
makeAnother: "Make another query" makeAnother: "Make another query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "よくログインしている" active: "よくログインしている"
activePlaytime: "アクティブなプレイ時間" activePlaytime: "アクティブなプレイ時間"
activityIndex: "活動指数" activityIndex: "活動指数"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "離席" afk: "離席"
afkTime: "離席時間" afkTime: "離席時間"
all: "全て" all: "全て"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "国ごとのPing表を表示" page_network_geolocations_ping_per_country: "国ごとのPing表を表示"
page_network_join_addresses: "参加アドレスタブを表示" page_network_join_addresses: "参加アドレスタブを表示"
page_network_join_addresses_graphs: "参加アドレスのグラフを表示" page_network_join_addresses_graphs: "参加アドレスのグラフを表示"
page_network_join_addresses_graphs_pie: "最後に参加したアドレスのグラフを表示"
page_network_join_addresses_graphs_time: "参加アドレスの経時変化のグラフを表示" page_network_join_addresses_graphs_time: "参加アドレスの経時変化のグラフを表示"
page_network_overview: "ネットワークの概要タブを表示" page_network_overview: "ネットワークの概要タブを表示"
page_network_overview_graphs: "ネットワークの概要グラフを表示" page_network_overview_graphs: "ネットワークの概要グラフを表示"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "国ごとのPing表を表示" page_server_geolocations_ping_per_country: "国ごとのPing表を表示"
page_server_join_addresses: "参加アドレスタブを表示" page_server_join_addresses: "参加アドレスタブを表示"
page_server_join_addresses_graphs: "参加アドレスグラフを表示" page_server_join_addresses_graphs: "参加アドレスグラフを表示"
page_server_join_addresses_graphs_pie: "最後に参加したアドレスのグラフを表示"
page_server_join_addresses_graphs_time: "参加アドレスの経時変化のグラフを表示" page_server_join_addresses_graphs_time: "参加アドレスの経時変化のグラフを表示"
page_server_online_activity: "オンラインアクティビティタブを表示" page_server_online_activity: "オンラインアクティビティタブを表示"
page_server_online_activity_graphs: "オンラインアクティビティグラフを表示" page_server_online_activity_graphs: "オンラインアクティビティグラフを表示"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`それは`" are: "`それは`"
label: label:
editQuery: "Edit Query"
from: ">から</label>" from: ">から</label>"
makeAnother: "別のクエリを作る" makeAnother: "別のクエリを作る"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "활동적인" active: "활동적인"
activePlaytime: "Active Playtime" activePlaytime: "Active Playtime"
activityIndex: "활동 색인" activityIndex: "활동 색인"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK 시간" afkTime: "AFK 시간"
all: "모두" all: "모두"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">from</label>" from: ">from</label>"
makeAnother: "Make another query" makeAnother: "Make another query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Actief" active: "Actief"
activePlaytime: "Actieve Speeltijd" activePlaytime: "Actieve Speeltijd"
activityIndex: "Activiteitsindex" activityIndex: "Activiteitsindex"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK Tijd" afkTime: "AFK Tijd"
all: "Alle" all: "Alle"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`zijn`" are: "`zijn`"
label: label:
editQuery: "Edit Query"
from: ">van</label>" from: ">van</label>"
makeAnother: "Maak nog een query" makeAnother: "Maak nog een query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Ativo" active: "Ativo"
activePlaytime: "Active Playtime" activePlaytime: "Active Playtime"
activityIndex: "Índice de Atividade" activityIndex: "Índice de Atividade"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK Time" afkTime: "AFK Time"
all: "Todos" all: "Todos"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`are`" are: "`are`"
label: label:
editQuery: "Edit Query"
from: ">from</label>" from: ">from</label>"
makeAnother: "Make another query" makeAnother: "Make another query"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Активный" active: "Активный"
activePlaytime: "Активное время игры" activePlaytime: "Активное время игры"
activityIndex: "Индекс активности" activityIndex: "Индекс активности"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Время AFK" afkTime: "Время AFK"
all: "Все" all: "Все"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "``" are: "``"
label: label:
editQuery: "Edit Query"
from: ">с</label>" from: ">с</label>"
makeAnother: "Сделать другой запрос" makeAnother: "Сделать другой запрос"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Aktivite" active: "Aktivite"
activePlaytime: "Aktif Oyun Süresi" activePlaytime: "Aktif Oyun Süresi"
activityIndex: "Aktivite göstergesi" activityIndex: "Aktivite göstergesi"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "AFK Süresi" afkTime: "AFK Süresi"
all: "Tamamı" all: "Tamamı"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`vardır`" are: "`vardır`"
label: label:
editQuery: "Edit Query"
from: ">dan</label>" from: ">dan</label>"
makeAnother: "Başka bir sorgu yap" makeAnother: "Başka bir sorgu yap"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "Активний" active: "Активний"
activePlaytime: "Активний час гри" activePlaytime: "Активний час гри"
activityIndex: "Індекс активності" activityIndex: "Індекс активності"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "AFK" afk: "AFK"
afkTime: "Час AFK" afkTime: "Час AFK"
all: "Всі" all: "Всі"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "``" are: "``"
label: label:
editQuery: "Edit Query"
from: ">з</label>" from: ">з</label>"
makeAnother: "Зробити інший запит" makeAnother: "Зробити інший запит"
servers: servers:

View File

@ -290,6 +290,8 @@ html:
active: "活躍" active: "活躍"
activePlaytime: "活躍時間" activePlaytime: "活躍時間"
activityIndex: "活躍指數" activityIndex: "活躍指數"
addJoinAddressGroup: "Add address group"
addressGroup: "Address group {{n}}"
afk: "掛機" afk: "掛機"
afkTime: "掛機時間" afkTime: "掛機時間"
all: "全部" all: "全部"
@ -664,7 +666,6 @@ html:
page_network_geolocations_ping_per_country: "See Ping Per Country table" page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab" page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs" page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph" page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab" page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs" page_network_overview_graphs: "See Network Overview graphs"
@ -700,7 +701,6 @@ html:
page_server_geolocations_ping_per_country: "See Ping Per Country table" page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab" page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs" page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph" page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab" page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs" page_server_online_activity_graphs: "See Online Activity graphs"
@ -794,6 +794,7 @@ html:
generic: generic:
are: "`是`" are: "`是`"
label: label:
editQuery: "Edit Query"
from: ">從 </label>" from: ">從 </label>"
makeAnother: "進行另一個查詢" makeAnother: "進行另一個查詢"
servers: servers:

View File

@ -7,11 +7,11 @@
"proxy": "http://localhost:8800", "proxy": "http://localhost:8800",
"dependencies": { "dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@fortawesome/fontawesome-free": "^6.5.1", "@fortawesome/fontawesome-free": "^6.5.2",
"@fortawesome/fontawesome-svg-core": "^6.5.1", "@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.1", "@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@fullcalendar/bootstrap": "^6.1.11", "@fullcalendar/bootstrap": "^6.1.11",
"@fullcalendar/core": "^6.1.11", "@fullcalendar/core": "^6.1.11",
@ -20,28 +20,28 @@
"@fullcalendar/react": "^6.1.11", "@fullcalendar/react": "^6.1.11",
"@highcharts/map-collection": "^2.1.0", "@highcharts/map-collection": "^2.1.0",
"@testing-library/jest-dom": "^6.4.2", "@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1", "@testing-library/react": "^15.0.2",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"axios": "^1.6.7", "axios": "^1.6.8",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"export-to-csv": "^1.2.4", "export-to-csv": "^1.2.4",
"highcharts": "^10.3.3", "highcharts": "^10.3.3",
"i18next": "^23.10.0", "i18next": "^23.11.2",
"i18next-chained-backend": "^4.6.2", "i18next-chained-backend": "^4.6.2",
"i18next-http-backend": "^2.5.0", "i18next-http-backend": "^2.5.1",
"i18next-localstorage-backend": "^4.2.0", "i18next-localstorage-backend": "^4.2.0",
"masonry-layout": "^4.2.2", "masonry-layout": "^4.2.2",
"moment": "^2.30.1", "moment": "^2.30.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-bootstrap": "^2.10.1", "react-bootstrap": "^2.10.2",
"react-bootstrap-range-slider": "^3.0.8", "react-bootstrap-range-slider": "^3.0.8",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-i18next": "^14.1.0", "react-i18next": "^14.1.0",
"react-mcjsonchat": "^1.0.0", "react-mcjsonchat": "^1.0.0",
"react-router-dom": "6", "react-router-dom": "6",
"sass": "^1.71.1", "sass": "^1.75.0",
"source-map-explorer": "^2.5.2", "source-map-explorer": "^2.5.2",
"swagger-ui": "^5.11.10", "swagger-ui": "^5.16.1",
"web-vitals": "^3.0.2" "web-vitals": "^3.0.2"
}, },
"scripts": { "scripts": {
@ -69,6 +69,6 @@
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"vite": "^5.1.5" "vite": "^5.2.9"
} }
} }

View File

@ -3,13 +3,14 @@ import {useQueryResultContext} from "../../hooks/queryResultContext";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faFilter} from "@fortawesome/free-solid-svg-icons"; import {faFilter} from "@fortawesome/free-solid-svg-icons";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {Link} from "react-router-dom";
const QueryPath = () => { const QueryPath = ({newQuery}) => {
const {t} = useTranslation(); const {t} = useTranslation();
const {result} = useQueryResultContext(); const {result} = useQueryResultContext();
const hasResults = result && result.data; const hasResults = Boolean(result?.data);
const path = result?.path; const path = result?.path;
if (!path || !path.length) return <></>; if (!path?.length || (newQuery && hasResults)) return <></>;
const getReadableFilterName = kind => { const getReadableFilterName = kind => {
@ -48,6 +49,7 @@ const QueryPath = () => {
return ( return (
<aside id={"result-path"} className={"alert shadow " + (hasResults ? "alert-success" : "alert-warning")}> <aside id={"result-path"} className={"alert shadow " + (hasResults ? "alert-success" : "alert-warning")}>
{!newQuery && <Link className={"link float-end"} to={"/query/new"}>{t('html.query.label.editQuery')}</Link>}
{path.map((step, i) => <p key={step.kind + step.size} {path.map((step, i) => <p key={step.kind + step.size}
style={{marginBottom: 0, marginLeft: i * 0.7 + "rem"}}> style={{marginBottom: 0, marginLeft: i * 0.7 + "rem"}}>
<FontAwesomeIcon <FontAwesomeIcon

View File

@ -0,0 +1,66 @@
import {useTranslation} from "react-i18next";
import React, {useCallback, useEffect, useState} from "react";
import {Card, Form} from "react-bootstrap";
import CardHeader from "../CardHeader.jsx";
import {faCheck, faList, faPencil} from "@fortawesome/free-solid-svg-icons";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import MultiSelect from "../../input/MultiSelect.jsx";
import {faTrashAlt} from "@fortawesome/free-regular-svg-icons";
const AddressGroupCard = ({n, group, editGroup, allAddresses, remove}) => {
const {t} = useTranslation();
const [selectedIndexes, setSelectedIndexes] = useState([]);
const [editingName, setEditingName] = useState(false);
const [name, setName] = useState(group.name);
useEffect(() => {
if (!selectedIndexes.length && allAddresses?.length && group?.addresses?.length) {
setSelectedIndexes(group.addresses
.map(address => allAddresses.indexOf(address))
.filter(index => index !== -1)) // Make sure addresses are not selected that no longer exist
}
}, [selectedIndexes, group, allAddresses])
const applySelected = useCallback(() => {
editGroup({...group, addresses: allAddresses.filter((a, i) => selectedIndexes.includes(i))})
}, [editGroup, group, allAddresses, selectedIndexes]);
const editName = useCallback(newName => {
editGroup({...group, name: newName});
}, [editGroup, group]);
useEffect(() => {
if (!editingName && name !== group.name) editName(name);
}, [editName, editingName, name])
const selectedAddresses = allAddresses.filter((a, i) => selectedIndexes.includes(i));
const isUpToDate = !selectedIndexes.length || selectedAddresses.length === group.addresses.length && selectedAddresses.every((a, i) => a === group.addresses[i]);
return (
<Card>
<CardHeader icon={faList} color={"amber"} label={
editingName ?
<Form.Control
style={{position: "absolute", top: "0.5rem", left: "2.5rem", width: "calc(100% - 3rem)"}}
value={name}
onChange={e => setName(e.target.value)}/> : group.name
}>
<button
style={editingName ? {position: "absolute", right: "1rem", top: "1.2rem"} : {marginLeft: "0.5rem"}}
onClick={() => setEditingName(!editingName)}>
<FontAwesomeIcon icon={editingName ? faCheck : faPencil}/>
</button>
</CardHeader>
<Card.Body>
<MultiSelect options={allAddresses} selectedIndexes={selectedIndexes}
setSelectedIndexes={setSelectedIndexes}/>
<button className={'mt-2 btn ' + (isUpToDate ? 'bg-transparent' : 'bg-theme')}
onClick={applySelected} disabled={isUpToDate}>
{t('html.label.apply')}
</button>
<button className={'mt-2 btn btn-outline-secondary float-end'}
onClick={remove}>
<FontAwesomeIcon icon={faTrashAlt}/>
</button>
</Card.Body>
</Card>
)
}
export default AddressGroupCard;

View File

@ -0,0 +1,32 @@
import {Col, Row} from "react-bootstrap";
import AddressGroupCard from "./AddressGroupCard.jsx";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faPlus} from "@fortawesome/free-solid-svg-icons";
import React from "react";
import {useTranslation} from "react-i18next";
import {useJoinAddressListContext} from "../../../hooks/context/joinAddressListContextHook.jsx";
const AddressGroupSelectorRow = () => {
const {t} = useTranslation();
const {list, add, remove, replace, allAddresses} = useJoinAddressListContext();
return (
<Row id={"address-selector"}>
{list.map((group, i) =>
<Col lg={2} key={group.uuid}>
<AddressGroupCard n={i + 1}
group={group}
editGroup={replacement => replace(replacement, i)}
allAddresses={allAddresses}
remove={() => remove(i)}/>
</Col>)}
<Col lg={2}>
<button className={"btn bg-theme mb-4"} onClick={add}>
<FontAwesomeIcon icon={faPlus}/> {t('html.label.addJoinAddressGroup')}
</button>
</Col>
</Row>
)
}
export default AddressGroupSelectorRow;

View File

@ -0,0 +1,27 @@
import LoadIn from "../../animation/LoadIn.jsx";
import ExtendableRow from "../../layout/extension/ExtendableRow.jsx";
import JoinAddressGraphCard from "../server/graphs/JoinAddressGraphCard.jsx";
import {Col} from "react-bootstrap";
import React from "react";
import AddressGroupSelectorRow from "./AddressGroupSelectorRow.jsx";
import {JoinAddressListContextProvider} from "../../../hooks/context/joinAddressListContextHook.jsx";
import {staticSite} from "../../../service/backendConfiguration.js";
const JoinAddresses = ({id, seeTime, identifier}) => {
return (
<LoadIn>
{seeTime && <section id={id} className={id}>
<JoinAddressListContextProvider identifier={identifier} isAllowed={seeTime}>
<ExtendableRow id={`row-${id}-0`}>
<Col lg={12}>
<JoinAddressGraphCard identifier={identifier}/>
</Col>
</ExtendableRow>
{!staticSite && <AddressGroupSelectorRow/>}
</JoinAddressListContextProvider>
</section>}
</LoadIn>
)
}
export default JoinAddresses;

View File

@ -0,0 +1,30 @@
import LoadIn from "../../animation/LoadIn.jsx";
import ExtendableRow from "../../layout/extension/ExtendableRow.jsx";
import {Col} from "react-bootstrap";
import PlayerRetentionGraphCard from "./PlayerRetentionGraphCard.jsx";
import React, {useState} from "react";
import {JoinAddressListContextProvider} from "../../../hooks/context/joinAddressListContextHook.jsx";
import AddressGroupSelectorRow from "./AddressGroupSelectorRow.jsx";
const PlayerRetention = ({id, seeRetention, identifier}) => {
const [selectedGroupBy, setSelectedGroupBy] = useState('none');
return (
<LoadIn>
{seeRetention && <section id={id} className={id}>
<JoinAddressListContextProvider identifier={identifier} isAllowed={seeRetention}
loadIndividualAddresses>
<ExtendableRow id={`row-${id}-0`}>
<Col lg={12}>
<PlayerRetentionGraphCard identifier={identifier}
selectedGroupBy={selectedGroupBy}
setSelectedGroupBy={setSelectedGroupBy}/>
</Col>
</ExtendableRow>
{selectedGroupBy === 'joinAddress' && <AddressGroupSelectorRow/>}
</JoinAddressListContextProvider>
</section>}
</LoadIn>
)
};
export default PlayerRetention

View File

@ -17,6 +17,7 @@ import {useTheme} from "../../../hooks/themeHook";
import {useNavigation} from "../../../hooks/navigationHook"; import {useNavigation} from "../../../hooks/navigationHook";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons"; import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons";
import {useJoinAddressListContext} from "../../../hooks/context/joinAddressListContextHook.jsx";
const dayMs = 24 * 3600000; const dayMs = 24 * 3600000;
const getWeek = (date) => { const getWeek = (date) => {
@ -26,7 +27,7 @@ const getWeek = (date) => {
return Math.ceil(dayOfYear / 7) return Math.ceil(dayOfYear / 7)
}; };
const PlayerRetentionGraphCard = ({identifier}) => { const PlayerRetentionGraphCard = ({identifier, selectedGroupBy, setSelectedGroupBy}) => {
const {t} = useTranslation(); const {t} = useTranslation();
const {nightModeEnabled} = useTheme(); const {nightModeEnabled} = useTheme();
const {setHelpModalTopic} = useNavigation(); const {setHelpModalTopic} = useNavigation();
@ -40,6 +41,8 @@ const PlayerRetentionGraphCard = ({identifier}) => {
loadingError: joinAddressLoadingError loadingError: joinAddressLoadingError
} = useDataRequest(fetchPlayerJoinAddresses, [identifier]); } = useDataRequest(fetchPlayerJoinAddresses, [identifier]);
const {list, playerAddresses} = useJoinAddressListContext();
const [selectedWindow, setSelectedWindow] = useState('days'); const [selectedWindow, setSelectedWindow] = useState('days');
const windowOptions = useMemo(() => [ const windowOptions = useMemo(() => [
{name: 'hours', displayName: t('html.label.time.hours'), increment: 3600000}, {name: 'hours', displayName: t('html.label.time.hours'), increment: 3600000},
@ -57,7 +60,7 @@ const PlayerRetentionGraphCard = ({identifier}) => {
{name: 'registered-2y', displayName: t('html.label.retention.inLast730d'), start: time - 2 * 365 * dayMs}, {name: 'registered-2y', displayName: t('html.label.retention.inLast730d'), start: time - 2 * 365 * dayMs},
{name: 'registered-ever', displayName: t('html.label.retention.inAnytime'), start: 0}, {name: 'registered-ever', displayName: t('html.label.retention.inAnytime'), start: 0},
], [t, time]); ], [t, time]);
const [selectedGroupBy, setSelectedGroupBy] = useState('none'); // State moved to higher level for join address group selection
const groupByOptions = useMemo(() => [ const groupByOptions = useMemo(() => [
{name: 'none', displayName: t('html.label.retention.groupByNone')}, {name: 'none', displayName: t('html.label.retention.groupByNone')},
{name: 'days', displayName: t('html.label.time.day')}, {name: 'days', displayName: t('html.label.time.day')},
@ -165,8 +168,11 @@ const PlayerRetentionGraphCard = ({identifier}) => {
break; break;
case 'joinAddress': case 'joinAddress':
const joinAddress = joinAddressData[point.playerUUID]; const joinAddress = joinAddressData[point.playerUUID];
if (!grouped[joinAddress]) grouped[joinAddress] = []; const joinAddressGroups = list.filter(g => g.addresses.includes(joinAddress)).map(g => g.name);
grouped[joinAddress].push(point); for (const joinAddressGroup of joinAddressGroups) {
if (!grouped[joinAddressGroup]) grouped[joinAddressGroup] = [];
grouped[joinAddressGroup].push(point);
}
break; break;
case 'none': case 'none':
default: default:
@ -175,7 +181,7 @@ const PlayerRetentionGraphCard = ({identifier}) => {
} }
} }
return grouped; return grouped;
}, [groupByOptions, selectedGroupBy]); }, [groupByOptions, selectedGroupBy, list]);
const createSeries = useCallback(async (retentionData, joinAddressData) => { const createSeries = useCallback(async (retentionData, joinAddressData) => {
@ -207,10 +213,10 @@ const PlayerRetentionGraphCard = ({identifier}) => {
}, [nightModeEnabled, mapToData, groupOptions, selectedGroup, selectedYAxis, group]); }, [nightModeEnabled, mapToData, groupOptions, selectedGroup, selectedYAxis, group]);
useEffect(() => { useEffect(() => {
if (!data || !joinAddressData) return; if (!data || !playerAddresses) return;
createSeries(data.player_retention, joinAddressData.join_address_by_player).then(series => setSeries(series.flat())); createSeries(data.player_retention, playerAddresses).then(series => setSeries(series.flat()));
}, [data, joinAddressData, createSeries, setSeries]); }, [data, playerAddresses, createSeries, setSeries]);
useEffect(() => { useEffect(() => {
const windowName = windowOptions.find(option => option.name === selectedWindow).displayName; const windowName = windowOptions.find(option => option.name === selectedWindow).displayName;
@ -261,13 +267,15 @@ const PlayerRetentionGraphCard = ({identifier}) => {
}, },
tooltip: selectedAxis === 'date' || selectedAxis === 'deltas' ? { tooltip: selectedAxis === 'date' || selectedAxis === 'deltas' ? {
enabled: true, enabled: true,
shared: series.length <= 10,
valueDecimals: 2, valueDecimals: 2,
pointFormat: (selectedGroupBy !== 'none' ? '{series.name} - ' : '') + '<b>{point.y} ' + (selectedYAxis === 'percentage' ? '%' : t('html.label.players')) + '</b>' pointFormat: (selectedGroupBy !== 'none' ? '{series.name} - ' : '') + '<b>{point.y} ' + (selectedYAxis === 'percentage' ? '%' : t('html.label.players')) + '</b><br>'
} : { } : {
enabled: true, enabled: true,
shared: series.length <= 10,
valueDecimals: 2, valueDecimals: 2,
headerFormat: '{point.x} ' + windowName + '<br>', headerFormat: '{point.x} ' + windowName + '<br>',
pointFormat: (selectedGroupBy !== 'none' ? '{series.name} - ' : '') + '<b>{point.y} ' + (selectedYAxis === 'percentage' ? '%' : t('html.label.players')) + '</b>' pointFormat: (selectedGroupBy !== 'none' ? '{series.name} - ' : '') + '<b>{point.y} ' + (selectedYAxis === 'percentage' ? '%' : t('html.label.players')) + '</b><br>'
}, },
series: series series: series
}) })

View File

@ -17,6 +17,7 @@ import FilterDropdown from "./FilterDropdown";
import FilterList from "./FilterList"; import FilterList from "./FilterList";
import {useQueryResultContext} from "../../../hooks/queryResultContext"; import {useQueryResultContext} from "../../../hooks/queryResultContext";
import {useNavigate} from "react-router-dom"; import {useNavigate} from "react-router-dom";
import {useNavigation} from "../../../hooks/navigationHook.jsx";
const parseTime = (dateString, timeString) => { const parseTime = (dateString, timeString) => {
const d = dateString.match( const d = dateString.match(
@ -37,7 +38,8 @@ const parseTime = (dateString, timeString) => {
const QueryOptionsCard = () => { const QueryOptionsCard = () => {
const {t} = useTranslation(); const {t} = useTranslation();
const navigate = useNavigate() const navigate = useNavigate()
const {setResult} = useQueryResultContext(); const {result, setResult} = useQueryResultContext();
const {setCurrentTab} = useNavigation();
const [loadingResults, setLoadingResults] = useState(false); const [loadingResults, setLoadingResults] = useState(false);
@ -52,6 +54,7 @@ const QueryOptionsCard = () => {
// View & filter data // View & filter data
const {data: options, loadingError} = useDataRequest(fetchFilters, []); const {data: options, loadingError} = useDataRequest(fetchFilters, []);
const [graphData, setGraphData] = useState(undefined); const [graphData, setGraphData] = useState(undefined);
useEffect(() => { useEffect(() => {
if (options) { if (options) {
@ -71,24 +74,22 @@ const QueryOptionsCard = () => {
if (invalidFields.length || !options) return; if (invalidFields.length || !options) return;
if (!fromDate && !fromTime && !toDate && !toTime) return; if (!fromDate && !fromTime && !toDate && !toTime) return;
const newMin = parseTime(
fromDate ? fromDate : options.view.afterDate,
fromTime ? fromTime : options.view.afterTime
);
const newMax = parseTime(
toDate ? toDate : options.view.beforeDate,
toTime ? toTime : options.view.beforeTime
);
setExtremes({ setExtremes({
min: newMin, min: parseTime(
max: newMax fromDate || options.view.afterDate,
fromTime || options.view.afterTime
),
max: parseTime(
toDate || options.view.beforeDate,
toTime || options.view.beforeTime
)
}); });
}, [invalidFields, options]); }, [invalidFields, options]);
/* eslint-enable react-hooks/exhaustive-deps */ /* eslint-enable react-hooks/exhaustive-deps */
useEffect(updateExtremes, [invalidFields, updateExtremes]); useEffect(updateExtremes, [updateExtremes]);
const onSetExtremes = useCallback((event) => { const onSetExtremes = useCallback((event) => {
if (event && event.trigger) { if (event?.trigger) {
const afterDate = Highcharts.dateFormat('%d/%m/%Y', event.min); const afterDate = Highcharts.dateFormat('%d/%m/%Y', event.min);
const afterTime = Highcharts.dateFormat('%H:%M', event.min); const afterTime = Highcharts.dateFormat('%H:%M', event.min);
const beforeDate = Highcharts.dateFormat('%d/%m/%Y', event.max); const beforeDate = Highcharts.dateFormat('%d/%m/%Y', event.max);
@ -100,6 +101,33 @@ const QueryOptionsCard = () => {
} }
}, [setFromTime, setFromDate, setToTime, setToDate]); }, [setFromTime, setFromDate, setToTime, setToDate]);
useEffect(() => {
if (!options?.view || !result?.view) return;
setSelectedServers(result.view.servers?.map(server => options.view.servers?.findIndex(s => s.serverUUID === server.serverUUID))?.filter(i => i !== -1) || [])
setFromDate(result.view.afterDate);
setFromTime(result.view.afterTime);
setToDate(result.view.beforeDate);
setToTime(result.view.beforeTime);
const existingFilters = result.filters;
existingFilters.forEach(f => f.options = options.filters.find(fo => fo.kind === f.kind).options);
setFilters(existingFilters);
setExtremes({
min: parseTime(
result.view.afterDate || options.view.afterDate,
result.view.afterTime || options.view.afterTime
),
max: parseTime(
result.view.beforeDate || options.view.beforeDate,
result.view.beforeTime || options.view.beforeTime
)
});
setCurrentTab('html.query.label.editQuery')
}, [options, result, setFromDate, setFromTime, setToDate, setToTime, setFilters, setSelectedServers, setExtremes]);
const getServerSelectorMessage = () => { const getServerSelectorMessage = () => {
const selected = selectedServers.length; const selected = selectedServers.length;
const available = options.view.servers.length; const available = options.view.servers.length;
@ -117,10 +145,10 @@ const QueryOptionsCard = () => {
const performQuery = async () => { const performQuery = async () => {
const inputDto = { const inputDto = {
view: { view: {
afterDate: fromDate ? fromDate : options.view.afterDate, afterDate: fromDate || options.view.afterDate,
afterTime: fromTime ? fromTime : options.view.afterTime, afterTime: fromTime || options.view.afterTime,
beforeDate: toDate ? toDate : options.view.beforeDate, beforeDate: toDate || options.view.beforeDate,
beforeTime: toTime ? toTime : options.view.beforeTime, beforeTime: toTime || options.view.beforeTime,
servers: selectedServers.map(index => options.view.servers[index]) servers: selectedServers.map(index => options.view.servers[index])
}, },
filters filters

View File

@ -12,10 +12,10 @@ const BetweenDatesFilter = ({index, label, filter, removeFilter, setFilterOption
const options = filter.options; const options = filter.options;
const [fromDate, setFromDate] = useState(options.after[0]); const [fromDate, setFromDate] = useState(filter.parameters?.afterDate || options.after[0]);
const [fromTime, setFromTime] = useState(options.after[1]); const [fromTime, setFromTime] = useState(filter.parameters?.afterTime || options.after[1]);
const [toDate, setToDate] = useState(options.before[0]); const [toDate, setToDate] = useState(filter.parameters?.beforeDate || options.before[0]);
const [toTime, setToTime] = useState(options.before[1]); const [toTime, setToTime] = useState(filter.parameters?.beforeTime || options.before[1]);
useEffect(() => { useEffect(() => {
setFilterOptions({ setFilterOptions({
...filter, ...filter,

View File

@ -9,7 +9,12 @@ const MultipleChoiceFilter = ({index, label, filter, removeFilter, setFilterOpti
const {t} = useTranslation(); const {t} = useTranslation();
const select = index === 0 ? t('html.query.filter.generic.start') : t('html.query.filter.generic.and'); const select = index === 0 ? t('html.query.filter.generic.start') : t('html.query.filter.generic.and');
const [selectedIndexes, setSelectedIndexes] = useState([]); const parameterSelected = filter.parameters?.selected
? JSON.parse(filter.parameters.selected)
.map(option => filter.options.options.indexOf(option))
: undefined;
const [selectedIndexes, setSelectedIndexes] = useState(parameterSelected || []);
useEffect(() => { useEffect(() => {
setFilterOptions({ setFilterOptions({
...filter, ...filter,

View File

@ -1,24 +1,80 @@
import React, {useState} from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchJoinAddressByDay} from "../../../../service/serverService"; import {fetchJoinAddressByDay} from "../../../../service/serverService";
import {ErrorViewCard} from "../../../../views/ErrorView"; import {ErrorViewCard} from "../../../../views/ErrorView";
import {CardLoader} from "../../../navigation/Loader"; import {ChartLoader} from "../../../navigation/Loader";
import {Card} from "react-bootstrap"; import {Card} from "react-bootstrap";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faChartColumn} from "@fortawesome/free-solid-svg-icons"; import {faChartColumn} from "@fortawesome/free-solid-svg-icons";
import JoinAddressGraph from "../../../graphs/JoinAddressGraph"; import JoinAddressGraph from "../../../graphs/JoinAddressGraph";
import Toggle from "../../../input/Toggle"; import Toggle from "../../../input/Toggle";
import {useJoinAddressListContext} from "../../../../hooks/context/joinAddressListContextHook.jsx";
import {useNavigation} from "../../../../hooks/navigationHook.jsx";
import {staticSite} from "../../../../service/backendConfiguration.js";
const JoinAddressGraphCard = ({identifier}) => { const JoinAddressGraphCard = ({identifier}) => {
const {t} = useTranslation(); const {t} = useTranslation();
const [stack, setStack] = useState(true); const [stack, setStack] = useState(true);
const {updateRequested} = useNavigation();
const {data, loadingError} = useDataRequest(fetchJoinAddressByDay, [identifier]); const {list} = useJoinAddressListContext();
const noSelectedAddresses = !list.filter(group => group.addresses.length).length;
const [data, setData] = useState(undefined);
const [loadingError, setLoadingError] = useState(undefined);
const loadAddresses = useCallback(async () => {
if (!staticSite && noSelectedAddresses) return;
let colors = ['#4ab4de'];
const dataByGroup = [];
const addressGroups = staticSite ? [{addresses: [], name: ""}] : list.filter(group => group.addresses.length);
for (const group of addressGroups) {
const {data, error} = await fetchJoinAddressByDay(updateRequested, group.addresses, identifier);
if (error) {
setLoadingError(error);
return;
}
colors = data?.colors;
dataByGroup.push({...group, data: data?.join_addresses_by_date || []});
}
if (!staticSite) {
// First group points from endpoint into frontend based groups
const points = {};
for (const group of dataByGroup) {
const groupName = group.name;
for (const point of group.data || []) {
if (!points[point.date]) points[point.date] = [];
const count = point.joinAddresses.map(j => j.count).reduce((partialSum, a) => partialSum + a, 0);
points[point.date].push({date: point.date, joinAddresses: [{joinAddress: groupName, count}]})
}
}
// expected output: [{date: number, addresses: [{joinAddress: "name", count: number}]}]
const flattened = Object.entries(points)
.sort((a, b) => Number(b.date) - Number(a.date))
.map(([date, pointList]) => {
return {
date: Number(date), joinAddresses: pointList.map(point => point.joinAddresses).flat()
}
});
setData({
join_addresses_by_date: flattened,
colors
});
} else {
// On exported site we get all addresses individually
setData({join_addresses_by_date: dataByGroup[0].data, colors})
}
}, [setData, setLoadingError, identifier, updateRequested, list]);
useEffect(() => {
loadAddresses();
}, [loadAddresses]);
if (loadingError) return <ErrorViewCard error={loadingError}/> if (loadingError) return <ErrorViewCard error={loadingError}/>
if (!data) return <CardLoader/>;
return ( return (
<Card> <Card>
@ -28,8 +84,12 @@ const JoinAddressGraphCard = ({identifier}) => {
</h6> </h6>
<Toggle value={stack} onValueChange={setStack} color={'amber'}>{t('html.label.stacked')}</Toggle> <Toggle value={stack} onValueChange={setStack} color={'amber'}>{t('html.label.stacked')}</Toggle>
</Card.Header> </Card.Header>
<JoinAddressGraph id={'join-address-graph'} data={data?.join_addresses_by_date} colors={data?.colors} {data &&
stack={stack}/> <JoinAddressGraph id={'join-address-graph'} data={data?.join_addresses_by_date} colors={data?.colors}
stack={stack}/>}
{!data && noSelectedAddresses &&
<div className="chart-area" style={{height: "450px"}}><p>Select some addresses</p></div>}
{!data && !noSelectedAddresses && <ChartLoader/>}
</Card> </Card>
) )
}; };

View File

@ -1,32 +0,0 @@
import React from 'react';
import {useTranslation} from "react-i18next";
import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchJoinAddressPie} from "../../../../service/serverService";
import {ErrorViewCard} from "../../../../views/ErrorView";
import {CardLoader} from "../../../navigation/Loader";
import {Card} from "react-bootstrap";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faLocationArrow} from "@fortawesome/free-solid-svg-icons";
import GroupVisualizer from "../../../graphs/GroupVisualizer";
const JoinAddressGroupCard = ({identifier}) => {
const {t} = useTranslation();
const {data, loadingError} = useDataRequest(fetchJoinAddressPie, [identifier]);
if (loadingError) return <ErrorViewCard error={loadingError}/>
if (!data) return <CardLoader/>;
return (
<Card id={'join-address-groups'}>
<Card.Header>
<h6 className="col-black" style={{width: '100%'}}>
<Fa icon={faLocationArrow} className="col-amber"/> {t('html.label.latestJoinAddresses')}
</h6>
</Card.Header>
<GroupVisualizer groups={data.slices} colors={data.colors}/>
</Card>
)
};
export default JoinAddressGroupCard

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const MultiSelect = ({options, selectedIndexes, setSelectedIndexes}) => { const MultiSelect = ({options, selectedIndexes, setSelectedIndexes, className}) => {
const handleChange = (event) => { const handleChange = (event) => {
const renderedOptions = Object.values(event.target.selectedOptions) const renderedOptions = Object.values(event.target.selectedOptions)
.map(htmlElement => htmlElement.text) .map(htmlElement => htmlElement.text)
@ -9,7 +9,7 @@ const MultiSelect = ({options, selectedIndexes, setSelectedIndexes}) => {
} }
return ( return (
<select className="form-control" multiple <select className={"form-control " + className} multiple
onChange={handleChange}> onChange={handleChange}>
{options.map((option, i) => { {options.map((option, i) => {
return ( return (

View File

@ -58,7 +58,7 @@ const Header = ({page, tab, hideUpdater}) => {
</button>} </button>}
{staticSite && <Fa icon={faClockRotateLeft} title={t('html.label.exported')}/>} {staticSite && <Fa icon={faClockRotateLeft} title={t('html.label.exported')}/>}
{' '} {' '}
<span className="refresh-time"><FormattedDate date={lastUpdate.date}/></span> <span className="refresh-time"><FormattedDate date={lastUpdate.date} react/></span>
</div> </div>
</>} </>}

View File

@ -40,7 +40,7 @@ export function formatDate(date, offset, pattern, recentDays, recentDaysPattern,
return date !== 0 ? new SimpleDateFormat(format).format(timestamp) : '-' return date !== 0 ? new SimpleDateFormat(format).format(timestamp) : '-'
} }
const FormattedDate = ({date}) => { const FormattedDate = ({date, react}) => {
const {t} = useTranslation(); const {t} = useTranslation();
const {pattern, recentDays, recentDaysPattern, offset} = useDatePreferences(); const {pattern, recentDays, recentDaysPattern, offset} = useDatePreferences();
@ -48,6 +48,12 @@ const FormattedDate = ({date}) => {
if (!pattern || date === undefined || date === null) return <></>; if (!pattern || date === undefined || date === null) return <></>;
if (!isNumber(date)) return date; if (!isNumber(date)) return date;
if (react) {
return <span title={formatDate(date, offset, pattern, false, null, t)}>
{formatDate(date, offset, pattern, recentDays, recentDaysPattern, t)}
</span>
}
return formatDate(date, offset, pattern, recentDays, recentDaysPattern, t); return formatDate(date, offset, pattern, recentDays, recentDaysPattern, t);
}; };

View File

@ -0,0 +1,71 @@
import {createContext, useCallback, useContext, useEffect, useMemo, useState} from "react";
import {randomUuid} from "../../util/uuid.js";
import {fetchPlayerJoinAddresses} from "../../service/serverService.js";
import {useNavigation} from "../navigationHook.jsx";
import {usePreferences} from "../preferencesHook.jsx";
import {useTranslation} from "react-i18next";
const JoinAddressListContext = createContext({});
export const JoinAddressListContextProvider = ({identifier, children, loadIndividualAddresses, isAllowed}) => {
const {t} = useTranslation();
const {updateRequested} = useNavigation();
const {preferencesLoaded, getKeyedPreference, setSomePreferences} = usePreferences();
const [list, setList] = useState([]);
const updateList = useCallback(newValue => {
setList(newValue);
const userPreferences = {}
userPreferences["join-addresses-" + identifier] = newValue;
setSomePreferences(userPreferences);
}, [setList])
useEffect(() => {
if (preferencesLoaded && !list.length) {
const value = getKeyedPreference("join-addresses-" + identifier);
if (value?.length) {
setList(value)
}
}
}, [list, setList, preferencesLoaded, getKeyedPreference]);
const add = useCallback(() => {
updateList([...list, {
name: t('html.label.addressGroup').replace("{{n}}", list.length + 1),
addresses: [],
uuid: randomUuid()
}])
}, [updateList, list]);
const remove = useCallback(index => {
updateList(list.filter((f, i) => i !== index));
}, [updateList, list]);
const replace = useCallback((replacement, index) => {
const newList = [...list];
newList[index] = replacement;
updateList(newList)
}, [updateList, list]);
const [allAddresses, setAllAddresses] = useState([]);
const [playerAddresses, setPlayerAddresses] = useState(undefined);
const loadAddresses = useCallback(async () => {
if (!isAllowed) return;
const {data, error} = await fetchPlayerJoinAddresses(updateRequested, identifier, !loadIndividualAddresses);
setAllAddresses(data?.joinAddresses || [error]);
setPlayerAddresses(data?.joinAddressByPlayer);
}, [setAllAddresses, identifier, updateRequested, isAllowed]);
useEffect(() => {
loadAddresses();
}, [loadAddresses]);
const sharedState = useMemo(() => {
return {list, add, remove, replace, allAddresses, playerAddresses};
}, [list, add, remove, replace, allAddresses, playerAddresses]);
return (<JoinAddressListContext.Provider value={sharedState}>
{children}
</JoinAddressListContext.Provider>
)
}
export const useJoinAddressListContext = () => {
return useContext(JoinAddressListContext);
}

View File

@ -33,7 +33,15 @@ export const PreferencesContextProvider = ({children}) => {
} else { } else {
localStorage.setItem("preferences", JSON.stringify(withDefaultsRemoved)); localStorage.setItem("preferences", JSON.stringify(withDefaultsRemoved));
} }
}, [defaultPreferences, authRequired, authLoaded, loggedIn]); setPreferences({...defaultPreferences, ...(withDefaultsRemoved || {})});
}, [defaultPreferences, authRequired, authLoaded, loggedIn, setPreferences]);
const setSomePreferences = useCallback(userPref => {
storePreferences({...preferences, ...userPref});
}, [storePreferences, preferences]);
const getKeyedPreference = useCallback(key => {
return preferences[key];
}, [preferences]);
useEffect(() => { useEffect(() => {
updatePreferences(); updatePreferences();
@ -42,12 +50,13 @@ export const PreferencesContextProvider = ({children}) => {
const sharedState = useMemo(() => { const sharedState = useMemo(() => {
return { return {
...preferences, ...preferences,
storePreferences, getKeyedPreference,
setSomePreferences,
defaultPreferences, defaultPreferences,
preferencesLoaded: Object.keys(defaultPreferences || {}).length > 0 preferencesLoaded: Object.keys(defaultPreferences || {}).length > 0
} }
}, },
[preferences, defaultPreferences, storePreferences]); [preferences, defaultPreferences, storePreferences, getKeyedPreference, setSomePreferences]);
return (<PreferencesContext.Provider value={sharedState}> return (<PreferencesContext.Provider value={sharedState}>
{children} {children}
</PreferencesContext.Provider> </PreferencesContext.Provider>

View File

@ -261,42 +261,22 @@ export const fetchPingGraph = async (timestamp, identifier) => {
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }
export const fetchJoinAddressPie = async (timestamp, identifier) => { export const fetchJoinAddressByDay = async (timestamp, addresses, identifier) => {
if (identifier) { if (identifier) {
return await fetchJoinAddressPieServer(timestamp, identifier); return await fetchJoinAddressByDayServer(timestamp, addresses, identifier);
} else { } else {
return await fetchJoinAddressPieNetwork(timestamp); return await fetchJoinAddressByDayNetwork(timestamp, addresses);
} }
} }
const fetchJoinAddressPieServer = async (timestamp, identifier) => { const fetchJoinAddressByDayServer = async (timestamp, addresses, identifier) => {
let url = `/v1/graph?type=joinAddressPie&server=${identifier}`; let url = `/v1/graph?type=joinAddressByDay&server=${identifier}&addresses=${addresses.join(',')}`;
if (staticSite) url = `/data/graph-joinAddressPie_${identifier}.json`;
return doGetRequest(url, timestamp);
}
const fetchJoinAddressPieNetwork = async (timestamp) => {
let url = `/v1/graph?type=joinAddressPie`;
if (staticSite) url = `/data/graph-joinAddressPie.json`;
return doGetRequest(url, timestamp);
}
export const fetchJoinAddressByDay = async (timestamp, identifier) => {
if (identifier) {
return await fetchJoinAddressByDayServer(timestamp, identifier);
} else {
return await fetchJoinAddressByDayNetwork(timestamp);
}
}
const fetchJoinAddressByDayServer = async (timestamp, identifier) => {
let url = `/v1/graph?type=joinAddressByDay&server=${identifier}`;
if (staticSite) url = `/data/graph-joinAddressByDay_${identifier}.json`; if (staticSite) url = `/data/graph-joinAddressByDay_${identifier}.json`;
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }
const fetchJoinAddressByDayNetwork = async (timestamp) => { const fetchJoinAddressByDayNetwork = async (timestamp, addresses) => {
let url = `/v1/graph?type=joinAddressByDay`; let url = `/v1/graph?type=joinAddressByDay&addresses=${addresses.join(',')}`;
if (staticSite) url = `/data/graph-joinAddressByDay.json`; if (staticSite) url = `/data/graph-joinAddressByDay.json`;
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }
@ -321,22 +301,22 @@ const fetchNetworkRetentionData = async (timestamp) => {
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }
export const fetchPlayerJoinAddresses = async (timestamp, identifier) => { export const fetchPlayerJoinAddresses = async (timestamp, identifier, justList) => {
if (identifier) { if (identifier) {
return await fetchServerPlayerJoinAddresses(timestamp, identifier); return await fetchServerPlayerJoinAddresses(timestamp, identifier, justList);
} else { } else {
return await fetchNetworkPlayerJoinAddresses(timestamp); return await fetchNetworkPlayerJoinAddresses(timestamp, justList);
} }
} }
const fetchServerPlayerJoinAddresses = async (timestamp, identifier) => { const fetchServerPlayerJoinAddresses = async (timestamp, identifier, justList) => {
let url = `/v1/joinAddresses?server=${identifier}`; let url = `/v1/joinAddresses?server=${identifier}${justList ? "&listOnly=true" : ""}`;
if (staticSite) url = `/data/joinAddresses-${identifier}.json`; if (staticSite) url = `/data/joinAddresses-${identifier}.json`;
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }
const fetchNetworkPlayerJoinAddresses = async (timestamp) => { const fetchNetworkPlayerJoinAddresses = async (timestamp, justList) => {
let url = `/v1/joinAddresses`; let url = `/v1/joinAddresses${justList ? "?listOnly=true" : ""}`;
if (staticSite) url = `/data/joinAddresses.json`; if (staticSite) url = `/data/joinAddresses.json`;
return doGetRequest(url, timestamp); return doGetRequest(url, timestamp);
} }

View File

@ -0,0 +1,6 @@
// https://stackoverflow.com/a/2117523/20825073
export function randomUuid() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}

View File

@ -1,29 +1,12 @@
import React from 'react'; import React from 'react';
import {Col} from "react-bootstrap"; import JoinAddresses from "../../components/cards/common/JoinAddresses.jsx";
import JoinAddressGroupCard from "../../components/cards/server/graphs/JoinAddressGroupCard"; import {useAuth} from "../../hooks/authenticationHook.jsx";
import JoinAddressGraphCard from "../../components/cards/server/graphs/JoinAddressGraphCard";
import LoadIn from "../../components/animation/LoadIn";
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
import {useAuth} from "../../hooks/authenticationHook";
const NetworkJoinAddresses = () => { const NetworkJoinAddresses = () => {
const {hasPermission} = useAuth(); const {hasPermission} = useAuth();
const seeTime = hasPermission('page.network.join.addresses.graphs.time'); const seeTime = hasPermission('page.network.join.addresses.graphs.time');
const seeLatest = hasPermission('page.network.join.addresses.graphs.pie');
return ( return (
<LoadIn> <JoinAddresses id={'network-join-addresses'} identifier={null} seeTime={seeTime}/>
<section className={"network-join-addresses"}>
<ExtendableRow id={'row-network-join-addresses-0'}>
{seeTime && <Col lg={8}>
<JoinAddressGraphCard identifier={undefined}/>
</Col>}
{seeLatest && <Col lg={4}>
<JoinAddressGroupCard identifier={undefined}/>
</Col>}
</ExtendableRow>
</section>
</LoadIn>
) )
}; };

View File

@ -1,24 +1,12 @@
import React from 'react'; import React from 'react';
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
import {Col} from "react-bootstrap";
import LoadIn from "../../components/animation/LoadIn";
import PlayerRetentionGraphCard from "../../components/cards/common/PlayerRetentionGraphCard";
import {useAuth} from "../../hooks/authenticationHook"; import {useAuth} from "../../hooks/authenticationHook";
import PlayerRetention from "../../components/cards/common/PlayerRetention.jsx";
const NetworkPlayerRetention = () => { const NetworkPlayerRetention = () => {
const {hasPermission} = useAuth(); const {hasPermission} = useAuth();
const seeRetention = hasPermission('page.network.retention'); const seeRetention = hasPermission('page.network.retention');
return ( return (
<LoadIn> <PlayerRetention id={"network-retention"} identifier={null} seeRetention={seeRetention}/>
{seeRetention && <section className="network-retention">
<ExtendableRow id={'row-network-retention-0'}>
<Col lg={12}>
<PlayerRetentionGraphCard identifier={null}/>
</Col>
</ExtendableRow>
</section>}
</LoadIn>
) )
}; };

View File

@ -12,7 +12,7 @@ const NewQueryView = () => {
{hasPermission('access.query') && <section className={"query-options-view"}> {hasPermission('access.query') && <section className={"query-options-view"}>
<Row> <Row>
<Col md={12}> <Col md={12}>
<QueryPath/> <QueryPath newQuery/>
<QueryOptionsCard/> <QueryOptionsCard/>
</Col> </Col>
</Row> </Row>

View File

@ -1,31 +1,14 @@
import React from 'react'; import React from 'react';
import {Col} from "react-bootstrap";
import JoinAddressGroupCard from "../../components/cards/server/graphs/JoinAddressGroupCard";
import JoinAddressGraphCard from "../../components/cards/server/graphs/JoinAddressGraphCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import LoadIn from "../../components/animation/LoadIn"; import JoinAddresses from "../../components/cards/common/JoinAddresses.jsx";
import ExtendableRow from "../../components/layout/extension/ExtendableRow"; import {useAuth} from "../../hooks/authenticationHook.jsx";
import {useAuth} from "../../hooks/authenticationHook";
const ServerJoinAddresses = () => { const ServerJoinAddresses = () => {
const {hasPermission} = useAuth();
const {identifier} = useParams(); const {identifier} = useParams();
const {hasPermission} = useAuth();
const seeTime = hasPermission('page.server.join.addresses.graphs.time'); const seeTime = hasPermission('page.server.join.addresses.graphs.time');
const seeLatest = hasPermission('page.server.join.addresses.graphs.pie');
return ( return (
<LoadIn> <JoinAddresses id={'server-join-addresses'} identifier={identifier} seeTime={seeTime}/>
<section className={"server-join-addresses"}>
<ExtendableRow id={'row-server-join-addresses-0'}>
{seeTime && <Col lg={8}>
<JoinAddressGraphCard identifier={identifier}/>
</Col>}
{seeLatest && <Col lg={4}>
<JoinAddressGroupCard identifier={identifier}/>
</Col>}
</ExtendableRow>
</section>
</LoadIn>
) )
}; };

View File

@ -1,10 +1,7 @@
import React from 'react'; import React from 'react';
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
import {Col} from "react-bootstrap";
import LoadIn from "../../components/animation/LoadIn";
import PlayerRetentionGraphCard from "../../components/cards/common/PlayerRetentionGraphCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useAuth} from "../../hooks/authenticationHook"; import {useAuth} from "../../hooks/authenticationHook";
import PlayerRetention from "../../components/cards/common/PlayerRetention.jsx";
const ServerPlayerRetention = () => { const ServerPlayerRetention = () => {
const {hasPermission} = useAuth(); const {hasPermission} = useAuth();
@ -12,15 +9,7 @@ const ServerPlayerRetention = () => {
const seeRetention = hasPermission('page.server.retention'); const seeRetention = hasPermission('page.server.retention');
return ( return (
<LoadIn> <PlayerRetention id={"server-retention"} identifier={identifier} seeRetention={seeRetention}/>
<section className="server-retention">
{seeRetention && <ExtendableRow id={'row-server-retention-0'}>
<Col lg={12}>
<PlayerRetentionGraphCard identifier={identifier}/>
</Col>
</ExtendableRow>}
</section>
</LoadIn>
) )
}; };

File diff suppressed because it is too large Load Diff