In C# I use resource strings and string.Format for localization. Sometimes I need to generate a message from an arbitrarily-sized list of terms. (Example: "You must select one of Dog, Cat, or Monkey" from list ["Dog", "Cat", "Monkey"])
I can write code to produce that message, but it undermines the flexibility of the format strings (the ability for translators to rearrange where arguments show up in a format string) and their clarity (example: "You must select one of {0}") .
What better can I do in my code and resource files to avoid those drawbacks?
Example of current code:
// assuming all string literals are in a Resource file somewhere...
string message = string.Format(
"You must select one of {0}.",
Conjoin(new []{ "Dog", "Cat", "Monkey" }));
// produces "You must select one of Dog, Cat, or Monkey
string Conjoin(string[] items)
{
if (items.Length == 1) return items[0];
if (items.Length == 2) return string.Format("{0} or {1}", items[0], items[1]);
if (items.Length >= 3)
{
string result = items[0];
for (int i = 1; i < items.Length - 1; i++)
{
result = string.Format("{0}, {1}", result, items[i]);
}
result = string.Format("{0}, or {1}", result, items[items.Length - 1]);
return result;
}
return "";
}
If you have a low max size on the list it's easy enough to just localize the list formatters:
ListFormatter[1] "{0}"
ListFormatter[2] "{0} or {1}"
ListFormatter[3] "{0}, {1}, or {2}"
etc...
To generalize it to arbitrary list sizes, a method I have used in similar situations is to have individual formatters for list sizes with irregular formatters, and then a regular formatter for everything else. That formatter could be split into three sections, a prefix, suffix, and middle repeating section. So:
ListFormatter[1] "{0}"
ListFormatter[2] "{0} or {1}"
ListFormatterNStart "{0}, "
ListFormatterNMid "{{0}}, "
ListFormatterNEnd "or {{0}}"
For English the Prefix and Mid are the same but maybe in other languages it won't be. Note the double bracket {{0}} parameters, which allow you to format a formatter.
In usage you'd do something like this, where N is the list size (psuedo-code)
if List[N] exists
formatter = ListFormatter[N]
else
formatter = ListFormatterNStart
for i = 1 to N-2
formatter += String.Format(ListFormatterNMid,i)
formatter += String.Format(ListFormatterNEnd, N-1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With