
Il existe un moyen simple d'implémenter le changement de langue dans une application mono-activité. La pile d'écrans dans cette approche n'est pas réinitialisée, l'utilisateur reste là où il a changé de langue. Lorsque l'utilisateur passe aux écrans précédents, ils sont immédiatement affichés traduits. Et le résultat de la localisation des nombres, des sommes d'argent et des intérêts peut surprendre les designers.

Qu'est-ce qui sera discuté et qu'est-ce qui ne sera pas discuté?
De plus, il n'y aura rien sur:
- La théorie qui sous-tend la sortie formatée des chaînes et les détails d'implémentation des bibliothèques qui traitent cela. Autrement dit, quelque chose qui pourrait vous aider à écrire votre bibliothèque.
- Chaîne de ressources , vecteur et autres. À propos des qualificatifs de ressources à utiliser, quelles images en arabe doivent être affichées de droite à gauche, lesquelles ne le sont pas et d'autres subtilités.
- Le processus de traduction centralisée des ressources pour toutes les plateformes. Comment l'organiser pour que tout le monde vive bien, même les surnoms iOS.
Et nous parlerons de:
- Pratique. Considérez le problème, ses limites et sa solution avec des diagrammes, des exemples et des fragments de code.
- API SDK utilisée pour cette solution.
- Caractéristiques de la mise en forme des valeurs numériques pour différentes normes régionales, que les concepteurs doivent connaître.
Que voulons-nous faire?
Qu'il y ait un écran avec des paramètres dans notre application, et nous voulons y ajouter quelques nouveaux éléments, dont l'un vous permettrait de changer la langue de l'application et l'autre de changer la devise dans laquelle les montants sont affichés. Voici quelques exemples de ce à quoi cela pourrait ressembler.


En plus de traduire le texte et d'afficher la mise en page de droite à gauche, ces paramètres doivent affecter le format d'affichage des valeurs numériques. Il est nécessaire que tout soit affiché en fonction des paramètres régionaux sélectionnés.

Solution architecturale
Imaginez que notre demande soit rédigée conformément à l' approche à activité unique . Ensuite, le mécanisme de changement de langue peut être implémenté comme suit.

SettingsInteractor
est la source de la valeur de langue actuelle. Il vous permet de vous abonner à cette valeur, de la recevoir de manière synchrone et de vous abonner uniquement aux mises à jour. Si nécessaire, vous pouvez introduire une abstraction supplémentaire sur SettingsInteractor
selon le principe de la séparation d'interface . Dans le diagramme, les détails non pertinents sont omis.
AppActivity
lors de la création remplace le contexte par un nouveau afin que l'application utilise les ressources pour la langue sélectionnée.
override fun attachBaseContext(base: Context) { super.attachBaseContext(applySelectedAppLanguage(base)) } private fun applySelectedAppLanguage(context: Context): Context { val locale = settingsInteractor.getUserSelectedLanguageBlocking() val newConfig = Configuration(context.resources.configuration) Locale.setDefault(locale) newConfig.setLocale(locale) return context.createConfigurationContext(newConfig) }
AppPresenter
à son tour, s'abonne aux mises à jour linguistiques et notifie View des modifications.
override fun onFirstViewAttach() { super.onFirstViewAttach() subscribeToLanguageUpdates() } private fun subscribeToLanguageUpdates() { settingsInteractor .getUserSelectedLanguageUpdates() .subscribe( { newLang -> viewState.applyNewAppLanguage(newLang) }, { error -> errorHandler.handle(error) } ) .disposeOnDestroy() }
AppActivity
recréé lorsqu'une notification de changement de langue est reçue.
override fun applyNewAppLanguage(lang: Locale) = recreate()

AppActivity
est le seul dans l'application. Tous les autres écrans sont implémentés en fragments. Par conséquent, lors de la recréation de l'activité, la pile d'écrans est enregistrée par le système. Si vous revenez aux écrans précédents, ils seront réinitialisés et affichés traduits. L'utilisateur restera sur la liste de sélection de la langue et verra le résultat de son choix instantanément.
En plus de remplacer le contexte, il est nécessaire de formater les données - nombres, argent, intérêts. Laissez chaque vue déléguer cette tâche à un composant distinct, appelons-le UiLocalizer
.

