Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
EnConverter
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 6
132
0.00% covered (danger)
0.00%
0 / 1
 getMainCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLanguageVariants
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getVariantsFallbacks
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 loadDefaultTables
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 translate
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 pigLatin
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21use MediaWiki\Language\LanguageConverter;
22use MediaWiki\Language\ReplacementArray;
23
24/**
25 * English specific converter routines.
26 *
27 * @ingroup Languages
28 */
29class EnConverter extends LanguageConverter {
30
31    public function getMainCode(): string {
32        return 'en';
33    }
34
35    public function getLanguageVariants(): array {
36        return [ 'en', 'en-x-piglatin' ];
37    }
38
39    public function getVariantsFallbacks(): array {
40        return [];
41    }
42
43    protected function loadDefaultTables(): array {
44        return [
45            'en' => new ReplacementArray(),
46            'en-x-piglatin' => new ReplacementArray(),
47        ];
48    }
49
50    /**
51     * Translates text into Pig Latin. This allows developers to test the language variants
52     * functionality and user interface without having to switch wiki language away from default.
53     * This method also processes custom conversion rules to allow testing these parts of the
54     * language converter as well.
55     *
56     * @param string $text
57     * @param string $toVariant
58     * @return string
59     */
60    public function translate( $text, $toVariant ) {
61        if ( $toVariant !== 'en-x-piglatin' ) {
62            return $text;
63        }
64        // Apply any custom rules.  (Primarily for testing.)
65        $this->loadTables();
66        $customRules = $this->mTables[$toVariant];
67
68        if ( !$customRules->getArray() ) {
69            return self::pigLatin( $text );
70        }
71
72        // Split on the matches from custom rules, so that we only apply
73        // the Pig Latin transformation on output. which is not from a
74        // custom rule; this avoids double-conversion.
75        // (See SrConverter for similar split-and-process code.)
76        $re = '(' .
77            implode(
78                '|',
79                array_map(
80                    'preg_quote',
81                    // "Original" texts from the ReplacementArray rules
82                    array_keys( $customRules->getArray() )
83                )
84            ) . ')';
85
86        $matches = preg_split( $re, $text, -1, PREG_SPLIT_OFFSET_CAPTURE );
87        $m = array_shift( $matches );
88
89        // Apply Pig Latin transformation to the initial "non-matching" section.
90        $ret = self::pigLatin( $m[0] );
91        $mstart = (int)$m[1] + strlen( $m[0] );
92        foreach ( $matches as $m ) {
93            // Use the ReplacementArray rules to transform any matching sections
94            $ret .= $customRules->replace(
95                substr( $text, $mstart, (int)$m[1] - $mstart )
96            );
97            // And Pig Latin transformation on the non-matching sections.
98            $ret .= self::pigLatin( $m[0] );
99            $mstart = (int)$m[1] + strlen( $m[0] );
100        }
101        // $mstart will always equal strlen($text) here.
102
103        return $ret;
104    }
105
106    /**
107     * Translates words into Pig Latin.
108     *
109     * @param string $text
110     * @return string
111     */
112    private static function pigLatin( string $text ): string {
113        // Only process words composed of standard English alphabet, leave the rest unchanged.
114        // This skips some English words like 'naïve' or 'résumé', but we can live with that.
115        // Ignore single letters and words which aren't lowercase or uppercase-first.
116        return preg_replace_callback( '/[A-Za-z][a-z\']+/', static function ( $matches ) {
117            $word = $matches[0];
118            if ( preg_match( '/^[aeiou]/i', $word ) ) {
119                return $word . 'way';
120            }
121
122            return preg_replace_callback( '/^(s?qu|[^aeiou][^aeiouy]*)(.*)$/i', static function ( $m ) {
123                $ucfirst = strtoupper( $m[1][0] ) === $m[1][0];
124                if ( $ucfirst ) {
125                    return ucfirst( $m[2] ) . lcfirst( $m[1] ) . 'ay';
126                }
127
128                return $m[2] . $m[1] . 'ay';
129            }, $word );
130        }, $text );
131    }
132}