将带有占位符(`{0}`)的字符串添加到资源中是一个好主意吗?

我在资源文件中添加了一个字符串。 我的应用程序将被本地化。
但是,将占位符( {0} )添加到资源中的字符串是一个好主意吗?
如果一些非技术人员进行本地化怎么办? 有没有办法让他在不知不觉中搞砸了?

如果这不是一个好主意,我该怎么办?

这是一个简单的例子。 我将使用WPF资源字典。

例:

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

嗯,我相信这是一个好主意,因为这是一种简单快捷的呈现参数化和本地化字符串的方法。

顺便说一句,正如你在问题中所说的那样,非技术人员可能会破坏你的本地化字符串,因为他们不明白什么是“{0}”。 我有两种“方法”来解决这个问题

  1. 只需注意非技术人员维护本地化字符串,他们就不必关注括号中的文本。

  2. 使用命名占位符:“{some-identifier}”并使用someTextResource.Replace("{some-identifier}", someTextVar)

关于第二个,你可以实现一些接受IDictionary替换关系实例的方法,其中key是要替换的标识符,并且值为替换标识符的文本。

这取决于

有时您别无选择,只能使用占位符,例如动态数据。 在这种情况下使用占位符,特别是编号的({0},{1},…)不仅是好主意,而且是国际化视角中最可接受的想法。 它允许在翻译期间重新排序句子,这绝对是你想要支持的。
至于非技术人员……好吧,如果你使用专业的软件翻译供应商,他们不会有任何问题,他们只是用来翻译这样的字符串。 如果你想指定通用翻译器的服务,它可能会造成问题。 但在这种情况下,我必须警告您,技术翻译是特定的 :翻译人员至少应遵守通用软件术语词汇表。

好的,现在为什么它取决于 。 基本上,使用string.Format()格式化字符串实际上是连接。 正如我所说,如果你有动态数据,你别无选择。 但是,如果您的数据是静态的,并且您只有很少的组合,那么在任何情况下都不应该使用占位符(也不应该使用串联(+)运算符的简单字符串连接,也不应该使用StringBuilder更复杂)。 对于静态数据,您应该只需创建所需的字符串。
它的真正原因是,许多语言需要根据上下文的不同forms的翻译。 例如,在我母亲的舌头(波兰语)中,我们使用不同forms的女性和男性名词。
这不仅仅是理论问题:4年前,当我在本地化工作时,我们不得不本地化新的主要反病毒软件。 问题是,一些程序员优化了资源,因此我们有一条类似于那条的消息:

 The {0} is inactive. To activate {0} click... 

什么代替了占位符,是function或程序名称。 在波兰语中function是女性化的,程序是男性化的。 更糟糕的是,我们的语言学家想要添加单词“program”和“funkcja”,具体取决于实际上不活跃的内容。
显然,我们(本地化软件工程师)无法在不触及代码的情况下解决问题(我们不允许这样做,但这是一个不同的故事……)。

总结一下:
如果你真的需要,请使用占位符。 磁盘空间很便宜。 避免连接(因为这不允许重新排序翻译的句子)。
不要太担心翻译,但记得给他们上下文(可能还有说明)。 对于他们来说,了解字符串的显示位置以及可能的值是很重要的。

如果这样做,请确保记录非技术翻译人员的行为。 否则你应该没事。

即使你为非技术翻译人员提供了一份文件,他们仍然有可能在不知情的情况下利用它,如果你自己处理这种情况,那么其他方面也不会成为问题。 我宁愿连接字符串。

我认为这是推荐的方法。 GNU GetText指南建议这样做。

正如Erno评论的那样,确保翻译的任何人都知道{0}代表什么。

这种方法的一个好处是,您可以控制值的插入位置和部分值格式。 你想念的是价值的多元化,但这是另一个讨论。

使用自动化测试来validation翻译供应商返回的资源文件的完整性。 理想情况下,为供应商提供在翻译期间执行此操作的工具,以尽早发现缺陷。

我通常会为这些类型的字符串提出一个命名方案,以便它们在代码中脱颖而出。

喜欢Strings.RELATIONSHIP_STATUS_MSG_FORMAT

我喜欢Resharper的命名修道院: __0__is_in_relationship_with__1__

清楚地说明从代码中使用时预期的参数:

 string msg = string.Format(Properties.Resources.__0__is_in_relationship_with__1__, "Romeo", "Juliet");