function switching between singular and plural?
I'm looking for a function that given a string it switches the string to singular/plural. I need it to work for european languages other than English.
Are there any functions that can do the trick? (Given a stri开发者_StackOverflowng to convert and the language?)
Thanks
Here is my handy function:
function plural( $amount, $singular = '', $plural = 's' ) {
if ( $amount === 1 ) {
return $singular;
}
return $plural;
}
By default, it just adds the 's' after the string. For example:
echo $posts . ' post' . plural( $posts );
This will echo '0 posts', '1 post', '2 posts', '3 posts', etc. But you can also do:
echo $replies . ' repl' . plural( $replies, 'y', 'ies' );
Which will echo '0 replies', '1 reply', '2 replies', '3 replies', etc. Or alternatively:
echo $replies . ' ' . plural( $replies, 'reply', 'replies' );
And it works for some other languages too. For example, in Spanish I do:
echo $comentarios . ' comentario' . plural( $comentarios );
Which will echo '0 comentarios', '1 comentario', '2 comentarios', '3 comentarios', etc. Or if adding an 's' is not the way, then:
echo $canciones . ' canci' . plural( $canciones, 'ón', 'ones' );
Which will echo '0 canciones', '1 canción', '2 canciones', '3 canciones', etc.
There is no function built into PHP for this type of operation. There are, however, some tools that you may be able to use to help accomplish your goal.
There is an unofficial Google Dictionary API which contains information on plurals. You can read more about that method here. You'll need to parse a JSON object to find the appropriate items and this method tends to be a little bit slow.
The other method that comes to mind is to use aspell, or one of its relatives. I'm not sure how accurate the dictionaries are for languages other than English but I've used aspell to expand words into their various forms.
I know this is not the most helpful answer, but hopefully it gives you a general direction to search in.
This is not easy: each language has its own rules for forming plurals of nouns. In English it tends to be that you put "-s" on the end of a word, unless it ends in "-x", "-s", "-z", "-sh", "-ch" in which case you add "-es". But then there's "mouse"=>"mice", "sheep"=>"sheep" etc.
The first thing to do, then, is to find out what the rule(s) are for forming the plural from the singular noun in the language(s) you want to work with. But that's not the whole solution. Another problem is recognising nouns. If you are given a noun, and need to convert it from singular to plural that's not too hard, but if you are given a piece of free text and you have to find the singular nouns and convert them to plural, that's a lot harder. You can get lists of nouns, but of course some words can be nouns and verbs ("hunt", "fish", "break" etc.) so then you need to parse the text to identify the nouns.
It's a big problem. There's probably an AI system out there that would do what you need, but I don't imagine there'll be anything free that does it all.
For anyone still stumbling across this in 2021, I suggest using the Inflector package from Doctrine.
Doctrine Inflector is a small library that can perform string manipulations with regard to uppercase/lowercase and singular/plural forms of words.
At time of writing, it supports English, French, Norwegian (bokmal), Portuguese, Spanish and Turkish.
Simply install it using composer: composer require doctrine/inflector
and use it like this:
<?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
English Only Solution
Here is a PHP class that has worked flawlessly for me thus far: http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
Here it is as a Gist in case that site goes away: https://gist.github.com/tbrianjones/ba0460cc1d55f357e00b
This is a small class and could easily and quickly be converted to other languages.
Here is a quick function that I usually use for less complex scenarios:
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;
}
Although for a more complex solution you can go with @T. Brian Jones' Solution
I like the answer of James Constantino. Simple and efficient, and you're sure to master every case, in any language. Though one must write more code (twice the common part of the word, namely).
I also like, of course, the TBrianJones solution, but it works only with English (as is. I can easily enhance it for my usual European languages, German, French, Spanish, Italian and Portuguese). Thanks for it. If you know the frequency of the words that will be used, you can optimize it by reorganizing the lines.
Also Felipe's proposal is good, and btw plebiscited.
But in every solution, I found what I consider as a bug: each of you use the singular form only for the value 1, and the plural form for every other case. Which is obviously wrong for negative values, but also --at least in French-- for values strictly lower than 2.
So here is my proposal, taking James's code as the base, optimized:
function singleOrPlural($amount, $singular, $plural) {
return (abs($amount)>=2
? $amount.' '.$plural
: $amount.' '.$singular
);
}
So a code like
echo "We bought ".singleOrPlural(1.5, "pound", "pounds")
." of apples and ".singleOrPlural(2, "pound", "pounds")." of bread.";
will give
We bought 1.5 pound of apples and 2 pounds of bread.
which is correct.
For the zero value, I cannot understand the reason of a plural, since there is none of the object, but maybe anglosaxon natives are used with that.
HTH, M.
I came up with a rather easy solution for something like this. However, this depends on some prior knowledge of general PHP as well as a custom mySQLi class, that can be found here (which explains my use of num_rows
.
In my case, I needed to pull up a number of notes from a database and say "1 note" and then the word "notes" for everything after 1, as well as something to say "0 notes".
To pull from the database and do a count, I had to use:
$total_notes = $database->num_rows("SELECT notes_id FROM $notes_db");
And then the code to echo the value...
<?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.';
}
?>
I have a multilanguage solution.
function howmany($number,$singular,$plural) {
if($number==1) return $number.' '.$singular;
else return $number.' '.$plural;
}
Call the function like so:
echo howmany($variablenumber,upcase('kaibigan'),upcase('ng kaibigan'));
Hope this helps!
You can try the following,
if ( !function_exists('pluralize') ) {
function pluralize( $amount, $singular, $plural, $show=false ) {
$OP = $show ? $amount.' ' : '';
$OP .= ( $amount == 1 ) ? $singular : $plural;
return $OP;
}
}
精彩评论