UiLocalizer
utilise les instances NumberFormat
appropriées pour convertir un nombre en chaîne.
private var numberFormat = NumberFormat.getNumberInstance(lang) private var percentFormat = NumberFormat.getPercentInstance(lang) private fun getNumberFormatForCurrency(currency: Currency) = NumberFormat .getCurrencyInstance(lang) .also { it.currency = currency }
Veuillez noter que la devise doit être définie séparément.
Si vous économisez des cycles CPU et des bits de mémoire, et que le changement de devise et de langue est la fonction principale et souvent utilisée de votre application, alors, bien sûr, vous avez besoin d'un cache.
Représentation des langues et des monnaies
Les instances de la classe Locale
sont créées par une balise de langue , qui se compose d'un code de langue à deux lettres et d'un code de région à deux lettres. Et les instances de la classe Currency
sont basées sur un code ISO à trois lettres . Sous cette forme, la langue et la devise doivent être sérialisées pour être enregistrées sur le disque ou transférées sur le réseau, et ce sera bon. Voici quelques exemples.
Le résultat du formatage des nombres conformément aux normes régionales peut différer de ce qui était attendu. Le symbole monétaire ou son code à trois lettres dans différentes langues sera affiché de différentes manières. Des signes négatifs pour des valeurs monétaires négatives apparaîtront à des endroits inattendus et à certains endroits, des parenthèses seront affichées à la place. Le signe de pourcentage peut ne pas être exactement le signe auquel nous sommes habitués.
Le fait est que, du point de vue des modèles régionaux, la ligne finale se compose d'un préfixe et d'un suffixe pour les nombres positifs et négatifs, d'un millier de séparateurs et d'un séparateur décimal, et ils sont différents pour les différents lieux.
Les chiffres
Devises
Intérêt
De plus, les résultats de formatage pour le SDK Android et le JDK peuvent être différents. De plus, toutes les options sont correctes, chacune d'elles est utilisée dans certains contextes.

Lorsque nous créons un NumberFormat
pour formater certaines valeurs, nous obtenons des objets de la classe DecimalFormat
qui sont simplement configurés par différents modèles. En DecimalFormat
objet en type DecimalFormat
et en utilisant son interface, vous pouvez modifier des parties du modèle pour tout casser. Mais il vaut mieux adorer le don.

Vous pouvez également passer un test pour apprécier la variété. Pas pour tous les paramètres régionaux, la même devise est affichée avec un symbole.

En fin de compte
Le schéma général de la solution est le suivant.

Le AppActivity
vie AppActivity
est le cycle de vie de l'application entière. Par conséquent, il suffit de le recréer pour redémarrer toute l'application et appliquer la langue sélectionnée. Et comme il n'y a qu'une seule activité, il suffit de conserver l'abonnement pour changer la langue en un seul endroit - dans AppPresenter
.
Comme nous l'avons vu, les formats régionaux de sortie des nombres ne sont pas anodins. Vous ne devez pas définir de manière rigide un modèle unique pour toutes les occasions. Il est préférable de confier le formatage du SDK et de convenir que les chiffres seront affichés selon la norme, et non pas comme dessinés sur les mises en page.
Quoi de plus facile à tester? (bonus)
Pour gagner du temps, vous pouvez utiliser le drapeau suivant.
android { ... buildTypes { debug { pseudoLocalesEnabled true } } ... }
Sélectionnez la pseudo-locale souhaitée dans les paramètres du téléphone.

Et regardez comment la mise en page se déroule à cause du long texte, et certains éléments de l'interface utilisateur ne veulent obstinément pas être affichés de droite à gauche.

Plus d'informations peuvent être trouvées dans la documentation .
Il convient de noter que les pseudo-paramètres régionaux ne fonctionneront pas si vous modifiez le contexte, comme dans la solution ci-dessus. Vous changez le contexte. Par conséquent, vous devez ajouter en-XA
et ar-XB
à la liste de sélection de langue dans l'application.
C’est tout. Bonne localisation et bonne humeur!
