88 votes

Comment obtenir une chaîne de caractères à partir de différentes langues dans Android ?

Je souhaite donc obtenir la valeur d'une chaîne de caractères dans plusieurs langues, indépendamment des paramètres linguistiques de l'appareil ou de l'application. Comment faire ?

En fait, ce dont j'ai besoin, c'est d'une fonction getString(int id, String locale) plutôt que getString(int id)

Comment pourrais-je faire cela ?

Remerciements

1 votes

Comment l'avez-vous mis en œuvre ? Merci de me répondre :)

0 votes

Comme réponse acceptée

0 votes

Sont ResourceBundle ou peuvent-ils accéder à notre dossier de ressources ?

168voto

Ted Hopp Points 122617

NOTE Si votre API minimum est de 17+, passez directement au bas de cette réponse. Sinon, lisez la suite...

NOTE Si vous utilisez des App Bundles, vous devez vous assurer que vous désactivez la séparation des langues ou que vous installez les différentes langues de manière dynamique. Voir aussi https://stackoverflow.com/a/51054393 pour cela. Si vous ne le faites pas, le système utilisera toujours la solution de repli.

Si vous avez plusieurs dossiers res pour différentes localités, vous pouvez faire quelque chose comme ceci :

Configuration conf = getResources().getConfiguration();
conf.locale = new Locale("pl");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources resources = new Resources(getAssets(), metrics, conf);
String str = resources.getString(id);

Vous pouvez également redémarrer votre activité en utilisant la méthode indiquée par @jyotiprakash.

NOTE Appeler le Resources comme cela modifie quelque chose en interne dans Android. Vous devrez invoquer le constructeur avec votre locale d'origine pour rétablir les choses telles qu'elles étaient.

EDIT Une recette légèrement différente (et un peu plus propre) pour récupérer les ressources d'un lieu spécifique est la suivante :

Resources res = getResources();
Configuration conf = res.getConfiguration();
Locale savedLocale = conf.locale;
conf.locale = desiredLocale; // whatever you want here
res.updateConfiguration(conf, null); // second arg null means don't change

// retrieve resources from desired locale
String str = res.getString(id);

// restore original locale
conf.locale = savedLocale;
res.updateConfiguration(conf, null);

À partir du niveau 17 de l'API, vous devez utiliser conf.setLocale() au lieu de définir directement conf.locale . Cela permet de mettre à jour correctement le sens de présentation de la configuration si vous passez d'une locale à l'autre, de droite à gauche ou de gauche à droite. (Le sens de la mise en page a été introduit en 17.)

Il est inutile de créer un nouveau Configuration (comme le suggère @Nulano dans un commentaire) parce que l'appel à l'objet updateConfiguration va modifier la configuration originale obtenue par l'appel à res.getConfiguration() .

J'hésiterais à regrouper tout cela dans une getString(int id, String locale) si vous devez charger plusieurs chaînes de caractères pour une locale. Changer de locale (en utilisant l'une ou l'autre des recettes) demande au framework de faire beaucoup de travail pour relier à nouveau toutes les ressources. Il est préférable de mettre à jour les locales une fois, de récupérer tout ce dont vous avez besoin, puis de rétablir les locales.

EDIT (Merci à @Mygod) :

Si votre niveau API minimum est de 17+, il existe une bien meilleure approche, comme le montre l'exemple suivant cette réponse sur un autre sujet. Par exemple, vous pouvez créer plusieurs Resource un pour chaque locale dont vous avez besoin, avec :

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) {
    Configuration conf = context.getResources().getConfiguration();
    conf = new Configuration(conf);
    conf.setLocale(desiredLocale);
    Context localizedContext = context.createConfigurationContext(conf);
    return localizedContext.getResources();
}

Il suffit ensuite d'extraire les ressources souhaitées de la base de données localisée. Resource renvoyé par cette méthode. Il n'est pas nécessaire de réinitialiser quoi que ce soit une fois les ressources récupérées.

35voto

Johnson_145 Points 1098

Voici une version combinée des approches décrites par Ted Hopp . Ainsi, le code fonctionne pour toutes les versions d'Android :

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) {
    String result;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api
        Configuration config = new Configuration(context.getResources().getConfiguration());
        config.setLocale(requestedLocale);
        result = context.createConfigurationContext(config).getText(resourceId).toString();
    }
    else { // support older android versions
        Resources resources = context.getResources();
        Configuration conf = resources.getConfiguration();
        Locale savedLocale = conf.locale;
        conf.locale = requestedLocale;
        resources.updateConfiguration(conf, null);

        // retrieve resources from desired locale
        result = resources.getString(resourceId);

        // restore original locale
        conf.locale = savedLocale;
        resources.updateConfiguration(conf, null);
    }

    return result;
}

Exemple d'utilisation :

String englishName = getLocaleStringResource(new Locale("en"), R.string.name, context);

Note

Comme indiqué dans la réponse initiale, il pourrait être plus efficace de remplacer les multiples appels du code ci-dessus par une seule modification de la configuration et plusieurs appels à resources.getString().

4voto

Amr Jyniat Points 177

Sur la base des réponses ci-dessus qui sont impressionnantes mais un peu complexes. essayez cette fonction simple :

public String getResStringLanguage(int id, String lang){
    //Get default locale to back it
    Resources res = getResources();
    Configuration conf = res.getConfiguration();
    Locale savedLocale = conf.locale;
    //Retrieve resources from desired locale
    Configuration confAr = getResources().getConfiguration();
    confAr.locale = new Locale(lang);
    DisplayMetrics metrics = new DisplayMetrics();
    Resources resources = new Resources(getAssets(), metrics, confAr);
    //Get string which you want
    String string = resources.getString(id);
    //Restore default locale
    conf.locale = savedLocale;
    res.updateConfiguration(conf, null);
    //return the string that you want
    return string;
}

Il suffit alors de l'appeler : String str = getResStringLanguage(R.string.any_string, "en");

Bon code :)

0voto

Alex Points 11

Cela pourrait-il se faire par exemple ?

String stringFormat = getString(stringId);
String string = String.format(Locale.ENGLISH, stringFormat, 6);

0voto

object Language {

    var locale: Locale? = null

    fun getLocaleStringResource(
        resourceId: Int,
        requestedLocale: Locale? = locale,
    ): String = with(game.activity) { Configuration(resources.configuration).run {
        setLocale(requestedLocale)
        createConfigurationContext(this).getText(resourceId).toString()
    } }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X