我正在寻找一个给定字符串的函数,它将字符串切换为单数/复数。我需要它为英语以外的欧洲语言工作。
有没有可以做到这一点的功能? (给定要转换的字符串和语言?)
由于
答案 0 :(得分:30)
这是我的便利功能:
function plural( $amount, $singular = '', $plural = 's' ) {
if ( $amount === 1 ) {
return $singular;
}
return $plural;
}
默认情况下,它只是在字符串后添加's'。例如:
echo $posts . ' post' . plural( $posts );
这将回应“0个帖子”,“1个帖子”,“2个帖子”,“3个帖子”等。但您也可以这样做:
echo $replies . ' repl' . plural( $replies, 'y', 'ies' );
这将回应'0回复','1回复','2回复','3回复'等。或者:
echo $replies . ' ' . plural( $replies, 'reply', 'replies' );
它也适用于其他一些语言。例如,在西班牙语中我做:
echo $comentarios . ' comentario' . plural( $comentarios );
这将回应'0 comentarios','1 comentario','2 comentarios','3 comentarios'等。或者如果添加's'不是那样的话,那么:
echo $canciones . ' canci' . plural( $canciones, 'ón', 'ones' );
这将回应'0 canciones','1canción','2 canciones','3 canciones'等。
答案 1 :(得分:8)
这并不容易:每种语言都有自己的规则来形成复数名词。在英语中,你倾向于在单词的末尾加上“-s”,除非它以“-x”,“ - s”,“ - z”,“ - sh”,“ - ch”结尾你添加“-es”的情况。但后来有“老鼠”=>“老鼠”,“绵羊”=>“绵羊”等。
然后,要做的第一件事就是找出从你想要使用的语言中用单数名词形成复数的规则。但这不是整个解决方案。另一个问题是识别名词。如果给你一个名词,并且需要将它从单数转换为复数而不是太难,但如果给你一段自由文本并且你必须找到单数名词并将它们转换为复数,那就更难了。你可以得到名词列表,但当然有些词可以是名词和动词(“狩猎”,“鱼”,“休息”等),所以你需要解析文本来识别名词。
这是一个大问题。可能有一个人工智能系统会做你需要的,但我不认为会有任何免费的东西可以做到这一切。
答案 2 :(得分:7)
这种类型的操作没有内置于PHP的功能。但是,您可以使用一些工具来帮助您实现目标。
有一个非官方的Google Dictionary API,其中包含有关复数的信息。您可以阅读有关that method here的更多信息。你需要解析一个JSON对象来找到合适的项目,这种方法往往有点慢。
另一种想到的方法是使用aspell或其中一个亲戚。我不确定字典对于除英语以外的语言有多准确,但我用aspell将单词扩展为各种形式。
我知道这不是最有帮助的答案,但希望它能为您提供搜索的一般方向。
答案 3 :(得分:7)
仅英文解决方案
到目前为止,这是一个对我来说完美无缺的PHP类: http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
如果网站消失,这是一个Gist: https://gist.github.com/tbrianjones/ba0460cc1d55f357e00b
这是一个小班级,可以轻松快速地转换为其他语言。
答案 4 :(得分:3)
这是一个我通常用于不太复杂的场景的快速功能:
public static function getPluralPrase($phrase,$value){
$plural='';
if($value>1){
for($i=0;$i<strlen($phrase);$i++){
if($i==strlen($phrase)-1){
$plural.=($phrase[$i]=='y')? 'ies':(($phrase[$i]=='s'|| $phrase[$i]=='x' || $phrase[$i]=='z' || $phrase[$i]=='ch' || $phrase[$i]=='sh')? $phrase[$i].'es' :$phrase[$i].'s');
}else{
$plural.=$phrase[$i];
}
}
return $plural;
}
return $phrase;
}
虽然对于更复杂的解决方案,您可以使用@T。 Brian Jones的解决方案
答案 5 :(得分:2)
我喜欢James Constantino的回答。简单高效,您确保以任何语言掌握每个案例。虽然必须编写更多代码(这个单词的共同部分的两倍,即)。
我当然也喜欢TBrianJones解决方案,但它只适用于英语(原样。我可以轻松地将其用于我常用的欧洲语言,德语,法语,西班牙语,意大利语和葡萄牙语)。谢谢你。如果您知道将使用的单词的频率,您可以通过重新组织行来优化它。
菲利普的建议也很好,并且顺便提一下。
但是在每个解决方案中,我发现了我认为的错误:你们每个人都只使用单数形式的值为1,而复数形式则用于其他每种情况。对于负值,这显然是错误的,但对于严格低于2的值,最重要的是 - 至少在法语中。
所以这是我的建议,以詹姆斯的代码为基础,优化:
function singleOrPlural($amount, $singular, $plural) {
return (abs($amount)>=2
? $amount.' '.$plural
: $amount.' '.$singular
);
}
所以像
这样的代码echo "We bought ".singleOrPlural(1.5, "pound", "pounds")
." of apples and ".singleOrPlural(2, "pound", "pounds")." of bread.";
将给出
We bought 1.5 pound of apples and 2 pounds of bread.
这是正确的。
对于零值,我无法理解复数的原因,因为没有任何对象,但也许使用anglosaxon natives。
HTH,M。
答案 6 :(得分:1)
对于 2021 年仍然遇到此问题的任何人,我建议使用来自 Doctrine 的 Inflector package。
Doctrine Inflector 是一个小型库,可以对大写/小写和单数/复数形式的单词进行字符串操作。
在撰写本文时,它支持英语、法语、挪威语(博克马尔语)、葡萄牙语、西班牙语和土耳其语。
只需使用 composer 安装它:composer require doctrine/inflector
并像这样使用它:
<?php
// Composer autoloading (your project probably already does this)
require __DIR__ . '/vendor/autoload.php';
// Build the inflector:
$inflector = \Doctrine\Inflector\InflectorFactory::create()->build();
// Singularize a word:
$inflector->singularize('houses'); // house
$inflector->singularize('vertices'); // vertex
答案 7 :(得分:0)
我有一个多语言解决方案。
function howmany($number,$singular,$plural) {
if($number==1) return $number.' '.$singular;
else return $number.' '.$plural;
}
像这样调用函数:
echo howmany($variablenumber,upcase('kaibigan'),upcase('ng kaibigan'));
希望这有帮助!
答案 8 :(得分:0)
您可以尝试以下方法,
if ( !function_exists('pluralize') ) {
function pluralize( $amount, $singular, $plural, $show=false ) {
$OP = $show ? $amount.' ' : '';
$OP .= ( $amount == 1 ) ? $singular : $plural;
return $OP;
}
}
答案 9 :(得分:0)
我想出了一个相当简单的解决方案。但是,这取决于一般PHP的一些先验知识以及自定义mySQLi类,可以找到here(这解释了我对num_rows
的使用。
在我的情况下,我需要从数据库中提取一些注释并说出“1注释”,然后在1之后说出“注释”一词,以及说“0注释”的内容。
要从数据库中取出并进行计数,我必须使用:
$total_notes = $database->num_rows("SELECT notes_id FROM $notes_db");
然后是回显价值的代码......
<?php
if($total_notes === 1){
echo '<strong>1</strong> note.';
}elseif($total_notes > 1){
echo '<strong>'.$total_notes.'</strong> notes.';
}elseif($total_notes === 0){
echo '<strong>0</strong> notes.';
}
?>