diff --git a/docs/historique/traque_14_12_25/compte_rendu.txt b/docs/historique/traque_14_12_25/compte_rendu.txt
index 084179a..94fd50c 100644
--- a/docs/historique/traque_14_12_25/compte_rendu.txt
+++ b/docs/historique/traque_14_12_25/compte_rendu.txt
@@ -9,7 +9,7 @@ Météo : 8°C, pas de pluie, brouillard (visibilité <400m), vent 10km/h
Problèmes
[ ] Une équipe perdait sans arrêt la connection avec le serveur
-[ ] La position en arrière plan, téléphone éteint par exemple, n'avait pas l'air de fonctionner (une équipe n'avait pas de notif)
+[x] La position en arrière plan, téléphone éteint par exemple, n'avait pas l'air de fonctionner (une équipe n'avait pas de notif)
[x] La photo d'une des équipes ne parvenait pas jusqu'au serveur. Tout semblait normal pour l'équipe. (Potentiellement un problème
de conversion : 046512 -> 46512)
[x] Le focus sur une équipe dans la page principale des admins est à revoir. Par exemple, le zoom seul devrait désactiver le focus
@@ -19,7 +19,6 @@ voyants des équipes encore en jeu soit mis en avant.
[x] La visibilité des éléments de la map en calque satellite est mauvaise. Il faut revoir les couleurs.
[x] Les zones polygonales s'affichent mal sur la version prod de l'app mobile. Les anciennes n'ont pas l'air de disparaitre.
[x] La zone de jeu (en rouge) est mal comprise, les joueurs évitent de rester dedans alors qu'ils ont le droit.
-[ ] L'application n'est pas pleinement intuitive, par exemple le bouton pour actualiser sa position ou alors les icônes des stats.
À faire
diff --git a/docs/historique/traque_20_09_25/compte_rendu.txt b/docs/historique/traque_20_09_25/compte_rendu.txt
index 658c7ac..ffed170 100644
--- a/docs/historique/traque_20_09_25/compte_rendu.txt
+++ b/docs/historique/traque_20_09_25/compte_rendu.txt
@@ -8,7 +8,7 @@ Cette traque est la première à se faire avec le nouveau site web et la version
Problèmes
[ ] Une équipe perdait sans arrêt la connection avec le serveur
-[ ] La position en arrière plan, téléphone éteint par exemple, n'avait pas l'air de fonctionner (une équipe n'avait pas de notif)
+[x] La position en arrière plan, téléphone éteint par exemple, n'avait pas l'air de fonctionner (une équipe n'avait pas de notif)
[ ] Aux deux tiers de la partie toutes les équipes ont été déconnectée en même temps mais ont pu se reconnecter. Ça s'est produit
sans raisons apparentes
[ ] Une équipe avait deux téléphones connectés sauf que le premier ne marchait pas bien. Par ailleurs, l'équipe disaient n'avoir
diff --git a/mobile/docs/TODO.md b/mobile/docs/TODO.md
index c830824..401e21b 100644
--- a/mobile/docs/TODO.md
+++ b/mobile/docs/TODO.md
@@ -11,18 +11,13 @@
- [x] Centrer la map sur la position à l'ouverture + bouton centrage
- [x] Indiquer que l'équipe est hors zone.
- [x] Mettre les stats dans le tiroir (distance, temps, vitesse moy, nb captures, nb envoi)
+- [x] Traduction anglaise
- [ ] Implémenter des notifs lors du background (hors zone, position envoyée, update zone)
-- [ ] Ajouter les logs de la partie
- [ ] Créer le menu paramètre (idées de section : langue, photo équipe, notifs, mode sombre, unitées)
- [ ] Afficher la trajectoire passée sur la carte (désactivable)
- [ ] Afficher les évènements passés sur la carte (captures, envois, départ) (désactivable)
- [ ] Permettre le changement du style de la carte (schéma, satellite, relief etc)
- [ ] Ajouter imprécision de la position au besoin (comme sur google maps)
- [ ] Synchroniser les horloges sur l'interface
-- [ ] Avoir un récap des évènement de la partie
+- [ ] Améliorer l'intuitivité de l'interface (bouton d'actualisation / stats)
- [ ] Publier sur le playstore
-
-## Autres idées
-
-- Améliorer l'accessibilité (traduction anglaise notamment).
-- Améliorer l'UI.
diff --git a/mobile/traque-app/app/(auth)/location-permission.jsx b/mobile/traque-app/app/(auth)/location-permission.jsx
index 5ec6f86..0bfb323 100644
--- a/mobile/traque-app/app/(auth)/location-permission.jsx
+++ b/mobile/traque-app/app/(auth)/location-permission.jsx
@@ -1,7 +1,39 @@
-import { Text } from 'react-native';
+//React
+import { StyleSheet, Text, View, Image } from 'react-native';
+import { useTranslation } from 'react-i18next';
const LocationPermission = () => {
- return {"Veuillez activer la géolocalisation en arrière plan dans les paramètres, puis relancez l'application."};
+ const { t } = useTranslation();
+
+ return (<>
+
+
+ {t("location-permission.title")}
+ {t("location-permission.subtitle")}
+
+ >);
};
export default LocationPermission;
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: "center",
+ justifyContent: "center",
+ padding: 20,
+ gap: 20
+ },
+ image: {
+ width: 150,
+ height: 150,
+ marginTop: -100,
+ },
+ title: {
+ fontSize: 20,
+ fontWeight: "bold",
+ },
+ subtitle: {
+ fontSize: 15,
+ },
+});
diff --git a/mobile/traque-app/app/(auth)/login.jsx b/mobile/traque-app/app/(auth)/login.jsx
index 30bd9b8..2ef8ce6 100644
--- a/mobile/traque-app/app/(auth)/login.jsx
+++ b/mobile/traque-app/app/(auth)/login.jsx
@@ -1,6 +1,6 @@
// React
import { useState } from 'react';
-import { ScrollView, View, Text, StyleSheet, Image, Alert, TouchableHighlight } from 'react-native';
+import { Keyboard, ScrollView, View, Text, StyleSheet, Image, Alert, TouchableHighlight } from 'react-native';
import { useTranslation } from 'react-i18next';
// Components
import { TouchableImage } from '@/components/common/Image';
@@ -28,7 +28,9 @@ const Login = () => {
const regex = /^\d{6}$/;
if (!regex.test(teamId)) {
- setTimeout(() => Alert.alert(t("error.title"), t("error.invalid_team_id")), 100);
+ Keyboard.dismiss();
+ Alert.alert(t("error.default.title"), t("error.default.invalid_team_id"));
+ setIsSubmitting(false);
return;
}
@@ -39,10 +41,12 @@ const Login = () => {
uploadTeamImage(teamId, image?.uri);
setTeamId("");
} else {
- setTimeout(() => Alert.alert(t("error.title"), t("error.unknown_team_id")), 100);
+ Keyboard.dismiss();
+ Alert.alert(t("error.default.title"), t("error.default.unknown_team_id"));
}
} catch (error) {
- setTimeout(() => Alert.alert(t("error.title"), t("error.server_connection")), 100);
+ Keyboard.dismiss();
+ Alert.alert(t("error.default.title"), t("error.default.server_connection"));
} finally {
setIsSubmitting(false);
}
@@ -53,20 +57,20 @@ const Login = () => {
- {t("index.header.title")}
+ {t("login.header.title")}
-
+
- {t("index.form.image_label")}
- {t("index.form.image_sublabel")}
+ {t("login.form.image_label")}
+ {t("login.form.image_sublabel")}
- {isSubmitting ? "..." : t("index.form.validate_button")}
+ {isSubmitting ? "..." : t("login.form.validate_button")}
diff --git a/mobile/traque-app/app/(game)/play.jsx b/mobile/traque-app/app/(game)/play.jsx
index f100231..086d6ae 100644
--- a/mobile/traque-app/app/(game)/play.jsx
+++ b/mobile/traque-app/app/(game)/play.jsx
@@ -35,8 +35,8 @@ const Play = () => {
-
-
+
+
@@ -49,8 +49,8 @@ const Play = () => {
- Alert.alert(t("interface.map.previous_marker_title"), t("interface.map.previous_marker_description"))} />
- Alert.alert(t("interface.map.enemy_marker_title"), t("interface.map.enemy_marker_description"))} />
+ Alert.alert(t("play.map.previous_marker_title"), t("play.map.previous_marker_description"))} />
+ Alert.alert(t("play.map.enemy_marker_title"), t("play.map.enemy_marker_description"))} />
diff --git a/mobile/traque-app/app/(game)/wait.jsx b/mobile/traque-app/app/(game)/wait.jsx
index fadc55b..0625eb6 100644
--- a/mobile/traque-app/app/(game)/wait.jsx
+++ b/mobile/traque-app/app/(game)/wait.jsx
@@ -1,16 +1,35 @@
// React
-import { View, Text, StyleSheet } from 'react-native';
+import { View, Text, StyleSheet, Image } from 'react-native';
+import { useTranslation } from 'react-i18next';
// Components
import { Header } from '@/components/game/Header';
// Constants
import { COLORS } from '@/constants';
const Wait = () => {
+ const { t } = useTranslation();
+
return (
-
-
- Veuillez patienter, la partie va bientôt commencer !
+
+
+ {t("wait.title")}
+
+
+ {t("wait.placement_rule")}
+
+
+ {t("wait.capture_rule")}
+
+
+
+
+ {t("wait.zone_rule")}
+
+
+ {t("wait.team_rule")}
+
+
);
@@ -22,10 +41,35 @@ const styles = StyleSheet.create({
globalContainer: {
backgroundColor: COLORS.background,
flex: 1,
+ padding: 20,
},
- topContainer: {
- width: '100%',
+ rulesContainer: {
+ flex: 1,
alignItems: 'center',
- padding: 15,
+ gap: 30
+ },
+ title: {
+ backgroundColor: "white",
+ textAlign: 'center',
+ fontSize: 30,
+ fontWeight: "bold",
+ borderWidth: 2,
+ borderRadius: 10,
+ padding: 10,
+ },
+ section: {
+ width: '100%',
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ gap: 20,
+ },
+ image: {
+ width: 100,
+ height: 100,
+ },
+ description: {
+ flex: 1,
+
}
});
diff --git a/mobile/traque-app/app/_layout.jsx b/mobile/traque-app/app/_layout.jsx
index 71f171e..b98e677 100644
--- a/mobile/traque-app/app/_layout.jsx
+++ b/mobile/traque-app/app/_layout.jsx
@@ -1,17 +1,22 @@
// React
import { useEffect } from 'react';
+import { View, StyleSheet } from 'react-native';
+import { useTranslation } from 'react-i18next';
// Expo
import { Slot, useRouter, usePathname } from 'expo-router';
+// Components
+import { IconButton } from '@/components/common/IconButton';
// Contexts
import { AuthProvider } from "@/contexts/authContext";
import { TeamProvider } from "@/contexts/teamContext";
+// Hook
+import { useUserState } from '@/hooks/useUserState';
// Services
import { startLocationTracking , stopLocationTracking } from '@/services/tasks/backgroundLocation';
// Constants
import { USER_STATE } from '@/constants';
// Traduction
import '@/i18n/config';
-import { useUserState } from '@/hooks/useUserState';
const NavigationManager = () => {
const router = useRouter();
@@ -72,15 +77,43 @@ const NavigationManager = () => {
return null;
};
+const Language = () => {
+ const { i18n } = useTranslation();
+
+ const toggleLanguage = () => {
+ i18n.changeLanguage(i18n.language === 'fr' ? 'en' : 'fr');
+ };
+
+ return (
+
+
+
+ );
+};
+
const RootLayout = () => {
return (
+
);
};
export default RootLayout;
+
+const styles = StyleSheet.create({
+ languageButton: {
+ position: 'absolute',
+ top: 0,
+ right: 0,
+ backgroundColor: "rgb(126, 182, 199)",
+ borderBottomLeftRadius: 20,
+ padding: 5,
+ justifyContent: 'center',
+ alignItems: 'center',
+ }
+});
diff --git a/mobile/traque-app/src/assets/images/flag.png b/mobile/traque-app/src/assets/images/flag.png
new file mode 100644
index 0000000..8981a76
Binary files /dev/null and b/mobile/traque-app/src/assets/images/flag.png differ
diff --git a/mobile/traque-app/src/assets/images/language.png b/mobile/traque-app/src/assets/images/language.png
new file mode 100644
index 0000000..063d6fe
Binary files /dev/null and b/mobile/traque-app/src/assets/images/language.png differ
diff --git a/mobile/traque-app/src/assets/images/team.png b/mobile/traque-app/src/assets/images/team.png
new file mode 100644
index 0000000..2da93e3
Binary files /dev/null and b/mobile/traque-app/src/assets/images/team.png differ
diff --git a/mobile/traque-app/src/components/game/Header.jsx b/mobile/traque-app/src/components/game/Header.jsx
index f6674e6..c9d0699 100644
--- a/mobile/traque-app/src/components/game/Header.jsx
+++ b/mobile/traque-app/src/components/game/Header.jsx
@@ -1,5 +1,6 @@
// React
-import { View, Text, Alert, StyleSheet } from 'react-native';
+import { View, Text, StyleSheet } from 'react-native';
+import { useTranslation } from 'react-i18next';
// Contexts
import { useAuth } from '@/contexts/authContext';
import { useTeam } from '@/contexts/teamContext';
@@ -7,18 +8,16 @@ import { useTeam } from '@/contexts/teamContext';
import { IconButton } from '@/components/common/IconButton';
export const Header = () => {
+ const { t } = useTranslation();
const { logout } = useAuth();
const { teamInfos } = useTeam();
const { name } = teamInfos;
return (
-
-
- Alert.alert("Settings")} />
-
+
- {name ?? "Inconnue"}
+ {name ?? t("common.no_value")}
);
@@ -27,17 +26,12 @@ export const Header = () => {
const styles = StyleSheet.create({
container: {
width: '100%',
- alignItems: 'center'
- },
- buttonsContainer: {
- width: "100%",
- flexDirection: "row",
- justifyContent: 'space-between'
},
nameContainer: {
width: '100%',
alignItems: 'center',
- justifyContent: 'center'
+ justifyContent: 'center',
+ marginBottom: 20
},
name: {
fontSize: 36,
diff --git a/mobile/traque-app/src/components/game/MapLayers.jsx b/mobile/traque-app/src/components/game/MapLayers.jsx
index 222969a..0b14277 100644
--- a/mobile/traque-app/src/components/game/MapLayers.jsx
+++ b/mobile/traque-app/src/components/game/MapLayers.jsx
@@ -13,7 +13,7 @@ export const StartZone = () => {
const { startingArea } = teamInfos;
return useMemo(() => {
- if (startingArea) return null;
+ if (!startingArea) return null;
return (
{
emitCapture(enemyCaptureCode)
.then((response) => {
if (response.hasCaptured) {
- Alert.alert("Bravo !", "Vous avez réussi à capturer votre cible. Une nouvelle cible vient de vous être attribuée.");
+ Keyboard.dismiss();
+ Alert.alert(t("info.success.title"), t("info.success.capture_success"));
setEnemyCaptureCode("");
} else {
- Alert.alert("Échec !", "Le code que vous venez de rentrer n'est pas celui de votre cible.");
+ Keyboard.dismiss();
+ Alert.alert(t("info.failure.title"), t("info.failure.capture_failure"));
}
})
.catch(() => {
- Alert.alert(t("error.title"), t("error.server_connection"));
+ Keyboard.dismiss();
+ Alert.alert(t("error.default.title"), t("error.default.server_connection"));
})
.finally(() => setIsCapturing(false));
};
@@ -46,16 +49,16 @@ export const TargetInfoDrawer = ({ height }) => {
return (
- {t("interface.drawer.capture_code", {name: name ?? t("general.no_value"), code: String(captureCode).padStart(4,"0")})}
+ {t("play.drawer.capture_code", {name: name ?? t("common.no_value"), code: String(captureCode).padStart(4,"0")})}
- {t("interface.drawer.target_name", {name: enemyName ?? t("general.no_value")})}
+ {t("play.drawer.target_name", {name: enemyName ?? t("common.no_value")})}
-
+
diff --git a/mobile/traque-app/src/components/game/TeamStats.jsx b/mobile/traque-app/src/components/game/TeamStats.jsx
index 730742f..7a2abf3 100644
--- a/mobile/traque-app/src/components/game/TeamStats.jsx
+++ b/mobile/traque-app/src/components/game/TeamStats.jsx
@@ -10,8 +10,10 @@ import { useTimeSinceSeconds } from '@/hooks/useTimeDelta';
import { secondsToHHMMSS } from '@/utils/functions';
const Stat = ({ children, source, description }) => {
+ const { t } = useTranslation();
+
return (
- Alert.alert("Info", description) : null}>
+ Alert.alert(t("info.default.title"), description) : null}>
{children}
@@ -36,13 +38,13 @@ export const TeamStats = () => {
return (
- {Math.floor(distance / 100) / 10}km
- {secondsToHHMMSS((finishDate ? Math.floor((finishDate - startDate) / 1000) : timeSinceGameStart))}
- {avgSpeed}km/h
+ {Math.floor(distance / 100) / 10}km
+ {secondsToHHMMSS((finishDate ? Math.floor((finishDate - startDate) / 1000) : timeSinceGameStart))}
+ {avgSpeed}km/h
- {nCaptures}
- {nSentLocation}
+ {nCaptures}
+ {nSentLocation}
);
diff --git a/mobile/traque-app/src/components/game/Toasts.jsx b/mobile/traque-app/src/components/game/Toasts.jsx
index a3eb814..b93c80f 100644
--- a/mobile/traque-app/src/components/game/Toasts.jsx
+++ b/mobile/traque-app/src/components/game/Toasts.jsx
@@ -22,28 +22,28 @@ export const Toasts = () => {
{
condition: userState === USER_STATE.PLACEMENT,
id: 'placement',
- text: ready ? t("interface.placed") : t("interface.not_placed"),
+ text: ready ? t("play.toast.placed") : t("play.toast.not_placed"),
toastColor: ready ? "rgb(25, 165, 25)" : "rgb(204, 51, 51)" ,
textColor: "white"
},
{
condition: userState === USER_STATE.PLAYING && !outOfZone && enemyHasHandicap,
id: 'enemy_revealed',
- text: t("interface.enemy_position_revealed"),
+ text: t("play.toast.enemy_position_revealed"),
toastColor: "white",
textColor: "black"
},
{
condition: userState === USER_STATE.PLAYING && outOfZone && hasHandicap,
id: 'out_of_zone',
- text: `${t("interface.go_in_zone")}\n${t("interface.team_position_revealed")}`,
+ text: `${t("play.toast.go_in_zone")}\n${t("play.toast.team_position_revealed")}`,
toastColor: "white",
textColor: "black"
},
{
condition: userState === USER_STATE.PLAYING && outOfZone && !hasHandicap,
id: 'has_handicap',
- text: `${t("interface.go_in_zone")}\n${t("interface.out_of_zone_message", {time: secondsToMMSS(outOfZoneTimeLeft)})}`,
+ text: `${t("play.toast.go_in_zone")}\n${t("play.toast.out_of_zone_message", {time: secondsToMMSS(outOfZoneTimeLeft)})}`,
toastColor: "white",
textColor: "black"
}
diff --git a/mobile/traque-app/src/hooks/usePickImage.jsx b/mobile/traque-app/src/hooks/usePickImage.jsx
index 5809b2b..28c0a39 100644
--- a/mobile/traque-app/src/hooks/usePickImage.jsx
+++ b/mobile/traque-app/src/hooks/usePickImage.jsx
@@ -33,7 +33,7 @@ export const usePickImage = () => {
}
} catch (error) {
console.error('Error picking image;', error);
- Alert.alert(t("error.title"), t("error.image_selection"));
+ Alert.alert(t("error.default.title"), t("error.default.image_selection"));
}
}, [t]);
diff --git a/mobile/traque-app/src/i18n/locales/en.json b/mobile/traque-app/src/i18n/locales/en.json
index 0db3279..db2e9da 100644
--- a/mobile/traque-app/src/i18n/locales/en.json
+++ b/mobile/traque-app/src/i18n/locales/en.json
@@ -1,3 +1,83 @@
{
-
+ "common": {
+ "no_value": "Unavailable"
+ },
+ "location-permission": {
+ "title": "Please enable background location in settings and restart the app.",
+ "subtitle": "Each team's location must be known by the server and organizers to ensure the game runs smoothly."
+ },
+ "login": {
+ "header": {
+ "title": "LA TRAQUE"
+ },
+ "form": {
+ "team_id_input": "Team ID",
+ "image_label": "Tap to change team photo",
+ "image_sublabel": "Upper body must be visible",
+ "validate_button": "Validate"
+ }
+ },
+ "wait": {
+ "title": "Rules Reminder !",
+ "placement_rule": "Go to your starting zone and wait for the game to begin.",
+ "capture_rule": "Track your target using their photo and the positions they reveal. To obtain your target's last known position, you must reveal your own. Once captured, enter their code in the app.",
+ "zone_rule": "Move on foot while making sure to stay within the game zone to avoid penalties ! If you stay outside the zone for too long, your interface will be disabled and your hunter will know your exact position.",
+ "team_rule": "Set up team strategies ! But always stay within earshot, do not communicate with other teams, and remain in public areas."
+ },
+ "play": {
+ "info": {
+ "zone_reduction_label": "Zone reduction in",
+ "send_position_label": "Position sent in"
+ },
+ "toast": {
+ "placed": "Placed",
+ "not_placed": "Not placed",
+ "enemy_position_revealed": "Enemy position continuously revealed !",
+ "go_in_zone": "Return to the zone !",
+ "team_position_revealed": "Position continuously revealed.",
+ "out_of_zone_message": "Handicap in {{time}}"
+ },
+ "map": {
+ "previous_marker_title": "Position sent",
+ "previous_marker_description": "This is your last position known by the server",
+ "enemy_marker_title": "Enemy position",
+ "enemy_marker_description": "This is the last known position of your enemies"
+ },
+ "drawer": {
+ "capture_code": "{{name}}'s code : {{code}}",
+ "target_name": "Target ({{name}})",
+ "target_code_input": "Target code",
+ "stat_distance_label": "Distance traveled",
+ "stat_time_label": "Elapsed time (HH:MM:SS)",
+ "stat_speed_label": "Average speed",
+ "stat_capture_label": "Total captures by your team",
+ "stat_reveal_label": "Total times your position was sent"
+ }
+ },
+ "info": {
+ "default": {
+ "title": "Info"
+ },
+ "succes": {
+ "title": "Success !",
+ "capture_success": "You have successfully captured your target. A new target has been assigned to you."
+ },
+ "failure": {
+ "title": "Failure...",
+ "capture_failure": "The capture failed. Please check the code and try again."
+ }
+ },
+ "error": {
+ "default": {
+ "title": "Error",
+ "invalid_team_id": "Please enter a valid team ID.",
+ "unknown_team_id": "Unknown team ID.",
+ "server_connection": "Server connection failed.",
+ "image_selection": "An error occurred during image selection."
+ },
+ "permission": {
+ "title": "Permission denied",
+ "storage_acces": "Enable storage or gallery access in settings."
+ }
+ }
}
diff --git a/mobile/traque-app/src/i18n/locales/fr.json b/mobile/traque-app/src/i18n/locales/fr.json
index a7ad7cc..bda3fd3 100644
--- a/mobile/traque-app/src/i18n/locales/fr.json
+++ b/mobile/traque-app/src/i18n/locales/fr.json
@@ -1,8 +1,12 @@
{
- "general": {
+ "common": {
"no_value": "Indisponible"
},
- "index": {
+ "location-permission": {
+ "title": "Veuillez activer la localisation en arrière plan dans les paramètres et relancer l'application.",
+ "subtitle": "La localisation de chaque équipe doit être connue par le serveur et les organisateurs pour veiller au bon déroulement du jeu."
+ },
+ "login": {
"header": {
"title": "LA TRAQUE"
},
@@ -13,24 +17,27 @@
"validate_button": "Valider"
}
},
- "interface": {
- "placed": "Placé",
- "not_placed": "Non placé",
- "zone_reduction_label": "Réduction de la zone dans",
- "send_position_label": "Position envoyée dans",
- "enemy_position_revealed": "Position ennemie révélée en continue !",
- "waiting_default_message": "Préparation de la partie",
- "placement_default_message": "Phase de placement",
- "go_in_zone": "Retournez dans la zone !",
- "team_position_revealed": "Position révélée en continue.",
- "out_of_zone_message": "Handicap dans {{time}}",
- "playing_message": "La partie est en cours",
- "winner_message": "Vous avez gagné !",
- "loser_message": "Vous avez perdu...",
- "captured_message": "Vous avez été éliminé...",
+ "wait": {
+ "title": "Rappel des règles !",
+ "placement_rule": "Rejoignez votre zone de départ et attendez le début de la partie.",
+ "capture_rule": "Traquez votre cible grâce à sa photo et aux positions qu'elle révèle. Pour obtenir la dernière position connue de votre cible, vous devrez révéler la vôtre. Une fois capturée, entrez son code dans l'application.",
+ "zone_rule": "Déplacez-vous à pied tout en veillant à rester dans la zone de jeu pour ne pas être pénalisé ! Si vous restez trop longtemps en dehors de la zone, votre interface sera désactivée et votre chasseur connaîtra précisément votre position.",
+ "team_rule": "Mettez en place des stratégies d'équipe ! Mais restez toujours à portée de voix, ne communiquez pas avec les autres équipes et restez dans les lieux publics."
+ },
+ "play": {
+ "info": {
+ "zone_reduction_label": "Réduction de la zone dans",
+ "send_position_label": "Position envoyée dans"
+ },
+ "toast": {
+ "placed": "Placé",
+ "not_placed": "Non placé",
+ "enemy_position_revealed": "Position ennemie révélée en continue !",
+ "go_in_zone": "Retournez dans la zone !",
+ "team_position_revealed": "Position révélée en continue.",
+ "out_of_zone_message": "Handicap dans {{time}}"
+ },
"map": {
- "team_marker_title": "Position actuelle",
- "team_marker_description": "Ceci est votre position",
"previous_marker_title": "Position envoyée",
"previous_marker_description": "Ceci est votre dernière position connue par le serveur",
"enemy_marker_title": "Position ennemie",
@@ -41,18 +48,33 @@
"target_name": "Cible ({{name}})",
"target_code_input": "Code cible",
"stat_distance_label": "Distance parcourue",
- "stat_time_label": "Temps écoulé au format HH:MM:SS",
+ "stat_time_label": "Temps écoulé (HH:MM:SS)",
"stat_speed_label": "Vitesse moyenne",
"stat_capture_label": "Nombre total de captures par votre équipe",
"stat_reveal_label": "Nombre total d'envois de votre position"
}
},
+ "info": {
+ "default": {
+ "title": "Info"
+ },
+ "succes": {
+ "title": "Bravo !",
+ "capture_success": "Vous avez réussi à capturer votre cible. Une nouvelle cible vient de vous être attribuée."
+ },
+ "failure": {
+ "title": "Raté...",
+ "capture_failure": "La capture a échoué. Vérifiez le code et réessayez."
+ }
+ },
"error": {
- "title": "Erreur",
- "invalid_team_id": "Veuillez entrer un ID d'équipe valide.",
- "unknown_team_id": "L'ID d'équipe est inconnu.",
- "server_connection": "La connexion au serveur a échoué.",
- "image_selection": "Une erreur est survenue lors de la sélection d'une image.",
+ "default": {
+ "title": "Erreur",
+ "invalid_team_id": "Veuillez entrer un ID d'équipe valide.",
+ "unknown_team_id": "L'ID d'équipe est inconnu.",
+ "server_connection": "La connexion au serveur a échoué.",
+ "image_selection": "Une erreur est survenue lors de la sélection d'une image."
+ },
"permission": {
"title": "Permission refusée",
"storage_acces": "Activez l'accès au stockage ou à la gallerie dans les paramètres."