diff --git a/demo-app/LOCALISATION.md b/demo-app/LOCALISATION.md new file mode 100644 index 0000000..9836451 --- /dev/null +++ b/demo-app/LOCALISATION.md @@ -0,0 +1,117 @@ +# Guide de Localisation / Localization Guide + +## Français + +### Fonctionnalité ajoutée + +L'application Android Remote Notify Demo App supporte maintenant le français ! L'application détecte automatiquement la langue du système et affiche l'interface dans la langue appropriée. + +### Langues supportées + +- **Anglais** (par défaut) - `values/strings.xml` +- **Français** - `values-fr/strings.xml` + +### Comment tester + +1. **Pour tester en français :** + - Allez dans les Paramètres de votre appareil Android + - Sélectionnez "Langues et entrée" ou "Language & input" + - Changez la langue principale vers "Français" + - Redémarrez l'application + +2. **Pour tester en anglais :** + - Remettez la langue de l'appareil en "English" + - Redémarrez l'application + +### Éléments traduits + +- Titre de l'application +- Interface principale (enregistrement du token) +- Écran des paramètres +- Messages d'état et d'erreur +- Messages toast (notifications temporaires) +- Menu et navigation + +### Ajouter d'autres langues + +Pour ajouter une nouvelle langue (ex: espagnol) : + +1. Créez un nouveau dossier : `app/src/main/res/values-es/` +2. Copiez le fichier `strings.xml` depuis `values/` +3. Traduisez toutes les chaînes de caractères +4. Testez avec un appareil configuré en espagnol + +--- + +## English + +### Added Feature + +The Remote Notify Demo App Android application now supports French! The app automatically detects the system language and displays the interface in the appropriate language. + +### Supported Languages + +- **English** (default) - `values/strings.xml` +- **French** - `values-fr/strings.xml` + +### How to Test + +1. **To test in French:** + - Go to your Android device Settings + - Select "Languages and input" + - Change the primary language to "Français" (French) + - Restart the application + +2. **To test in English:** + - Change device language back to "English" + - Restart the application + +### Translated Elements + +- Application title +- Main interface (token registration) +- Settings screen +- Status and error messages +- Toast messages (temporary notifications) +- Menu and navigation + +### Adding Other Languages + +To add a new language (e.g., Spanish): + +1. Create a new folder: `app/src/main/res/values-es/` +2. Copy the `strings.xml` file from `values/` +3. Translate all string values +4. Test with a device configured in Spanish + +--- + +## Technical Implementation + +### Structure + +``` +app/src/main/res/ +├── values/ +│ └── strings.xml # English (default) +├── values-fr/ +│ └── strings.xml # French +└── layout/ + ├── activity_main.xml # Uses @string/ references + └── activity_settings.xml # Uses @string/ references +``` + +### Code Changes + +- All hardcoded strings moved to resource files +- Kotlin code updated to use `getString(R.string.resource_name)` +- Layout files updated to use `@string/resource_name` +- Proper parameter formatting with `%1$s`, `%1$d` for dynamic content + +### Best Practices + +- Always use string resources instead of hardcoded text +- Use proper parameter formatting for dynamic strings +- Test all languages on actual devices +- Keep string keys consistent and descriptive +- Add comments to organize string resources diff --git a/demo-app/app/src/main/java/org/nella/rn/demo/MainActivity.kt b/demo-app/app/src/main/java/org/nella/rn/demo/MainActivity.kt index 3978a57..8a24127 100644 --- a/demo-app/app/src/main/java/org/nella/rn/demo/MainActivity.kt +++ b/demo-app/app/src/main/java/org/nella/rn/demo/MainActivity.kt @@ -76,17 +76,17 @@ class MainActivity : AppCompatActivity() { private fun updateStatusWithBackendUrl() { val backendUrl = SettingsActivity.getBackendUrl(this) - updateStatus("Ready to register with backend: $backendUrl") + updateStatus(getString(R.string.status_ready_to_register, backendUrl)) } private fun registerDeviceToken() { - updateStatus("Getting notification token...") + updateStatus(getString(R.string.status_getting_token)) registerButton.isEnabled = false FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> if (!task.isSuccessful) { Log.w(TAG, "Fetching Firebase registration token failed", task.exception) - updateStatus("Failed to get notification token: ${task.exception?.message}") + updateStatus(getString(R.string.status_failed_get_token, task.exception?.message ?: "")) registerButton.isEnabled = true return@addOnCompleteListener } @@ -101,14 +101,14 @@ class MainActivity : AppCompatActivity() { } private fun sendTokenToServer(token: String) { - updateStatus("Encrypting and sending token to server...") + updateStatus(getString(R.string.status_encrypting_token)) // Encrypt the token before sending val encryptedToken = try { encryptToken(token) } catch (e: Exception) { Log.e(TAG, "Failed to encrypt token", e) - updateStatus("Failed to encrypt token: ${e.message}") + updateStatus(getString(R.string.status_failed_encrypt, e.message ?: "")) registerButton.isEnabled = true return } @@ -131,7 +131,7 @@ class MainActivity : AppCompatActivity() { override fun onFailure(call: Call, e: IOException) { Log.e(TAG, "Failed to send token to server", e) runOnUiThread { - updateStatus("Failed to register token: ${e.message}") + updateStatus(getString(R.string.status_failed_register, e.message ?: "")) registerButton.isEnabled = true } } @@ -142,9 +142,9 @@ class MainActivity : AppCompatActivity() { runOnUiThread { if (response.isSuccessful) { - updateStatus("Encrypted token registered successfully!") + updateStatus(getString(R.string.status_success)) } else { - updateStatus("Server error: ${response.code}\n$responseBody") + updateStatus(getString(R.string.status_server_error, response.code, responseBody)) } registerButton.isEnabled = true } diff --git a/demo-app/app/src/main/java/org/nella/rn/demo/SettingsActivity.kt b/demo-app/app/src/main/java/org/nella/rn/demo/SettingsActivity.kt index 63f8244..84a56e4 100644 --- a/demo-app/app/src/main/java/org/nella/rn/demo/SettingsActivity.kt +++ b/demo-app/app/src/main/java/org/nella/rn/demo/SettingsActivity.kt @@ -58,19 +58,19 @@ class SettingsActivity : AppCompatActivity() { // Enable back button supportActionBar?.setDisplayHomeAsUpEnabled(true) - supportActionBar?.title = "Settings" + supportActionBar?.title = getString(R.string.settings_title) } private fun saveUrl() { val url = urlEditText.text.toString().trim() if (url.isEmpty()) { - Toast.makeText(this, "URL cannot be empty", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.toast_url_empty), Toast.LENGTH_SHORT).show() return } if (!isValidUrl(url)) { - Toast.makeText(this, "Please enter a valid URL (e.g., https://example.com)", Toast.LENGTH_LONG).show() + Toast.makeText(this, getString(R.string.toast_url_invalid), Toast.LENGTH_LONG).show() return } @@ -78,7 +78,7 @@ class SettingsActivity : AppCompatActivity() { val cleanUrl = url.trimEnd('/') setBackendUrl(this, cleanUrl) - Toast.makeText(this, "Backend URL saved successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.toast_url_saved), Toast.LENGTH_SHORT).show() // Return to main activity finish() @@ -86,7 +86,7 @@ class SettingsActivity : AppCompatActivity() { private fun resetToDefault() { urlEditText.setText(DEFAULT_BACKEND_URL) - Toast.makeText(this, "Reset to default URL", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.toast_reset_default), Toast.LENGTH_SHORT).show() } private fun isValidUrl(url: String): Boolean { diff --git a/demo-app/app/src/main/res/layout/activity_main.xml b/demo-app/app/src/main/res/layout/activity_main.xml index 64bde54..cf310d1 100644 --- a/demo-app/app/src/main/res/layout/activity_main.xml +++ b/demo-app/app/src/main/res/layout/activity_main.xml @@ -10,7 +10,7 @@ android:id="@+id/titleText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Token Registration" + android:text="@string/title_token_registration" android:textSize="24sp" android:textStyle="bold" app:layout_constraintBottom_toTopOf="@+id/registerButton" @@ -24,7 +24,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" - android:text="Register Device Token" + android:text="@string/button_register_device_token" android:textSize="16sp" app:layout_constraintBottom_toTopOf="@+id/statusText" app:layout_constraintEnd_toEndOf="parent" @@ -38,7 +38,7 @@ android:layout_marginTop="24dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" - android:text="Press the button to register your device token" + android:text="@string/status_press_button" android:textAlignment="center" android:textSize="14sp" app:layout_constraintBottom_toBottomOf="parent" diff --git a/demo-app/app/src/main/res/layout/activity_settings.xml b/demo-app/app/src/main/res/layout/activity_settings.xml index f1578d8..a379dfd 100644 --- a/demo-app/app/src/main/res/layout/activity_settings.xml +++ b/demo-app/app/src/main/res/layout/activity_settings.xml @@ -8,7 +8,7 @@ @@ -16,7 +16,7 @@ @@ -24,7 +24,7 @@ android:id="@+id/urlEditText" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="https://demo.rn.nella.org" + android:hint="@string/settings_url_hint" android:inputType="textUri" android:layout_marginBottom="16dp" android:padding="12dp" @@ -33,7 +33,7 @@ @@ -49,7 +49,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Reset to Default" + android:text="@string/button_reset_default" android:layout_marginEnd="8dp" style="?android:attr/borderlessButtonStyle" /> @@ -58,7 +58,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Save" + android:text="@string/button_save" android:layout_marginStart="8dp" /> @@ -66,7 +66,7 @@ diff --git a/demo-app/app/src/main/res/values-fr/strings.xml b/demo-app/app/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000..36761ae --- /dev/null +++ b/demo-app/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,37 @@ + + + + App de Démo Remote Notify + + + Enregistrement du Token + Enregistrer le Token d’Appareil + Prêt à s’enregistrer avec le backend : %1$s + Appuyez sur le bouton pour enregistrer votre token d’appareil + Récupération du token de notification... + Échec de la récupération du token de notification : %1$s + Chiffrement et envoi du token au serveur... + Échec du chiffrement du token : %1$s + Échec de l’enregistrement du token : %1$s + Token chiffré enregistré avec succès ! + Erreur serveur : %1$d\n%2$s + + + Paramètres + Configuration du Serveur Backend + Entrez l’URL de votre serveur backend d’application : + https://demo.rn.nella.org + Exemples :\n• https://demo.rn.nella.org\n• https://votre-domaine.com\n• https://10.0.2.2:8443 (émulateur Android) + Réinitialiser par Défaut + Enregistrer + \n🔒 Note de Sécurité :\nToute communication utilise des tokens de notification chiffrés. L’URL du backend devrait utiliser HTTPS pour la sécurité. + + + L’URL ne peut pas être vide + Veuillez entrer une URL valide (ex: https://example.com) + URL du backend enregistrée avec succès + Réinitialisation à l’URL par défaut + + + Paramètres + \ No newline at end of file diff --git a/demo-app/app/src/main/res/values/strings.xml b/demo-app/app/src/main/res/values/strings.xml index a72acaa..9425e84 100644 --- a/demo-app/app/src/main/res/values/strings.xml +++ b/demo-app/app/src/main/res/values/strings.xml @@ -1,3 +1,36 @@ + Remote Notify Demo App + + + Token Registration + Register Device Token + Ready to register with backend: %1$s + Press the button to register your device token + Getting notification token... + Failed to get notification token: %1$s + Encrypting and sending token to server... + Failed to encrypt token: %1$s + Failed to register token: %1$s + Encrypted token registered successfully! + Server error: %1$d\n%2$s + + + Settings + Backend Server Configuration + Enter the URL of your app backend server: + https://demo.rn.nella.org + Examples:\n• https://demo.rn.nella.org\n• https://your-domain.com\n• https://10.0.2.2:8443 (Android emulator) + Reset to Default + Save + \n🔒 Security Note:\nAll communication uses encrypted notification tokens. The backend URL should use HTTPS for security. + + + URL cannot be empty + Please enter a valid URL (e.g., https://example.com) + Backend URL saved successfully + Reset to default URL + + + Settings