Phrase de restauration dans G1nkgo

[FR]
J’ai continué à investiguer le problème d’incompatibilité avec les graines en français car cela me préoccupait. J’ai découvert qu’il y a un problème de normalisation UTF-8, du moins dans Gecko/Durt2, et probablement quelque chose de similaire se produit dans Cesium2.

Avec ce correctif [1] (qui n’est probablement pas l’endroit le plus approprié pour l’implémenter—il serait préférable de le faire dans Durt2), on résout le problème qui cause des échecs d’importation dans Gecko.

Les phrases accentuées en français, lorsqu’elles sont copiées et collées entre différents emplacements, peuvent changer d’encodage UTF-8 de manière imperceptible à l’œil humain. Cela provoque des conflits dans la validation des mots.

Dans Ginkgo, cela ne se produit pas car la librería bip39_mnemonic effectue automatiquement la normalisation des caractères UTF-8.

[ES]
He continuado investigando el problema de incompatibilidad con semillas en francés porque me preocupaba. Descubrí que hay un problema de normalización de UTF-8, al menos en Gecko/Durt2, y probablemente algo similar ocurra en Cesium2.

Con este parche [1] (que probablemente no sea el lugar más adecuado para implementarlo—sería mejor hacerlo en Durt2), se soluciona el problema que causa fallos de importación en Gecko.

Las frases acentuadas en francés, cuando se copian y pegan entre diferentes ubicaciones, pueden cambiar de codificación UTF-8 de forma imperceptible al ojo humano. Esto causa conflictos en la validación de palabras.

En Ginkgo esto no ocurre porque la librería bip39_mnemonic ya realiza automáticamente la normalización de caracteres UTF-8.

[1] See unorm.nfc

diff --git a/lib/services/mnemonic_service.dart b/lib/services/mnemonic_service.dart
index 81709de3..be8ba680 100644
--- a/lib/services/mnemonic_service.dart
+++ b/lib/services/mnemonic_service.dart
@@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:gecko/globals.dart';
+import 'package:unorm_dart/unorm_dart.dart' as unorm;
 
 /// Service for handling BIP39 mnemonic operations.
 ///
@@ -60,7 +61,9 @@ class MnemonicService {
   /// Returns a [MnemonicResult] with the validated mnemonic or null if invalid.
   static Future<MnemonicResult?> validateAndProcessMnemonic(String inputMnemonic) async {
     try {
-      final words = inputMnemonic.trim().split(' ');
+      // Normalize to NFC (composed form) - important for accented characters like French
+      final normalizedMnemonic = unorm.nfc(inputMnemonic.trim());
+      final words = normalizedMnemonic.split(' ');
       if (words.length != 12) {
         return null; // Invalid length
       }
@@ -75,10 +78,10 @@ class MnemonicService {
       String englishMnemonic;
       if (detectedLanguage == BidouilleLang.english) {
         // Input is already English
-        englishMnemonic = inputMnemonic;
+        englishMnemonic = normalizedMnemonic;
       } else {
         // Convert to English for crypto operations
-        englishMnemonic = await multilangService.convertToEnglish(inputMnemonic, sourceLanguage: detectedLanguage);
+        englishMnemonic = await multilangService.convertToEnglish(normalizedMnemonic, sourceLanguage: detectedLanguage);
       }
 
       // Validate the English mnemonic with BIP39
@@ -87,7 +90,7 @@ class MnemonicService {
       }
 
       return MnemonicResult(
-        displayMnemonic: inputMnemonic,
+        displayMnemonic: normalizedMnemonic,
         englishMnemonic: englishMnemonic,
         originalLanguage: detectedLanguage,
       );
@@ -149,7 +152,8 @@ class MnemonicService {
       // Validate each word
       final validWords = <String>[];
       for (final word in words) {
-        final cleanWord = word.trim().toLowerCase();
+        // Normalize to NFC (composed form) - important for accented characters like French
+        final cleanWord = unorm.nfc(word.trim().toLowerCase());
         if (await isValidBip39Word(cleanWord, preferredLanguage: preferredLanguage)) {
           validWords.add(cleanWord);
         } else {
4 Likes