I have a computed String stored in local variable.
There is no way I can know the string on before hand, however I know for sure in the end it will be one of the Strings whose translations to different languages are inside the string.xml files.
How can I translate such a dynamic string to the current locale?
Although this will take quite long, you could iterate through all the strings, check whether they match, and return the localized version if they do:
public String translatedString(String s)
//Set the locale to en-us
Resources standardResources = context.getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = Locale.US;
Resources defaultResources = new Resources(assets, metrics, config);
//Iterate over string res
Field fields[] = R.string.class.getFields();
for (Field field : fields) {
String value = defaultResources.getString(defaultResources.getIdentifier(field.getName(), "string", this.getPackageName())));
if (value.equals(s)){
return getResources().getString(getResources().getIdentifier(field.getName(), "string", this.getPackageName())));
}
}
return null;
}
Related
I'm getting stuck in this for two days i hope i find a solution..
I'm trying to localize my app (Arabic, and English)
the localization mechanism is working fine, the words, layout directions are working well,
However there are two things are not being localized the first one is numbers.
numbers are not being localized to arabic.
the second one is Font style font style are not being localized neither.
BUT it change the font style and number to arabic, only if i reinstalled the app using my USB and the configuration was in Arabic before the installing. here is my code
public static void changeLocale(Activity context, Bundle... bundles) {
MedfastSharedPreferencesHelper sharakehSharedPreference = new MedfastSharedPreferencesHelper(context);
String lang = sharakehSharedPreference.getKey("locale");
Locale locale = null;
if (null == lang) {
locale = new Locale(Resources.getSystem().getConfiguration().locale.getLanguage());
lang = locale.getDisplayLanguage();
if (locale.getDisplayLanguage().equalsIgnoreCase("English")) {
locale = new Locale("ar");
lang = "ar";
} else {
locale = new Locale("en");
lang = "en";
}
} else if (lang.equalsIgnoreCase("ar")) {
lang = "en";
locale = new Locale("en");
} else if (lang.equalsIgnoreCase("en")) {
lang = "ar";
locale = new Locale("ar");
}
sharakehSharedPreference.setKey("locale", lang);
Resources resources = context.getResources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
Locale.setDefault(locale);
Configuration configuration = resources.getConfiguration();
configuration.setLocale(locale);
configuration.locale = locale;
resources.updateConfiguration(configuration, displayMetrics);
Intent intent = new Intent(context, ((Activity) context).getClass());
if (null != bundles && bundles.length > 0 && null != bundles[0])
intent.putExtras(bundles[0]);
context.startActivity(intent);
context.finish();
}
After researching, android does not support font as resource, so i had do create 6 classes in order to customize my fonts and check weather if the locale is Arabic or english, and depending on the locale i load the font, unlike drawable in android
Hey as Basil Battikhi said, the font does not apply to numbers, But there are some solutions:
1: Create your own custom textView to be able to change things you want.
2: Define this in strings.xml
<string name="number">%1d</string>
and set number to your textView like this:
textCoin.text = getString(R.string.number, it)
3: You can use this code for formating your textView for numbers:
public static String convertEngNumToFa(String number) {
if (AppConstants.FA_LOCALE == DataManager.Language.fa) {
StringBuilder res = new StringBuilder();
try {
for (char _ch : number.toCharArray()) {
if ((int) _ch > 47 && (int) _ch < 58) {
int x = (int) _ch + 1632 - 48;
char ch = (char) (x);
res.append(Character.toString(ch));
} else {
res.append(Character.toString(_ch));
}
}
} catch (Exception e) {
return res.toString();
}
return res.toString();
} else return number;
}
Does android API support translating string resources by value?
I know that I can create multiple XML files for different locale. My problem is that I am getting the values from the server in a "default locale" so, I can't use getString(int).
I want something like getTranslation("myValueInDefaultLocale", "target locale")
There is no efficient way to do what you are asking, but to modify the server. If you can't change server, then you can do this:
Save current locale
Switch to default locale programmatically
Iterate through all string resources looking for specific string
Save ID of the string
Switch back to saved locale
Get translated value of string by ID in desired locale
But this will work really slow. Don't say I didn't warn you.
Here is the code sample:
String translateFrom = "server reply";
Resources res = getResources();
Configuration conf = res.getConfiguration();
Locale savedLocale = conf.locale;
conf.locale = defaultLocale; // set to default locale here
res.updateConfiguration(conf, null);
// iterate through all string resources in default locale
int idTranslateTo = 0;
Field fields[] = R.string.class.getFields();
for (Field field : fields) {
int id = getResources().getIdentifier(field.getName(), "string", this.getPackageName()));
if (translateFrom.equals(res.getString(id)) {
idTranslateTo = id;
break;
}
}
// restore original locale
conf.locale = savedLocale;
res.updateConfiguration(conf, null);
// retrieve translated string from saved locale
if (idTranslateTo != 0) {
String translateTo = res.getString(idTranslateTo);
}
I am trying to override locale configuration in my app. But, I am not able to differentiate between language and their regions.
I am trying following code to override the locale.
Getting locale to override.
Example : "de_DE", "de_AT"
public static Locale getLocaleFromString(#NonNull final String locale) {
String[] split = locale.split("_");
if (split != null || split.length > 1) {
String language = split[0];
String country = split[1];
return new Locale(language, language, country);
}
return Locale.getDefault();
}
The structure of my resource folders is:
values/strings.xml (default strings)
values-de-rDE/strings.xml
values-de-rAT/strings.xml
If, I define values-de/strings.xml, application start reading from this folder.
That means locale overriding works in app, but some how android system is not able to read string from region specific folders.
(My device language is english.)
Any help would be really appreciated.
The arguments passed to Location's constructor may be wrong:
The second should be country and the third should be variant.
So getLocaleFromString should like this:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = getLocaleFromString("de_DE");
res.updateConfiguration(conf, dm);
setContentView(R.layout.activity_main);
}
public static Locale getLocaleFromString(#NonNull final String locale) {
String[] split = locale.split("_");
if (split != null || split.length > 1) {
String language = split[0];
String country = split[1];
return new Locale(language, country);
}
return Locale.getDefault();
}
}
I know there are several ways that I can get the list of all of the Locales supported by the device. Has anyone been able to get the list of locales that you have included in your app?
Using the following code I know I can get the list the device supports:
String[] languages = getAssets().getLocales();
or
String[] languages = Resources.getSystem().getAssets().getLocales();
But I want the list that is shipped w/ my app so i can compare it against the list that the phone supports to create a subset list depending on phone support and app support.
Obviously I could ship w/ a file that has the list of my supported languages, but this is not a route I want to take.
public ArrayList<Locale> getTranslatedLocales(int compairsonStringResourceID, boolean onlyThoseSupportedByThePhone) {
Locale english = Locale.ENGLISH;
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources resources = getResources();
Configuration configuration = resources.getConfiguration();
Locale assignedLanguage = configuration.locale;
ArrayList<Locale> loc = new ArrayList<Locale>();
ArrayList<String> processed = new ArrayList<String>();
String englishConst = english.getLanguage();
if(onlyThoseSupportedByThePhone) {
String[] locales = resources.getAssets().getLocales();
for (String string : locales) {
if(!string.startsWith(englishConst) && !processed.contains(string)) {
processed.add(string);
loc.add(new Locale(string));
}
}
} else {
Locale[] locales = Locale.getAvailableLocales();
for (Locale locale : locales) {
String language = locale.getLanguage();
if(!locale.getLanguage().equals(englishConst) && !processed.contains(language)) {
processed.add(language);
loc.add(locale);
}
}
}
configuration.locale = english;
Resources res = new Resources(getAssets(), metrics, configuration);
String compareString = res.getString(compairsonStringResourceID);
ArrayList<Locale> supported = new ArrayList<Locale>();
supported.add(english);
for (int i = 0; i < loc.size(); i++) {
configuration.locale = loc.get(i);
res = new Resources(getAssets(), metrics, configuration);
Resources res2 = new Resources(getAssets(), metrics, configuration);
String s2 = res2.getString(compairsonStringResourceID);
if(!compareString.equals(s2)){
supported.add(configuration.locale);
}
}
configuration.locale = assignedLanguage;
setLocale(assignedLanguage);
return supported;
}
I am supporting multiple language using values/strings.xml in my app
My current language is ENGLISH.
I have stored icon names in DB, having different languages.
Called following function with icon name in different languages.
More Explanation:[[
Suppose I search "Coffee" then it will return me index =3 because my language is ENGLISH.
Now for next time i search "Kaffee" then it will not found any string like "Kaffee" because my current language is ENGLISH and it is using values/strings.xml file. but i need return index as 3.]]
Need Result : I want to get return index = 3 every time, whatever is my current language.
My thought : Any how I have to search iconName in all of these three languages, not only from current selected ENGLISH language.
Question : So, it is possible to use all supported language's strings to search and get Correct index ?Please give some guidlines!
getIndexOfIcon("Coffee"); --> returns index = 3
getIndexOfIcon("Kaffee"); --> returns index = 0
getIndexOfIcon("Café");--> returns index = 0
public static int getIndexOfIcon(String iconName)
{
String[] predefined_icon_drawable_names;
predefined_icon_drawable_names = mContext.getResources().getStringArray(R.array.predefined_icon_drawable_names_array);
int indextOfIcon = 0;
try
{
indextOfIcon = Arrays.asList(predefined_icon_drawable_names).indexOf(iconName);
if(indextOfIcon<0)
indextOfIcon = 0;
}
catch (Exception e)
{
indextOfIcon = 0;
e.printStackTrace();
}
return indextOfIcon;
}
Following are the strings.xml
ENGLISH Language:/values/strings.xml
<string-array name="predefined_icon_drawable_names_array">
<item>Default</item>
<item>Bath</item>
<item>Brush Teeth</item>
<item>Coffee</item>
</string-array>
GERMAN Language:/values-de/strings.xml
<string-array name="predefined_icon_drawable_names_array">
<item>Standard</item>
<item>Bad</item>
<item>Pinselzähne</item>
<item>Kaffee</item>
</string-array>
SPANISH Language:/values-es/strings.xml
<string-array name="predefined_icon_drawable_names_array">
<item>Por defecto</item>
<item>Baño</item>
<item>Cepillar dientes</item>
<item>Café</item>
</string-array>
Try this way,hope this will help you to solve your problem...
Note : don't try to forget to set your current language after this code.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("English Index : "+getIndexOfIcon(this,"en","Coffee"));
System.out.println("GERMAN Index : "+getIndexOfIcon(this,"de","Kaffee"));
System.out.println("SPANISH Index : "+getIndexOfIcon(this,"es","Café"));
}
public static int getIndexOfIcon(Context mContext,String languageCode,String iconName)
{
Locale locale;
if(languageCode.equals("de")){
locale = new Locale(languageCode,"DE");
}else if(languageCode.equals("es")){
locale = new Locale(languageCode,"ES");
}else{
locale = new Locale(languageCode,"EN");
}
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
mContext.getResources().updateConfiguration(config,mContext.getResources().getDisplayMetrics());
String[] predefined_icon_drawable_names;
predefined_icon_drawable_names = mContext.getResources().getStringArray(R.array.predefined_icon_drawable_names_array);
int indextOfIcon = 0;
try
{
indextOfIcon = Arrays.asList(predefined_icon_drawable_names).indexOf(iconName);
if(indextOfIcon<0)
indextOfIcon = 0;
}
catch (Exception e)
{
indextOfIcon = 0;
e.printStackTrace();
}
return indextOfIcon;
}
I am not quite sure what you want to achieve, but i had a similar problem and solved it with this code:
String localized = context.getResources().getString(context.getResources().getIdentifier(mCursor.getString(COLUMN_NAME), "string", context.getPackageName()));
COLUMN_NAME comes out of a query and i just ID'ed my strings with the same names. You might can use this to get what you need.