punto - Android: cómo obtener una cadena en una configuración regional específica SIN cambiar la configuración regional actual
configuracion regional excel (4)
Caso de uso: mensajes de error de registro tal como se muestran al usuario.
Sin embargo, no desea tener mensajes en su registro que dependan de la configuración regional del dispositivo del usuario. Por otro lado, no desea cambiar la configuración regional del dispositivo del usuario solo para su registro (técnico). ¿Se puede lograr esto? Encontré un par de soluciones potenciales aquí en stackoverflow:
- cómo obtener una cadena de diferentes lugares en Android?
- ¿Puedo acceder a recursos de diferentes entornos Android?
- android: obtenga una cadena de la configuración regional predeterminada mediante una cadena en una configuración regional específica
- tal vez incluso Android - Cambio de configuración regional dentro de la aplicación
Sin embargo, todos dan como resultado el cambio de la configuración regional de mi dispositivo (hasta el siguiente cambio de configuración).
De todos modos, mi solución actual es así:
public String getStringInDefaultLocale(int resId) {
Resources currentResources = getResources();
AssetManager assets = currentResources.getAssets();
DisplayMetrics metrics = currentResources.getDisplayMetrics();
Configuration config = new Configuration(
currentResources.getConfiguration());
config.locale = DEFAULT_LOCALE;
/*
* Note: This (temporiarily) changes the devices locale! TODO find a
* better way to get the string in the specific locale
*/
Resources defaultLocaleResources = new Resources(assets, metrics,
config);
String string = defaultLocaleResources.getString(resId);
// Restore device-specific locale
new Resources(assets, metrics, currentResources.getConfiguration());
return string;
}
Para ser honesto, no me gusta este enfoque en absoluto. No es eficiente y, pensando en la concurrencia y todo eso, podría dar lugar a cierta vista en la configuración regional "incorrecta".
Entonces, ¿Alguna idea? Tal vez esto podría lograrse utilizando ResourceBundle s, al igual que en Java estándar?
Puede guardar todas las cadenas de la configuración regional predeterminada en un Map
dentro de una clase global, como la Application
que se ejecuta al iniciar la aplicación:
public class DualLocaleApplication extends Application {
private static Map<Integer, String> defaultLocaleString;
public void onCreate() {
super.onCreate();
Resources currentResources = getResources();
AssetManager assets = currentResources.getAssets();
DisplayMetrics metrics = currentResources.getDisplayMetrics();
Configuration config = new Configuration(
currentResources.getConfiguration());
config.locale = Locale.ENGLISH;
new Resources(assets, metrics, config);
defaultLocaleString = new HashMap<Integer, String>();
Class<?> stringResources = R.string.class;
for (Field field : stringResources.getFields()) {
String packageName = getPackageName();
int resId = getResources().getIdentifier(field.getName(), "string", packageName);
defaultLocaleString.put(resId, getString(resId));
}
// Restore device-specific locale
new Resources(assets, metrics, currentResources.getConfiguration());
}
public static String getStringInDefaultLocale(int resId) {
return defaultLocaleString.get(resId);
}
}
Esta solución no es óptima, pero no tendrá problemas de concurrencia.
Prueba esto:
Configuration conf = getResources().getConfiguration();
conf.locale = new Locale("ar"); // locale I used here is Arabic
Resources resources = new Resources(getAssets(), getResources().getDisplayMetrics(), conf);
/* get localized string */
String appName = resources.getString(R.string.app_name);
Puedes usar esto para API +17
@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static String getStringByLocal(Activity context, int id, String locale) {
Configuration configuration = new Configuration(context.getResources().getConfiguration());
configuration.setLocale(new Locale(locale));
return context.createConfigurationContext(configuration).getResources().getString(id);
}
Actualización : cómo admitir versiones antiguas.
@NonNull
public static String getStringByLocal(Activity context, int resId, String locale) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
return getStringByLocalPlus17(context, resId, locale);
else
return getStringByLocalBefore17(context, resId, locale);
}
@NonNull
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static String getStringByLocalPlus17(Activity context, int resId, String locale) {
Configuration configuration = new Configuration(context.getResources().getConfiguration());
configuration.setLocale(new Locale(locale));
return context.createConfigurationContext(configuration).getResources().getString(resId);
}
private static String getStringByLocalBefore17(Context context,int resId, String language) {
Resources currentResources = context.getResources();
AssetManager assets = currentResources.getAssets();
DisplayMetrics metrics = currentResources.getDisplayMetrics();
Configuration config = new Configuration(currentResources.getConfiguration());
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
/*
* Note: This (temporarily) changes the devices locale! TODO find a
* better way to get the string in the specific locale
*/
Resources defaultLocaleResources = new Resources(assets, metrics, config);
String string = defaultLocaleResources.getString(resId);
// Restore device-specific locale
new Resources(assets, metrics, currentResources.getConfiguration());
return string;
}
Mira este artículo
Para api +17 podríamos usar esto:
public static String getDefaultString(Context context, @StringRes int stringId){
Resources resources = context.getResources();
Configuration configuration = new Configuration(resources.getConfiguration());
Locale defaultLocale = new Locale("en");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleList localeList = new LocaleList(defaultLocale);
configuration.setLocales(localeList);
return context.createConfigurationContext(configuration).getString(stringId);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
configuration.setLocale(defaultLocale);
return context.createConfigurationContext(configuration).getString(stringId);
}
return context.getString(stringId);
}