如何在C#中用逗号和连词本地化或字符串格式化单词列表?

时间:2016-07-22 23:09:58

标签: c# localization string-formatting

在C#中,我使用资源字符串和string.Format进行本地化。有时我需要从任意大小的术语列表中生成消息。 (示例:“您必须从列表中选择一只狗,猫或猴子”[“狗”,“猫”,“猴子”])

我可以编写代码来生成该消息,但它会破坏格式字符串的灵活性(翻译人员重新排列参数在格式字符串中显示的位置)及其清晰度(例如:“您必须选择{0}之一”)。

我可以在代码和资源文件中做些什么来避免这些缺点?

当前代码示例:

// 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 "";
}

2 个答案:

答案 0 :(得分:3)

如果列表中的最大大小较小,那么只需将列表格式化程序本地化即可:

ListFormatter[1]   "{0}"
ListFormatter[2]   "{0} or {1}"
ListFormatter[3]   "{0}, {1}, or {2}"
etc...

为了将其推广到任意列表大小,我在类似情况下使用的方法是使用具有不规则格式化程序的列表大小的单独格式化程序,然后使用常规格式化程序来处理其他所有内容。该格式化程序可以分为三个部分,前缀,后缀和中间重复部分。所以:

ListFormatter[1]      "{0}"
ListFormatter[2]      "{0} or {1}"
ListFormatterNStart   "{0}, "
ListFormatterNMid     "{{0}}, "
ListFormatterNEnd     "or {{0}}"

对于英语,Prefix和Mid是相同的,但也许在其他语言中它不会。请注意双括号{{0}}参数,它们允许您格式化格式化程序。

在使用中,您可以执行以下操作,其中N是列表大小(伪代码)

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)

答案 1 :(得分:1)

这是你的Conjoin函数,适用于任何大小的数组,而且更短:

// Uses LINQ
public string Conjoin(string[] items)
{
    if (items.Length == 1)
        return string.Format("{0}", items[0]);
    else if (items.Length == 2)
        return string.Format("{0} or {1}", items[0], items[1]);

    items[items.Length - 1] = "or " + items.Last();

    return string.Join(items.Select(i => string.Format(", {0}", i)).ToArray()).TrimStart(',').TrimStart(' ');
}

我用Conjoin(new string[] { "Dog", "Cat", "Monkey", "Duck" })试了一下。

输出:Dog, Cat, Monkey, or Duck