Translate the remaining French and Turkish

mise.toml, the comments in app/build.gradle (corrected where they no
longer described the build: the car build is signed by build-car, and
the updater reads the version from build-car's file name), OTA.md's
message table (now the updater's current English messages), the Turkish
messages quoted in CHANGELOG.md and OTA.md (glossed in English), two
test assertion messages, an icon comment, and the ignition-state comment
in EVHardware.kt. The vendored EVHardware library still has about 120
half-French comment lines; noted in SPECS.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
2026-10-18 17:45:56 +02:00
co-authored by Claude Opus 5.5
parent 5e2e354bdd
commit 29064cf8db
8 changed files with 116 additions and 117 deletions
+68 -71
View File
@@ -1,17 +1,16 @@
# Environnement de développement — EVABRPUploader.
# Development environment with mise (the Nix flake, `nix develop`, is the other way in).
#
# Commité volontairement : il décrit comment construire le projet, pas la machine de
# quelqu'un. Les chemins passent par {{env.HOME}} / JAVA_HOME, jamais en dur.
# Pour une surcharge locale (chemin de keystore, SDK ailleurs), créer un mise.local.toml
# — celui-là reste ignoré par git.
# Committed on purpose: it describes how to build the project, not someone's machine. Paths
# go through {{env.HOME}} / JAVA_HOME, never hard-coded. For a local override (keystore path,
# SDK elsewhere), create a mise.local.toml — that one stays ignored by git.
#
# mise install installe le JDK
# mise run bootstrap installe le SDK Android si absent
# mise run test tests unitaires
# mise tasks liste tout
# mise install installs the JDK
# mise run bootstrap installs the Android SDK if missing
# mise run test unit tests
# mise tasks lists everything
#
# Pourquoi épingler le JDK : le JDK par défaut de la machine (26) n'est pas supporté
# par AGP et fait échouer le build avec une erreur de version de classe peu parlante.
# Why the JDK is pinned: the machine's default JDK (26) is not supported by AGP and fails the
# build with an unhelpful class-version error.
[tools]
java = "17"
@@ -24,42 +23,40 @@ _.path = [
"{{env.HOME}}/Android/Sdk/cmdline-tools/latest/bin",
]
# Version du SDK requise par app/build.gradle (compileSdk = 36).
# SDK version app/build.gradle needs (compileSdk = 36).
COMPILE_SDK = "36"
BUILD_TOOLS = "36.0.0"
# Secrets de SIGNATURE D'APK — sans rapport avec la clé d'API ABRP, qui se saisit dans
# l'application. À définir hors du dépôt : décommenter dans un mise.local.toml (ignoré
# par git) et pointer vers un keystore local, JAMAIS vers un fichier du dépôt.
# APK SIGNING secrets — nothing to do with the ABRP API key, which is entered in the app.
# Set them outside the repository: uncomment in a mise.local.toml (ignored by git) and point
# at a local keystore, NEVER at a file in the repository. The car build is signed by
# `build-car` (flake.nix) instead.
# SIGNING_KEYSTORE = "{{env.HOME}}/.keystores/signing.keystore"
# SIGNING_STORE_PASSWORD = "…"
# SIGNING_KEY_ALIAS = "platform"
# SIGNING_KEY_PASSWORD = "…"
# Gradle doit tourner sur le JDK que mise vient d'installer. Sans -Dorg.gradle.java.home,
# Gradle peut réutiliser un daemon lancé par un autre JDK — typiquement celui embarqué par
# l'extension Java de VS Code, un JRE 21 sans jlink : le build échoue alors sur
# JdkImageTransform, avec un message qui n'a rien à voir avec le code.
# JAVA_HOME est posé par [tools] ci-dessus : $JAVA_HOME est résolu par le shell au moment
# de l'exécution, donc ceci reste portable d'une machine à l'autre.
# ── Émulateur ────────────────────────────────────────────────────────────────────
# Gradle must run on the JDK mise just installed. Without -Dorg.gradle.java.home, Gradle may
# reuse a daemon started by another JDK — typically the one bundled with VS Code's Java
# extension, a JRE 21 without jlink: the build then fails in JdkImageTransform, with a message
# that has nothing to do with the code. JAVA_HOME is set by [tools] above; $JAVA_HOME is
# resolved by the shell at run time, so this stays portable between machines.
# ── Emulator ─────────────────────────────────────────────────────────────────────
#
# ATTENTION sur la fidélité : le véhicule tourne en AAOS 9 (API 28). Google ne publie
# AUCUNE image système Automotive en dessous d'API 33 — vérifié avec sdkmanager --list.
# Il n'existe donc pas d'émulateur qui reproduise à la fois l'OS et l'API voiture du MG4.
# D'où deux profils, chacun fidèle sur un axe :
# A WORD on fidelity: the car runs AAOS 9 (API 28). Google publishes NO Automotive system
# image below API 33 — checked with sdkmanager --list. So no emulator reproduces both the OS
# and the car API of the MG4. Hence two profiles, each faithful on one axis:
#
# emulator-car API 33 Automotive — a bien un CarPropertyManager, mauvaise version
# d'OS. Pour tester le cycle de vie du service et le chemin voiture.
# Les propriétés VENDEUR SAIC (0x216xxxxx : SOC, autonomie) n'existent
# pas dans l'émulateur : ces lectures échoueront, c'est normal.
# emulator-screen API 28 tablette — bonne version d'OS et bon écran (1920x720 @ 160dpi,
# 12,8" HD comme le MG4), mais AUCUN service voiture.
# Pour l'UI, les layouts et la densité.
# emulator-car API 33 Automotive — has a CarPropertyManager, wrong OS version. For the
# service lifecycle and the car path. SAIC VENDOR properties (0x216xxxxx:
# SOC, range) do not exist in the emulator: those reads fail, as expected.
# emulator-screen API 28 tablet — right OS version and right screen (1920x720 @ 160 dpi,
# 12.8" HD like the MG4), but NO car services. For the UI, layouts and
# density. (The AOSP API 28 image also shares the car's platform key, so the
# car build installs there as the system user.)
#
# Rien de tout cela ne remplace un essai sur le véhicule.
# Densité cible du projet : 160 dpi.
# Écran 12,8" 1920x720. Firmware de référence : SWI68-29958-1300R69.
# None of this replaces a test on the car.
# Target density: 160 dpi. Screen 12.8" 1920x720. Reference firmware: SWI68-29958-1300R69.
EMU_CAR_AVD = "evabrp-car"
EMU_CAR_IMAGE = "system-images;android-33;android-automotive;x86_64"
@@ -70,16 +67,16 @@ EMU_HEIGHT = "720"
EMU_DENSITY = "160"
[tasks.bootstrap]
description = "Installe le SDK Android (platform + build-tools) s'il manque"
description = "Installs the Android SDK (platform + build-tools) if missing"
run = """
set -e
if [ -d "$ANDROID_HOME/platforms/android-$COMPILE_SDK" ]; then
echo "SDK $COMPILE_SDK déjà présent → rien à faire"
echo "SDK $COMPILE_SDK already present, nothing to do"
exit 0
fi
mkdir -p "$ANDROID_HOME"
if [ ! -x "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then
echo "Téléchargement des commandline-tools…"
echo "Downloading the command-line tools…"
tmp=$(mktemp -d)
curl -sSL -o "$tmp/tools.zip" \
https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
@@ -92,59 +89,59 @@ yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_H
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" \
"platform-tools" "platforms;android-$COMPILE_SDK" "build-tools;$BUILD_TOOLS"
echo "sdk.dir=$ANDROID_HOME" > local.properties
echo "SDK installé, local.properties écrit"
echo "SDK installed, local.properties written"
"""
[tasks.build]
description = "Compile l'APK debug"
description = "Builds the debug APK"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME assembleStableDebug'
[tasks.test]
description = "Tests unitaires JVM"
description = "JVM unit tests"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME testStableDebugUnitTest testUnstableDebugUnitTest'
[tasks.lint]
description = "Analyse lint Android"
description = "Android lint"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME lintStableDebug lintUnstableDebug'
[tasks.permissions]
description = "Contrôle de dérive des permissions (le même que la CI)"
description = "Permission drift check (the same as CI)"
run = "bash .github/security/check-permissions.sh"
[tasks.check]
description = "Ce que la CI exécute : permissions + lint + tests"
description = "What CI runs: permissions + lint + tests"
depends = ["permissions", "lint", "test"]
[tasks.install]
description = "Installe l'APK debug sur le véhicule connecté en ADB"
description = "Installs the debug APK on the car connected over ADB"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME installStableDebug'
[tasks.logs]
description = "Suit les logs de l'app sur le véhicule"
description = "Follows the app's logs on the car"
run = "adb logcat -s AbrpUploadService:V CarPropertyAdapter:V VhalProbe:V SecurePrefs:V OtaUpdater:V UpdateHook:V NilsMG4.Telemetry:V NilsMG4.Mongo:V NilsMG4.SteeringKey:V EVABRP.Boot:V EVABRP.Wifi:V"
[tasks.release]
description = "APK release des deux canaux (stable sans OTA, unstable avec OTA)"
description = "Release APKs of both channels (stable without OTA, unstable with OTA)"
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME assembleStableRelease assembleUnstableRelease'
[tasks.clean]
run = './gradlew -Dorg.gradle.java.home=$JAVA_HOME clean'
[tasks.emulator-setup]
description = "Installe l'émulateur + les images système et crée les deux AVD"
description = "Installs the emulator and system images and creates both AVDs"
run = '''
set -e
SDK="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager"
AVDM="$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager"
if [ ! -e /dev/kvm ]; then
echo "ERREUR : /dev/kvm absent — pas d'accélération matérielle, l'émulateur sera inutilisable." >&2
echo "Sous WSL2 : activer la virtualisation imbriquée côté Windows." >&2
echo "ERROR: /dev/kvm missing — no hardware acceleration, the emulator would be unusable." >&2
echo "On WSL2: enable nested virtualisation on the Windows side." >&2
exit 1
fi
if ! id -nG | tr ' ' '\n' | grep -qx kvm; then
echo "ATTENTION : utilisateur absent du groupe kvm. Corriger avec :" >&2
echo " sudo usermod -aG kvm $USER # puis se reconnecter" >&2
echo "WARNING: user is not in the kvm group. Fix with:" >&2
echo " sudo usermod -aG kvm $USER # then log in again" >&2
fi
yes | "$SDK" --sdk_root="$ANDROID_HOME" --licenses > /dev/null
@@ -153,13 +150,13 @@ yes | "$SDK" --sdk_root="$ANDROID_HOME" --licenses > /dev/null
create_avd() {
name="$1"; image="$2"; device="$3"
if "$AVDM" list avd 2>/dev/null | grep -q "Name: $name"; then
echo "AVD $name déjà présent"
echo "AVD $name already exists"
else
echo no | "$AVDM" create avd -n "$name" -k "$image" -d "$device" --force
fi
cfg="$HOME/.android/avd/$name.avd/config.ini"
# Écran du MG4. Sans ça l'AVD garde la densité du profil générique et les layouts
# ne ressemblent pas à ce que voit le conducteur.
# The MG4's screen. Without this the AVD keeps the generic profile's density and the
# layouts do not look like what the driver sees.
sed -i '/^hw.lcd/d;/^disk.dataPartition.size/d' "$cfg"
{
echo "hw.lcd.width=$EMU_WIDTH"
@@ -167,55 +164,55 @@ create_avd() {
echo "hw.lcd.density=$EMU_DENSITY"
echo "disk.dataPartition.size=4G"
} >> "$cfg"
echo "AVD $name configuré en ${EMU_WIDTH}x${EMU_HEIGHT} @ ${EMU_DENSITY}dpi"
echo "AVD $name set to ${EMU_WIDTH}x${EMU_HEIGHT} @ ${EMU_DENSITY}dpi"
}
create_avd "$EMU_CAR_AVD" "$EMU_CAR_IMAGE" "automotive_1024p_landscape"
create_avd "$EMU_SCREEN_AVD" "$EMU_SCREEN_IMAGE" "pixel_c"
'''
# swiftshader_indirect, pas « host » : WSL2 n'expose aucun GPU réel (uniquement Mesa
# llvmpipe). Avec -gpu host l'émulateur meurt au démarrage sur « Your GPU cannot be used
# for hardware rendering », avant qu'aucune fenêtre n'apparaisse — d'où l'icône de tray
# sans émulateur visible. Le rendu logiciel est plus lent, mais il démarre.
# swiftshader_indirect, not "host": WSL2 exposes no real GPU (only Mesa llvmpipe). With
# -gpu host the emulator dies at start-up on "Your GPU cannot be used for hardware
# rendering", before any window appears — hence a tray icon and no visible emulator.
# Software rendering is slower, but it starts.
[tasks.emulator-car]
description = "Lance l'émulateur Automotive (API 33 — a un CarPropertyManager)"
description = "Starts the Automotive emulator (API 33 — has a CarPropertyManager)"
run = '''
set -e
"$ANDROID_HOME/emulator/emulator" -avd "$EMU_CAR_AVD" \
-gpu swiftshader_indirect -no-snapshot-save -no-boot-anim &
"$ANDROID_HOME/platform-tools/adb" wait-for-device
echo "Émulateur voiture prêt."
echo "Car emulator ready."
'''
[tasks.emulator-screen]
description = "Lance l'émulateur écran MG4 (API 28, 1920x720 @ 160dpi — pas de service voiture)"
description = "Starts the MG4 screen emulator (API 28, 1920x720 @ 160dpi — no car services)"
run = '''
set -e
"$ANDROID_HOME/emulator/emulator" -avd "$EMU_SCREEN_AVD" \
-gpu swiftshader_indirect -no-snapshot-save -no-boot-anim &
"$ANDROID_HOME/platform-tools/adb" wait-for-device
echo "Émulateur écran prêt."
echo "Screen emulator ready."
'''
[tasks.emulator-stop]
description = "Arrête l'émulateur en cours"
description = "Stops the running emulator"
run = '"$ANDROID_HOME/platform-tools/adb" emu kill || true'
[tasks.run]
description = "Compile, installe et lance l'APK sur l'émulateur ou le véhicule connecté"
description = "Builds, installs and starts the APK on the emulator or the connected car"
depends = ["build"]
run = '''
set -e
ADB="$ANDROID_HOME/platform-tools/adb"
if [ -z "$($ADB devices | sed '1d' | grep -w device || true)" ]; then
echo "Aucun appareil connecté. Lancer d'abord 'mise run emulator-car' ou 'mise run emulator-screen'," >&2
echo "ou brancher le véhicule en ADB." >&2
echo "No device connected. Start 'mise run emulator-car' or 'mise run emulator-screen' first," >&2
echo "or connect the car over ADB." >&2
exit 1
fi
APK=$(ls -t app/build/outputs/apk/stable/debug/*.apk | head -1)
echo "Installation de $APK"
echo "Installing $APK"
$ADB install -r -g "$APK"
$ADB shell am start -n "com.stinnesbeck.nilsmg4/com.evsuite.abrp.MainActivity"
echo "Lancé. Logs : mise run logs"
echo "Started. Logs: mise run logs"
'''