Is adding strings with placeholders (`{0}`) into resources a good idea?
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.