Android String File equivalent in iPhone(Monotouch) - android

In android we have files by name String. Developers define the string values that they used for naming objects in this file. This is a very useful way. Because avoid of hard coding string values(you can change them from a single file, less time to change), also useful to creating multi language application and etc. (for more info just google this).
But the question is this: whether iPhone(Monotouch) have a mechanism like this to define strings on them or developers have to define themselves mechanism for this?

In XCode, you'll find File/New File, then on the left, pick "Resource", and you'll find "Strings File".
From code, you'll be referencing the keys in your strings file with NSLocalizedString:
NSLog("%#", NSLocalizedString(#"YOUR-STRING-KEY-OR-DEFAULT-VALUE", #"Comment about what this is"));
For details on what that second param is for, What is the second parameter of NSLocalizedString()?

Put your strings in a single file. Make them global constants. Access them throughout the app. When you change these, the change will be reflected everywhere.
It's not a big deal to have persistent string references throughout your app. It can be done in any decent programming language and platform I suppose.

Related

How to parameterise all strings in android application

I am building an application and I am thinking of how to "parametrise" all the strings in the application (is it even possible) in order to allow me to change them easily without "redeploying" it again ...
meaning it will be somewhere in a file with strings (something like you have PO files in PHP when using templates and different languages) where I can manage it ..
it might be useful when I would like to use different languages :)
I am kinda struggling on this one, so I was thinking if you can give me a clue or show me where to "go" to study how this should be implemented ..
Thanks
If you want different langage in your app, create as many strings.xml files as you need. However, when you add new strings file, you have to redeploy.
To avoid that, you should call a specific API in backend which send you all the texts according to the langage of the device. For that you must manage back and front.
So if I understand your question correcly go to res - >value folder -> strings.xml - > open it and you will see something like this:
<string name="app_name">this is your app name</string>
And now every time that you want text to be "this is your app name" all you need to do is to add this line:
android:text="#string/app_name"
And when you will change the actual string in strings.xml it will also change in every place he is being used (android:text="#string/app_name")
Android has a built-in mechanism for localising assets (Strings included)
https://developer.android.com/guide/topics/resources/localization#creating-alternatives
What you are trying to do is known as 'Localisation', this can be helpful if you want to give users different language support and similar kind of stuff.
In android, this is done by putting all the strings in the Strings.xml file located in the res folder.
If you're using android studio, just press Alt + Enter on any hardcoded string and then select 'Extract string resource' from the popup, give the name of the string and Voila! you're done.
It is also a part of good coding practice, in fact you've might have noticed 'Lint warnings' in your layout files if you type any hardcoded string, and it asks you to add this string in the strings.xml file
You can create a separate String file for each language that you wanna include.
Option 1
Using the Default Built-In Mechanism
You already have answers about this or you can read the official documentation about it.
Essentially, you maintain an xml file called strings.xml which is a key-value of Strings. Each file (one per language) will be located in a values folder. E.g.: for french, you'd want values-fr/strings.xml. Each file will include all the translated strings. If a value is not found in French, then the english file will be searched instead as a fallback. If the key is not there, the app will crash (if I am not mistaken).
Pros
Included with the system
Supports many languages
Packed at compile time, always available.
Cons
Resources are "read-only" once they are compiled; you cannot change a string and save the change this way.
Option 2
Roll your own Thing.
If you need to be able to dynamically alter these strings, you'll need a few key pieces:
A way to obtain/download said strings.
A default in case step 1 fails (what if the user cannot download them?) You need defaults.
To ensure every widget that needs to display text, calls your own creation of a class that can manage said dynamic strings (i'll elaborate down below)
You need to know what to do if a String is somehow magically missing; because this is dynamic, there has to be a fallback in case the string is not found (see 2)
This has to be relatively fast (you don't want expensive lookups when constructing strings and UI elements).
Pros
You can model this the way it works best for you
You will be able to load strings as you see fit and even change them at runtime.
Cons
You have to build all this.
It's error prone, and most likely slower than the native solution.
You must ensure you don't miss strings and that you have dafults.
You must modify normal widgets (say TextView) to understand how to fetch the strings (or you must always provide them), and this is not going to be automatic, you'll either have to delegate or subclass into a YourCustomTextViewThatUnderstandsYourStringThing extends TextView (name... is just a draft ;) )
You must ensure you don't leak memory by keeping strings in memory you don't care anymore.
If you want to "persist" these downloaded languages (and you should), you have to write/use your own persisting mechanism (either by writing the files or by using some database, shared preferences is not the place for these).
You need to cache them (see above) and manage the validity of the strings (what if they become old, can they become old? when should you re-fetch them?)
etc.
As you can see it's not trivial and each app has its own world of problems to solve, but that's roughly what it means.
As for "code"... the simplest way I can think of (or rather, the bare basics) are:
Find a way to "store" the strings: e.g.:
Map<String, String> oneLanguage
So in this Map, you store the KEY (to find the value) and the VALUE:
oneLanguage.put("app_name", "My Super App")
Keep all the strings in one place in memory:
Map<String, Map<String, String>> allLanguages
so then you do:
allLanguages.put("English", oneLanguage);
Now you can add other languages:
anotherLanguage.put("app_name", "Mi Super App"); //my Spanish is top-notch
allLanguages.put("Spanish", anotherLanguage);
Now you have a place where to store (in memory) all your keys/values for each language.
When you want to retrieve Spanish, you'd have a method like:
String getString(#NonNull String locale, #NonNull String key) {
return allLanguages.get(locale).get(key);
}
And then you'd need to (either manually or via subclassing or whatever approach you find more convenient) to set these strings like:
// I mean, don't hardcode the locale... but you get the idea.
appNameTextView.setText(yourLanguageManager.getString("Spanish", "app_name"));
What approach you take for this last step, is entirely up to you.
As usual, all the above is pseudo-code, and not a complete solution to this approach. Things you want to do: ask the device what locale is using, keep track of which locale is in use (so you don't have to pass it every time), fetch these locales from your server (not pictured) :), persist these to disk, as well as save in shared preferences, the "locale" key that the user has selected, add methods to your yourLanguageManager so it can have things like:
boolean updateLocale(String locale, Map<String, String newStrings)
boolean deleteLocale(String locale)
Map<String, String> getLocale(String locale)
etc.. you get the idea.
All in all, it's just a simple data structure that can contain keys and values.
Good luck!

Is there a way to override getString() for resources the android framework inflates?

Is there any way to intercept the Android framework's inflation of xml resources (menus and layouts) to change the strings it uses (e.g. for attributes like android:text="#string/button_trade_commit".)
I know it's possible to override getString() as it's called from an Activity. But framework code doesn't seem to use getString(). For example, in MenuInflator.java, strings come from mContext.obtainStyledAttributes(), and obtainStyledAttributes() is final: I can't override it.
Anybody know of another way to accomplish this?
Background: I want to allow non-English-speaking users to localize my app themselves. I imagine an interface that displays the English strings and lets them enter a translation which is then used in place of the English string from then on. I can imagine also providing a "Share translations" button that uploads the translations, and then,
on the server side, incorporating them into a downloadable module that other users of the same language would get. Being able to substitute strings at runtime is the blocking piece that I can't figure out.
I don't believe you can override the systems getString() methods the way you are looking at it.
It might be worth trying to use a custom attribute and handle the work there: http://developer.android.com/training/custom-views/create-view.html#customattr
I don't think you will be able to modify the process Android uses when inflating resources the way you wanted to.
What you can do is to simply not provide any strings (android:text, etc.) in XML files. You can always obtain a reference to any element in your XML file in the code. Once you have a reference, you can provide texts in the code, taking properly localized strings from your custom framework.
I am not sure about this, but i think you can examine the source of Calligraphy library for Android. It is overriding system LayoutInflater to change the FontType, so i imagine you can do the same to change the strings.

Benefit of Declaring String as Resource in strings.xml file

I have read in many places that you should declare your String objects in your resource file but I haven't read about any benefits anywhere.
I have already declared all my Strings that I have in my layouts as resources but I haven't done so in my classes.
My question is:
What are the benefits of declaring Strings as a resource? Are there any memory benefits?
Internationalisation,
Keeping all of your strings in a single place (where they can be editted globally),
Changing strings based on device (mdpi/large/portrait)... I mean, it'd be really rare for this
last one, but it's possible.
Sharing the same string among many layouts (this will happen in any app which isn't tiny)
The top one I reckon is: Translations! Put a new strings.xml in the right folder and the app translates itself for each device.
But there's a matter of organisation too. Just like the layout, you normally don't build in the code, because that's not the place for it.
The code is to process stuff. The string is just one more of the resources that your code will use to show stuff on the screen.
One of the main benefits is for localization: you keep your code language-independent and just need to provide a different XML file for each language you want to support.

Android - Ant - validate layout xml files for android:text="#string/" pattern

As part of an automated build for android projects, I want to validate the layout xml files contains a string reference (i.e. pointing to strings.xml) such as
android:text="#string/what_ever_identifier"
and not something like
android:text="a string not referenced in strings.xml"
If the text contains absolute strings, then I want the build process to fail.
I searched for the appropriate ant tasks but could not find any. The closest I saw was ReplaceRegExp. But I do not want the replace functionality of regex. I need something similar to grep.
Any pointers on how I can achieve this?
I think what you are probably looking for is the "-z" flag passed to aapt, which has it require that any strings it knows are displayed to the user come from string resources that can be localized rather than string literals.

Should keys be placed on a xml to be accessed with R.string.key?

I usually place my keys on an xml and access them with R.string.key_name but someone make me notice that I could have inline strings in the code.
I feel that I might use that key in different places and if I change its name I would just rename in the xml but perhaps that doesn't make too much sense with keys.
What do you think?
Your question conflates two different questions:
Does it make sense to have a single definition of your key?
Does it make sense for this single definition to be within an XML file?
The answer to point 1 is clearly "yes". Duplicating strings used as keys (which need to be the same everywhere for your code to function correctly) is a recipe for pain and heartache.
But what benefit does putting the key in an XML file give you? You're just adding "noise" to your code, and ensuring that whoever reads it has to find, understand and look in at least one additional file.
public static final is the way to go.
Inline literal strings will be a massive pain to change if they get scattered through the code. Localizing them in one place with either the strings.xml or a defining a public final static variable will probably save you a headache later.

Categories

Resources