PHP function to convert a Portuguese word from plural to singular
Let me start by saying, that I have respect for Mike Brant, and have been enjoying his posts for quite a while now.  However, I disagree with some of his review.


$regex_config can not store the the replacement values as associative keys unless the regex patterns that use the same replacement value are merged.  This is not explained in the ... (yatta-yatta).  The key clash would be on el.
Simply throwing 1 at the end of preg_replace() is NOT going to provide the desired output.  Declaring a replacement limit on the call will only limit the replacements PER array element. The damage is evident in this output: meses => mês = mê
Most trivially, array_values() doesn't need to be called because preg_replace() is "key ignorant" regarding the array inputs.





For this process to maintain accuracy, there needs to be a return as soon as a replacement occurs on the input string.  To avoid calling multiple replacements, iterate the array of pattern-replacement pairs.
You can avoid using capture groups and shorten your replacement strings in a couple places by implementing the \K metacharacter (restart fullstring match).  This way you don't need to use $1 or rewrite a literals from the pattern into the replacement.
If you need to add case-sensitivity to your replacement process, you can check the last character of the incoming string.  If it is uppercase, assume the whole string is in CAPS and call mb_strtoupper().
I don't have a sample string to test against ~[áó].*eis$~iu, but I wonder if this is accurate/correct and my Portuguese is not too sharp.
After my implementation of \K you can see that two pairs of patterns are making the same replacement.  If you don't expect to be making lots of future adjustments to this set of regex patterns, you could combine the patterns with a pipe.  Here's what I mean: '~(?:[áó].*eis|[eé]is)$~iu' =&gt; 'el', and '~(?:[rzs]\Kes|s)$~iu' =&gt; ''
I am using the regex patterns as the keys because they will all logically be unique.  the same cannot be said about the replacement values (not without merging anyhow).




Code: (Demo)

function is_allcaps($string)
{
    $last_letter = mb_substr($string, -1, 1, 'UTF-8');
    return $last_letter === mb_strtoupper($last_letter, 'UTF-8');
    // otherwise use cytpe_upper() and setlocale()
}

function plural_to_singular($string)
{
    // quick return of "untouchables"
    if(preg_match('~^(?:[oó]culos|parab[eé]ns|f[eé]rias)$~iu', $string))
    {
        return $string;
    }

    $regex_map = [
        '~[õã]es$~iu' =&gt; 'ão',
        '~(?:[áó].*e|[eé])is$~iu' =&gt; 'el',
        '~[^eé]\Kis$~iu' =&gt; 'l',
        '~ns$~iu' =&gt; 'm',
        '~eses$~iu' =&gt; 'ês',
        '~(?:[rzs]\Ke)?s$~iu' =&gt; ''
    ];

    foreach ($regex_map as $pattern =&gt; $replacement)
    {
        $singular = preg_replace($pattern, $replacement, $string, 1, $count);
        if ($count)
        {
            return is_allcaps($string) ? mb_strtoupper($singular) : $singular;

        }
    }
    return $string;
}

$words = array(
    'óculos' =&gt; 'óculos',
    'papéis' =&gt; 'papel',
    'anéis' =&gt; 'anel',
    'PASTEIS' =&gt; 'PASTEL',
    'CAMIÕES' =&gt; 'CAMIÃO',
    'rodas' =&gt; 'roda',
    'cães' =&gt; 'cão',
    'meses' =&gt; 'mês',
    'vezes' =&gt; 'vez',
    'luzes' =&gt; 'luz',
    'cristais' =&gt; 'cristal',
    'canções' =&gt; 'canção',
    'nuvens' =&gt; 'nuvem',
    'alemães' =&gt; 'alemão'
);

foreach($words as $plural =&gt; $singular)
{
    echo "$plural =&gt; $singular = " , plural_to_singular($plural) , "\n";
}