Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions demo-app/LOCALISATION.md
Original file line number Diff line number Diff line change
@@ -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
16 changes: 8 additions & 8 deletions demo-app/app/src/main/java/org/nella/rn/demo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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
}
}
Expand All @@ -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
}
Expand Down
10 changes: 5 additions & 5 deletions demo-app/app/src/main/java/org/nella/rn/demo/SettingsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,35 @@ 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
}

// Remove trailing slash for consistency
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()
}

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 {
Expand Down
6 changes: 3 additions & 3 deletions demo-app/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand Down
14 changes: 7 additions & 7 deletions demo-app/app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Backend Server Configuration"
android:text="@string/settings_backend_config"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginBottom="16dp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enter the URL of your app backend server:"
android:text="@string/settings_enter_url"
android:textSize="16sp"
android:layout_marginBottom="8dp" />

<EditText
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"
Expand All @@ -33,7 +33,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Examples:\n• https://demo.rn.nella.org\n• https://your-domain.com\n• https://10.0.2.2:8443 (Android emulator)"
android:text="@string/settings_examples"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="24dp" />
Expand All @@ -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" />

Expand All @@ -58,15 +58,15 @@
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" />

</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="\n🔒 Security Note:\nAll communication uses encrypted notification tokens. The backend URL should use HTTPS for security."
android:text="@string/settings_security_note"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="24dp"
Expand Down
2 changes: 1 addition & 1 deletion demo-app/app/src/main/res/menu/main_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<item
android:id="@+id/action_settings"
android:title="Settings"
android:title="@string/menu_settings"
android:icon="@android:drawable/ic_menu_preferences"
app:showAsAction="ifRoom" />

Expand Down
37 changes: 37 additions & 0 deletions demo-app/app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Nom de l'application -->
<string name="app_name">App de Démo Remote Notify</string>

<!-- Activité principale -->
<string name="title_token_registration">Enregistrement du Token</string>
<string name="button_register_device_token">Enregistrer le Token d’Appareil</string>
<string name="status_ready_to_register">Prêt à s’enregistrer avec le backend : %1$s</string>
<string name="status_press_button">Appuyez sur le bouton pour enregistrer votre token d’appareil</string>
<string name="status_getting_token">Récupération du token de notification...</string>
<string name="status_failed_get_token">Échec de la récupération du token de notification : %1$s</string>
<string name="status_encrypting_token">Chiffrement et envoi du token au serveur...</string>
<string name="status_failed_encrypt">Échec du chiffrement du token : %1$s</string>
<string name="status_failed_register">Échec de l’enregistrement du token : %1$s</string>
<string name="status_success">Token chiffré enregistré avec succès !</string>
<string name="status_server_error">Erreur serveur : %1$d\n%2$s</string>

<!-- Activité de paramètres -->
<string name="settings_title">Paramètres</string>
<string name="settings_backend_config">Configuration du Serveur Backend</string>
<string name="settings_enter_url">Entrez l’URL de votre serveur backend d’application :</string>
<string name="settings_url_hint">https://demo.rn.nella.org</string>
<string name="settings_examples">Exemples :\n• https://demo.rn.nella.org\n• https://votre-domaine.com\n• https://10.0.2.2:8443 (émulateur Android)</string>
<string name="button_reset_default">Réinitialiser par Défaut</string>
<string name="button_save">Enregistrer</string>
<string name="settings_security_note">\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é.</string>

<!-- Messages toast -->
<string name="toast_url_empty">L’URL ne peut pas être vide</string>
<string name="toast_url_invalid">Veuillez entrer une URL valide (ex: https://example.com)</string>
<string name="toast_url_saved">URL du backend enregistrée avec succès</string>
<string name="toast_reset_default">Réinitialisation à l’URL par défaut</string>

<!-- Menu -->
<string name="menu_settings">Paramètres</string>
</resources>
33 changes: 33 additions & 0 deletions demo-app/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
<resources>
<!-- App name -->
<string name="app_name">Remote Notify Demo App</string>

<!-- Main Activity -->
<string name="title_token_registration">Token Registration</string>
<string name="button_register_device_token">Register Device Token</string>
<string name="status_ready_to_register">Ready to register with backend: %1$s</string>
<string name="status_press_button">Press the button to register your device token</string>
<string name="status_getting_token">Getting notification token...</string>
<string name="status_failed_get_token">Failed to get notification token: %1$s</string>
<string name="status_encrypting_token">Encrypting and sending token to server...</string>
<string name="status_failed_encrypt">Failed to encrypt token: %1$s</string>
<string name="status_failed_register">Failed to register token: %1$s</string>
<string name="status_success">Encrypted token registered successfully!</string>
<string name="status_server_error">Server error: %1$d\n%2$s</string>

<!-- Settings Activity -->
<string name="settings_title">Settings</string>
<string name="settings_backend_config">Backend Server Configuration</string>
<string name="settings_enter_url">Enter the URL of your app backend server:</string>
<string name="settings_url_hint">https://demo.rn.nella.org</string>
<string name="settings_examples">Examples:\n• https://demo.rn.nella.org\n• https://your-domain.com\n• https://10.0.2.2:8443 (Android emulator)</string>
<string name="button_reset_default">Reset to Default</string>
<string name="button_save">Save</string>
<string name="settings_security_note">\n🔒 Security Note:\nAll communication uses encrypted notification tokens. The backend URL should use HTTPS for security.</string>

<!-- Toast messages -->
<string name="toast_url_empty">URL cannot be empty</string>
<string name="toast_url_invalid">Please enter a valid URL (e.g., https://example.com)</string>
<string name="toast_url_saved">Backend URL saved successfully</string>
<string name="toast_reset_default">Reset to default URL</string>

<!-- Menu -->
<string name="menu_settings">Settings</string>
</resources>
Loading