处理单数/复数的最优雅的方式?
假设您正在制作一个博客软件,并且想要显示某个条目获得的评论数量。 您可以这样做:
[Entry title]
[Content........]
[ <?php print($numComments;) ?> Comments]
这可能会导致:
[Entry title]
[Content........]
5 Comments
但如果一个条目只有 1 条评论,我希望该行显示“评论”而不是“评论”。 内联的 if/else
又丑又重复。
处理这个问题的最佳方法是什么?
Say you're making a blog software, and want to show the number of comments an entry got. You might do it this way:
[Entry title]
[Content........]
[ <?php print($numComments;) ?> Comments]
Which might result in:
[Entry title]
[Content........]
5 Comments
But if an entry had only 1 comment, I want the line to say 'Comment' rather than 'Comments'. And in-line if/else
s are ugly and repetitive.
What's the best way to deal with this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
请使用
ngettext
函数来完成此类操作。 它允许您正确处理英语和其他语言中的复数形式
语言,一劳永逸。 您可以这样使用它:
ngettext
函数将返回第一个格式字符串 ("%d
) 如果只有一条注释且采用第二种格式Comment"
字符串(
"%d Comments"
)(如果有更多)。printf
函数将然后将数字放入字符串中。
这可能看起来工作量很大,但它非常强大:它有效
对于具有多个复数形式(!)的语言——它们
实际存在。 PHP 手册给出了单词“window”的示例
在某些异国情调中变成“1 okno”、“2 okna”和“5 oken”
我不认识的语言...
如果您使用
ngettext
,那么您未来的用户来自遥远国家的人将非常感谢你:-)
编辑:正如评论中所建议的,有一个功能可以
执行上述操作:
默认情况下,
xgettext
不会识别这个新函数,但您可以使用
--keyword
标志添加它。 给定一个文件test.php
,您可以使用 提取字符串
生成的
messages.po
文件包含如下条目:翻译器将填写每个复数形式并使用正确的
在消息目录标题中形成“复数形式”行,您将
能够支持所有语言。
Please use the
ngettext
function for things like this. Itallows you to deal correctly with plurals in English and other
languages, once and for all. You use it like this:
The
ngettext
function will return the first format string ("%d
) if there is just a single comment and the second formatComment"
string (
"%d Comments"
) if there are more. Theprintf
function willthen put the number into the string.
This might seem like a lot of work, but it is very powerful: it works
with languages that have more than one plural form(!) -- they
actually exist. The PHP manual gives an example for the word "window"
which becomes "1 okno", "2 okna" and "5 oken" in some exotic
language I don't recognize...
If you are consequent about using
ngettext
, then your future usersfrom far-away countries will be very grateful to you :-)
Edit: As suggested in the comments, there is a single function to
do the above:
By default,
xgettext
wont recognize this new function, but you canadd it with the
--keyword
flag. Given a filetest.php
withyou can extract the strings with
The resulting
messages.po
file has entries like these:The translator will fill in each plural form and with a correctly
formed "Plural-Forms" line in the message catalog header, you will be
able to support all languages.
为什么不花时间让事情变得更加人性化......
Why not take the time to humanize things even more....
创建一个函数,它接受一个数字和一个单词,并返回一个包含两者的字符串。 当数字大于 1 时,它将附加一个“s”(或查阅您构建的字典)。
Create a function that takes a number and a word, and returns a string containing both. It will append an "s" (or consult a dictionary that you build) when the number is bigger than 1.
令我惊讶的是,还没有人建议这样做,但我通常做的是使用条件运算符:
注意:字符串当然不应该像这样硬编码,而是从某个资源存储库加载,它存储在数字的格式占位符,以便您可以处理数字应出现在最后(或中间)的语言:
It surprises me that nobody suggested that yet, but what I usually do is to use the conditional operator:
Note: the string should of course not be hard coded like this at all, but rather loaded from some resource repository, where it is stored with a formatting placeholder for the number, so that you can handle languages where the number should appear last (or in the middle):
不是最优雅的,但最容易输出“评论”。
Not the most elegant, but the easiest it to output "Comment(s)".
在 C/C++ 中,您可以执行以下操作。 您也许可以在 PHP 中执行类似的操作。
以下方法也适用,但您可能会遇到在不同实现中错误处理
\b
(退格键)的问题。使用
\0
(空字符)不打印任何内容,而是在我的实现中打印一个空格。In C/C++, you can do the following. You may be able to do something similar in PHP.
The following also works, but you may run into issues with
\b
(backspace) being handled incorrectly in different implementations.Using
\0
(null character) to print nothing, instead, printed a space in my implementation.查看 Rails inflector 模块。 这为这个问题提供了一个很好的、集中的、可配置的解决方案。
Check out the Rails inflector module. This provides a nice, centralized and configurable solution to this problem.