我正在寻找一个给定字符串的函数,它将字符串切换为单数/复数。我需要它适用于英语以外的欧洲语言。
有没有什么功能可以解决问题?(给定一个要转换的字符串和语言?)
谢谢
这是我方便的功能:
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 comentarios'、'2 comentarios'、'3 comentarios'等。或者如果添加's'不是这样,那么:
echo $canciones . ' canci' . plural( $canciones, 'ón', 'ones' );
这将回显“0 canciones”、“1 canción”、“2 canciones”、“3 canciones”等。
这并不容易:每种语言都有自己的名词复数形成规则。在英语中,通常在单词的末尾加上“-s”,除非它以“-x”、“-s”、“-z”、“-sh”、“-ch”结尾,其中如果您添加“-es”。但是还有“mouse”=>“mice”、“sheep”=>“sheep”等。
那么,要做的第一件事就是找出在你想使用的语言中从单数名词形成复数的规则是什么。但这不是全部解决方案。另一个问题是识别名词。如果给您一个名词,并且需要将其从单数转换为复数,这并不太难,但是如果给您一段自由文本,您必须找到单数名词并将它们转换为复数,那就更难了。您可以获得名词列表,但当然有些单词可以是名词和动词(“hunt”、“fish”、“break”等),因此您需要解析文本以识别名词。
这是个大问题。那里可能有一个人工智能系统可以满足你的需求,但我不认为会有任何免费的东西可以做到这一切。
PHP 中没有内置用于此类操作的函数。但是,您可以使用一些工具来帮助实现您的目标。
有一个非官方的 Google Dictionary API,其中包含有关复数的信息。您可以在此处阅读有关该方法的更多信息。您需要解析 JSON 对象以找到合适的项目,并且此方法往往有点慢。
想到的另一种方法是使用 aspell 或其亲属之一。我不确定这些词典对于英语以外的语言有多准确,但我使用 aspell 将单词扩展为各种形式。
我知道这不是最有帮助的答案,但希望它能给你一个大致的搜索方向。
仅英文解决方案
到目前为止,这是一个对我来说完美无缺的 PHP 类:http: //kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
这是一个要点,以防该网站消失: https ://gist.github.com/tbrianjones/ba0460cc1d55f357e00b
这是一个小班,可以轻松快速地转换为其他语言。
对于任何在 2021 年仍然遇到这个问题的人,我建议使用 Doctrine 的Inflector 包。
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
这是我通常用于不太复杂的场景的快速功能:
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。布莱恩琼斯的解决方案
我喜欢詹姆斯康斯坦丁的回答。简单而高效,您一定能掌握任何语言的每个案例。尽管必须编写更多代码(即单词的公共部分的两倍)。
当然,我也喜欢 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.
哪个是对的。
对于零值,我无法理解复数的原因,因为没有对象,但也许盎格鲁撒克逊本地人与它一起使用。
HTH,M.
对于这样的事情,我想出了一个相当简单的解决方案。但是,这取决于一般 PHP 的一些先验知识以及自定义 mySQLi 类,可以在此处找到(这解释了我使用num_rows
.
在我的例子中,我需要从数据库中提取一些笔记并说“1 note”,然后在 1 之后的所有内容都使用“notes”这个词,以及说“0 notes”。
要从数据库中提取并进行计数,我必须使用:
$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.';
}
?>
我有一个多语言解决方案。
function howmany($number,$singular,$plural) {
if($number==1) return $number.' '.$singular;
else return $number.' '.$plural;
}
像这样调用函数:
echo howmany($variablenumber,upcase('kaibigan'),upcase('ng kaibigan'));
希望这可以帮助!
您可以尝试以下方法,
if ( !function_exists('pluralize') ) {
function pluralize( $amount, $singular, $plural, $show=false ) {
$OP = $show ? $amount.' ' : '';
$OP .= ( $amount == 1 ) ? $singular : $plural;
return $OP;
}
}