Is adding strings with placeholders (`{0}`) into resources a good idea?
I have added a string into a resources file. My application will be localized.
But, is adding strings with placeholders ({0}
) into resources a good idea?
What if some non-technical person does localization? Is there开发者_StackOverflow中文版 a way for them to screw it up, unknowingly?
If this isn't a good idea, what should I do?
Here is simple example. I will be using WPF resource dictionaries.
Example:
// Resource1.resx
// Name | Value
//---------------------------------------------------------------
// RELATIONSHIP_STATUS_MSG | {0} is in relationship with {1}.
//
class Program
{
static void Main(string[] args)
{
string msg = string.Format(Resource1.RELATIONSHIP_STATUS_MSG,
"Romeo", "Juliot");
Console.WriteLine(msg);
}
}
Well, I believe that it's a good idea because this is an easy and quick way of rendering parametrized and localized strings.
By the way, as you say in your question, non-tech people can break your localization strings because they don't understand what's "{0}". I've two "approaches" for solving that problem
Just notice non-tech people maintaining localized strings that they mustn't take care about text in brackets.
Use named placeholders: "{some-identifier}" and just use
someTextResource.Replace("{some-identifier}", someTextVar)
.
About 2nd one, you can implement some method accepting an IDictionary<TKey, TValue>
instance of substitution relations, where the key is the identifier to replace, and value the text to put replacing the identifier.
It depends.
Sometimes you have no choice but to use placeholders, for example for dynamic data. In such case using placeholders, especially numbered ones ({0}, {1}, ...) is not only the good idea but the most acceptable idea from Internationalization perspective. It allows for re-ordering the sentence during translation, which is definitely something you want to support.
As for non-technical people... Well, if you are using professional Software Translation Vendor, there won't make any problem to them, they are just used to translating strings like that. If you want to appoint services of just generic translator, it could pose problem. But in that case I have to warn you that technical translations are specific: translators should at least obey to common software terms glossary.
OK, now on why it depends. Basically, formatting strings with string.Format() is actually concatenation. As I said, if you have dynamic data, you have no choice. But if your data are static, and you have just few combinations, you should never, under any circumstances use placeholders (nor simple string concatenations with concatenation (+) operator, nor more complicated with StringBuilder). For static data, you should simply create as many strings needed.
The real reason for it, is many languages need different forms of translation depending on the context. For example in my mother's tongue (Polish) we use different forms for feminine and masculine nouns.
It is not just theoretical problem: 4 years ago, when I was working in Localization, we had to Localize new major Anti-Virus Software. The problem was, that some programmer optimized resources, so that we had one message similar to that one:
The {0} is inactive. To activate {0} click...
What was substituted for placeholder, was function or program name. In Polish function is feminine, by program is masculine. To make matters worse, our linguist wanted to add words "program" and "funkcja", depending on what actually was inactive.
Obviously, we (Localization Software Engineers) were unable to fix the problem without touching the code (which we were not allowed to do, but it is a different story...).
To summarize:
Use placeholders if you really have to. Disk space is cheap. Avoid concatenations (as this won't allow re-ordering the translated sentence).
Do not worry that much about translator, but remember to give them context (possibly also instructions). It is important for them to know where your string will be displayed and what are possible values.
If you do this make sure you document the behavior for non-technical translators. Otherwise you should be fine.
Use automated testing to verify the integrity of resource files returned by the translation vendors. Ideally, provide vendors with tools that do this during translation time to catch defects as early as possible.
Even though you provide a document for the non-technical translators there are still some chances that they could exploit it(unknowingly), that would other wise not an issue if you handle such case by yourself. I would rather concatenate string.
This is the recommended approach I think. The guidelines for GNU GetText suggest doing this for instance.
As Erno comments, make sure that whoever does the translation knows what the {0}'s stand for.
A benefit of this approach is that you can control where the values are inserted and part of the values formatting as well. The thing you miss is pluralization of values, but that is another discussion.
I usually come up with a naming scheme for these type strings so they stand out in code.
Like Strings.RELATIONSHIP_STATUS_MSG_FORMAT
I like Resharper's naming conventtion:
__0__is_in_relationship_with__1__
Makes it clear what arguments are expected when used from code:
string msg = string.Format(Properties.Resources.__0__is_in_relationship_with__1__,
"Romeo",
"Juliet");
精彩评论