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

How to localize or string format a list of words with commas and conjunctions in C#?

在 C# 中,我使用资源字符串和 string.Format 进行本地化。有时我需要从任意大小的术语列表中生成一条消息。 (示例:"You must select one of Dog, Cat, or Monkey" 来自列表 ["Dog"、"Cat"、"Monkey"])

我可以编写代码来生成该消息,但它破坏了格式字符串的灵活性(翻译人员重新排列参数在格式字符串中出现的位置的能力)和他们的清晰度(示例:"You must select one of {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 "";
}

这是您的 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.

如果列表中的最大大小较小,只需本地化列表格式化程序就足够了:

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)