# Singular and Plural keywords index

### Post version 4.27

After version 4.27 an option is available on the `Index Table -> Advanced settings` menu. After enabling the option a [new index](https://documentation.ajaxsearchpro.com/index-table/generating-the-index-table) needs to be created.

<figure><img src="/files/krevqSSAqOEktKJ9brGE" alt=""><figcaption><p>Enabling singularization and pluralization feature in Ajax Search Pro</p></figcaption></figure>

### Pre version 4.27

{% hint style="info" %}
The tutorial below is outdated, after Ajax Search Pro 4.27 is no longer needed, please see the Post version 4.27 section above.
{% endhint %}

Use the custom code snippet below to automatically singularize and pluralize **English** keywords when using the [Index Table](https://documentation.ajaxsearchpro.com/index-table) engine. This algorightm is efficient, but of course not a 100% accurate.

{% hint style="warning" %}
After adding the code a [new index](https://documentation.ajaxsearchpro.com/index-table/generating-the-index-table) must be generated
{% endhint %}

[What is this, and where do I put this custom code?](/safe-coding-guideline.md)

```php
// ---- !!! ONLY COPY PASTE CODE BELOW THIS LINE to the functions.php in your theme directory !!! ----// ---- AJAX SEARCH PRO: BEGIN SEMI-AUTOMATIC PLURALIZATION OF ENGLISH KEYWORDS -----
class Inflect
{
    static $plural = array(
        '/(quiz)$/i'               => "$1zes",
        '/^(ox)$/i'                => "$1en",
        '/([m|l])ouse$/i'          => "$1ice",
        '/(matr|vert|ind)ix|ex$/i' => "$1ices",
        '/(x|ch|ss|sh)$/i'         => "$1es",
        '/([^aeiouy]|qu)y$/i'      => "$1ies",
        '/(hive)$/i'               => "$1s",
        '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
        '/(shea|lea|loa|thie)f$/i' => "$1ves",
        '/sis$/i'                  => "ses",
        '/([ti])um$/i'             => "$1a",
        '/(tomat|potat|ech|her|vet)o$/i'=> "$1oes",
        '/(bu)s$/i'                => "$1ses",
        '/(alias)$/i'              => "$1es",
        '/(octop)us$/i'            => "$1i",
        '/(ax|test)is$/i'          => "$1es",
        '/(us)$/i'                 => "$1es",
        '/s$/i'                    => "s",
        '/$/'                      => "s"
    );
    
    static $singular = array(
        '/(quiz)zes$/i'             => "$1",
        '/(matr)ices$/i'            => "$1ix",
        '/(vert|ind)ices$/i'        => "$1ex",
        '/^(ox)en$/i'               => "$1",
        '/(alias)es$/i'             => "$1",
        '/(octop|vir)i$/i'          => "$1us",
        '/(cris|ax|test)es$/i'      => "$1is",
        '/(shoe)s$/i'               => "$1",
        '/(o)es$/i'                 => "$1",
        '/(bus)es$/i'               => "$1",
        '/([m|l])ice$/i'            => "$1ouse",
        '/(x|ch|ss|sh)es$/i'        => "$1",
        '/(m)ovies$/i'              => "$1ovie",
        '/(s)eries$/i'              => "$1eries",
        '/([^aeiouy]|qu)ies$/i'     => "$1y",
        '/([lr])ves$/i'             => "$1f",
        '/(tive)s$/i'               => "$1",
        '/(hive)s$/i'               => "$1",
        '/(li|wi|kni)ves$/i'        => "$1fe",
        '/(shea|loa|lea|thie)ves$/i'=> "$1f",
        '/(^analy)ses$/i'           => "$1sis",
        '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i'  => "$1$2sis",        
        '/([ti])a$/i'               => "$1um",
        '/(n)ews$/i'                => "$1ews",
        '/(h|bl)ouses$/i'           => "$1ouse",
        '/(corpse)s$/i'             => "$1",
        '/(us)es$/i'                => "$1",
        '/s$/i'                     => ""
    );
    
    static $irregular = array(
        'move'   => 'moves',
        'foot'   => 'feet',
        'goose'  => 'geese',
        'sex'    => 'sexes',
        'child'  => 'children',
        'man'    => 'men',
        'tooth'  => 'teeth',
        'person' => 'people'
    );
    
    static $uncountable = array( 
        'sheep', 
        'fish',
        'deer',
        'series',
        'species',
        'money',
        'rice',
        'information',
        'equipment'
    );
    
    public static function pluralize( $string ) 
    {
        // save some time in the case that singular and plural are the same
        if ( in_array( strtolower( $string ), self::$uncountable ) )
            return $string;
            
    
        // check for irregular singular forms
        foreach ( self::$irregular as $pattern => $result )
        {
            $pattern = '/' . $pattern . '$/i';
            
            if ( preg_match( $pattern, $string ) )
                return preg_replace( $pattern, $result, $string);
        }
        
        // check for matches using regular expressions
        foreach ( self::$plural as $pattern => $result )
        {
            if ( preg_match( $pattern, $string ) )
                return preg_replace( $pattern, $result, $string );
        }
        
        return $string;
    }
    
    public static function singularize( $string )
    {
        // save some time in the case that singular and plural are the same
        if ( in_array( strtolower( $string ), self::$uncountable ) )
            return $string;

        // check for irregular plural forms
        foreach ( self::$irregular as $result => $pattern )
        {
            $pattern = '/' . $pattern . '$/i';
            
            if ( preg_match( $pattern, $string ) )
                return preg_replace( $pattern, $result, $string);
        }
        
        // check for matches using regular expressions
        foreach ( self::$singular as $pattern => $result )
        {
            if ( preg_match( $pattern, $string ) )
                return preg_replace( $pattern, $result, $string );
        }
        
        return $string;
    }
    
    public static function pluralize_if($count, $string)
    {
        if ($count == 1)
            return "1 $string";
        else
            return $count . " " . self::pluralize($string);
    }
}

add_filter( 'asp_indexing_string_post_process', 'asp_index_add_singular_plural', 10, 1 );
function asp_index_add_singular_plural($s) {
    $final = array();
	$words = explode(' ', $s);
	
    foreach ($words as $word) {
        $singular = Inflect::singularize($word);
        $plural = Inflect::pluralize($word);

        $final[] = $word;

        if ($singular != $word)
            $final[] = $singular;

        if ($plural != $word)
            $final[] = $plural;
    }
	
    return implode(' ', $final);
}
// ---- AJAX SEARCH PRO: END SEMI-AUTOMATIC PLURALIZATION OF ENGLISH KEYWORDS -----
// --------------------------------------------------------------------------------
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://knowledgebase.ajaxsearchpro.com/miscellaneous/other/singular-and-plural-keywords-index.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
