Refactor global function wfBCP47 to static function LanguageCode::bcp47
authorFomafix <fomafix@googlemail.com>
Thu, 6 Apr 2017 15:17:19 +0000 (17:17 +0200)
committerFomafix <fomafix@googlemail.com>
Thu, 5 Oct 2017 07:54:45 +0000 (09:54 +0200)
Deprecate global function wfBCP47.

Change-Id: Ie6bb061b5d6ca67289bb18bc468a87421f38fc94

14 files changed:
RELEASE-NOTES-1.31
includes/Feed.php
includes/GlobalFunctions.php
includes/OutputPage.php
includes/Preferences.php
includes/installer/WebInstallerOutput.php
includes/page/ImagePage.php
includes/parser/CoreParserFunctions.php
includes/skins/SkinTemplate.php
languages/Language.php
languages/LanguageCode.php
resources/src/mediawiki.language/mediawiki.language.js
tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php [deleted file]
tests/phpunit/languages/LanguageCodeTest.php

index 60a49b7..3fd1fc8 100644 (file)
@@ -40,6 +40,8 @@ changes to languages because of Phabricator reports.
 
 === Other changes in 1.31 ===
 * MessageBlobStore::insertMessageBlob() (deprecated in 1.27) was removed.
+* The global function wfBCP47 was renamed to LanguageCode::bcp47.
+* The global function wfBCP47 is now deprecated.
 
 == Compatibility ==
 MediaWiki 1.31 requires PHP 5.5.9 or later. There is experimental support for
index f76a634..bc7747f 100644 (file)
@@ -139,7 +139,7 @@ class FeedItem {
         */
        public function getLanguage() {
                global $wgLanguageCode;
-               return wfBCP47( $wgLanguageCode );
+               return LanguageCode::bcp47( $wgLanguageCode );
        }
 
        /**
index 484dfe8..be8c40f 100644 (file)
@@ -3166,29 +3166,13 @@ function wfShorthandToInteger( $string = '', $default = -1 ) {
  * See unit test for examples.
  * See mediawiki.language.bcp47 for the JavaScript implementation.
  *
+ * @deprecated since 1.31, use LanguageCode::bcp47() directly.
+ *
  * @param string $code The language code.
  * @return string The language code which complying with BCP 47 standards.
  */
 function wfBCP47( $code ) {
-       $codeSegment = explode( '-', $code );
-       $codeBCP = [];
-       foreach ( $codeSegment as $segNo => $seg ) {
-               // when previous segment is x, it is a private segment and should be lc
-               if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
-                       $codeBCP[$segNo] = strtolower( $seg );
-               // ISO 3166 country code
-               } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
-                       $codeBCP[$segNo] = strtoupper( $seg );
-               // ISO 15924 script code
-               } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
-                       $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
-               // Use lowercase for other cases
-               } else {
-                       $codeBCP[$segNo] = strtolower( $seg );
-               }
-       }
-       $langCode = implode( '-', $codeBCP );
-       return $langCode;
+       return LanguageCode::bcp47( $code );
 }
 
 /**
index 785641d..8a489b8 100644 (file)
@@ -2200,7 +2200,7 @@ class OutputPage extends ContextSource {
                                        // IE and some other browsers use BCP 47 standards in
                                        // their Accept-Language header, like "zh-CN" or "zh-Hant".
                                        // We should handle these too.
-                                       $variantBCP47 = wfBCP47( $variant );
+                                       $variantBCP47 = LanguageCode::bcp47( $variant );
                                        if ( $variantBCP47 !== $variant ) {
                                                $aloption[] = 'substr=' . $variantBCP47;
                                        }
@@ -3437,7 +3437,7 @@ class OutputPage extends ContextSource {
                                foreach ( $variants as $variant ) {
                                        $tags["variant-$variant"] = Html::element( 'link', [
                                                'rel' => 'alternate',
-                                               'hreflang' => wfBCP47( $variant ),
+                                               'hreflang' => LanguageCode::bcp47( $variant ),
                                                'href' => $this->getTitle()->getLocalURL(
                                                        [ 'variant' => $variant ] )
                                                ]
index 96b002b..ba90121 100644 (file)
@@ -352,7 +352,7 @@ class Preferences {
 
                $options = [];
                foreach ( $languages as $code => $name ) {
-                       $display = wfBCP47( $code ) . ' - ' . $name;
+                       $display = LanguageCode::bcp47( $code ) . ' - ' . $name;
                        $options[$display] = $code;
                }
                $defaultPreferences['language'] = [
@@ -394,7 +394,7 @@ class Preferences {
 
                                        $options = [];
                                        foreach ( $variantArray as $code => $name ) {
-                                               $display = wfBCP47( $code ) . ' - ' . $name;
+                                               $display = LanguageCode::bcp47( $code ) . ' - ' . $name;
                                                $options[$display] = $code;
                                        }
 
index e4eb255..6a55d69 100644 (file)
@@ -233,7 +233,7 @@ class WebInstallerOutput {
        public function getHeadAttribs() {
                return [
                        'dir' => $this->getDir(),
-                       'lang' => wfBCP47( $this->getLanguageCode() ),
+                       'lang' => LanguageCode::bcp47( $this->getLanguageCode() ),
                ];
        }
 
index 0e3eaa5..62f5d00 100644 (file)
@@ -1054,8 +1054,8 @@ EOT
        protected function doRenderLangOpt( array $langChoices, $curLang, $defaultLang ) {
                global $wgScript;
                sort( $langChoices );
-               $curLang = wfBCP47( $curLang );
-               $defaultLang = wfBCP47( $defaultLang );
+               $curLang = LanguageCode::bcp47( $curLang );
+               $defaultLang = LanguageCode::bcp47( $defaultLang );
                $opts = '';
                $haveCurrentLang = false;
                $haveDefaultLang = false;
@@ -1067,7 +1067,7 @@ EOT
                // include a choice for that. Last of all, if we're viewing
                // the file in a language not on the list, add it as a choice.
                foreach ( $langChoices as $lang ) {
-                       $code = wfBCP47( $lang );
+                       $code = LanguageCode::bcp47( $lang );
                        $name = Language::fetchLanguageName( $code, $this->getContext()->getLanguage()->getCode() );
                        if ( $name !== '' ) {
                                $display = $this->getContext()->msg( 'img-lang-opt', $code, $name )->text();
index bebf3f8..6211196 100644 (file)
@@ -875,7 +875,7 @@ class CoreParserFunctions {
                $code = strtolower( $code );
                $inLanguage = strtolower( $inLanguage );
                $lang = Language::fetchLanguageName( $code, $inLanguage );
-               return $lang !== '' ? $lang : wfBCP47( $code );
+               return $lang !== '' ? $lang : LanguageCode::bcp47( $code );
        }
 
        /**
index 0690f03..532ee51 100644 (file)
@@ -174,7 +174,7 @@ class SkinTemplate extends Skin {
                                        )->text();
                                }
 
-                               $ilInterwikiCodeBCP47 = wfBCP47( $ilInterwikiCode );
+                               $ilInterwikiCodeBCP47 = LanguageCode::bcp47( $ilInterwikiCode );
                                $languageLink = [
                                        'href' => $languageLinkTitle->getFullURL(),
                                        'text' => $ilLangName,
@@ -1125,8 +1125,8 @@ class SkinTemplate extends Skin {
                                                        'class' => ( $code == $preferred ) ? 'selected' : false,
                                                        'text' => $varname,
                                                        'href' => $title->getLocalURL( [ 'variant' => $code ] + $params ),
-                                                       'lang' => wfBCP47( $code ),
-                                                       'hreflang' => wfBCP47( $code ),
+                                                       'lang' => LanguageCode::bcp47( $code ),
+                                                       'hreflang' => LanguageCode::bcp47( $code ),
                                                ];
                                        }
                                }
index c514cdc..435f058 100644 (file)
@@ -4309,7 +4309,7 @@ class Language {
         */
        public function getHtmlCode() {
                if ( is_null( $this->mHtmlCode ) ) {
-                       $this->mHtmlCode = wfBCP47( $this->getCode() );
+                       $this->mHtmlCode = LanguageCode::bcp47( $this->getCode() );
                }
                return $this->mHtmlCode;
        }
index 3fa3dc1..f50c55f 100644 (file)
@@ -80,4 +80,36 @@ class LanguageCode {
                }
                return $code;
        }
+
+       /**
+        * Get the normalised IETF language tag
+        * See unit test for examples.
+        * See mediawiki.language.bcp47 for the JavaScript implementation.
+        *
+        * @param string $code The language code.
+        * @return string The language code which complying with BCP 47 standards.
+        *
+        * @since 1.31
+        */
+       public static function bcp47( $code ) {
+               $codeSegment = explode( '-', $code );
+               $codeBCP = [];
+               foreach ( $codeSegment as $segNo => $seg ) {
+                       // when previous segment is x, it is a private segment and should be lc
+                       if ( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
+                               $codeBCP[$segNo] = strtolower( $seg );
+                       // ISO 3166 country code
+                       } elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {
+                               $codeBCP[$segNo] = strtoupper( $seg );
+                       // ISO 15924 script code
+                       } elseif ( ( strlen( $seg ) == 4 ) && ( $segNo > 0 ) ) {
+                               $codeBCP[$segNo] = ucfirst( strtolower( $seg ) );
+                       // Use lowercase for other cases
+                       } else {
+                               $codeBCP[$segNo] = strtolower( $seg );
+                       }
+               }
+               $langCode = implode( '-', $codeBCP );
+               return $langCode;
+       }
 }
index 6a52434..45863a3 100644 (file)
 
                /**
                 * Formats language tags according the BCP47 standard.
-                * See wfBCP47 for the PHP implementation.
+                * See LanguageCode::bcp47 for the PHP implementation.
                 *
                 * @param {string} languageTag Well-formed language tag
                 * @return {string}
diff --git a/tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php b/tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php
deleted file mode 100644 (file)
index 8fbca6c..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-<?php
-/**
- * @group GlobalFunctions
- * @covers ::wfBCP47
- */
-class WfBCP47Test extends MediaWikiTestCase {
-       /**
-        * test @see wfBCP47().
-        * Please note the BCP 47 explicitly state that language codes are case
-        * insensitive, there are some exceptions to the rule :)
-        * This test is used to verify our formatting against all lower and
-        * all upper cases language code.
-        *
-        * @see https://tools.ietf.org/html/bcp47
-        * @dataProvider provideLanguageCodes()
-        */
-       public function testBCP47( $code, $expected ) {
-               $code = strtolower( $code );
-               $this->assertEquals( $expected, wfBCP47( $code ),
-                       "Applying BCP47 standard to lower case '$code'"
-               );
-
-               $code = strtoupper( $code );
-               $this->assertEquals( $expected, wfBCP47( $code ),
-                       "Applying BCP47 standard to upper case '$code'"
-               );
-       }
-
-       /**
-        * Array format is ($code, $expected)
-        */
-       public static function provideLanguageCodes() {
-               return [
-                       // Extracted from BCP 47 (list not exhaustive)
-                       # 2.1.1
-                       [ 'en-ca-x-ca', 'en-CA-x-ca' ],
-                       [ 'sgn-be-fr', 'sgn-BE-FR' ],
-                       [ 'az-latn-x-latn', 'az-Latn-x-latn' ],
-                       # 2.2
-                       [ 'sr-Latn-RS', 'sr-Latn-RS' ],
-                       [ 'az-arab-ir', 'az-Arab-IR' ],
-
-                       # 2.2.5
-                       [ 'sl-nedis', 'sl-nedis' ],
-                       [ 'de-ch-1996', 'de-CH-1996' ],
-
-                       # 2.2.6
-                       [
-                               'en-latn-gb-boont-r-extended-sequence-x-private',
-                               'en-Latn-GB-boont-r-extended-sequence-x-private'
-                       ],
-
-                       // Examples from BCP 47 Appendix A
-                       # Simple language subtag:
-                       [ 'DE', 'de' ],
-                       [ 'fR', 'fr' ],
-                       [ 'ja', 'ja' ],
-
-                       # Language subtag plus script subtag:
-                       [ 'zh-hans', 'zh-Hans' ],
-                       [ 'sr-cyrl', 'sr-Cyrl' ],
-                       [ 'sr-latn', 'sr-Latn' ],
-
-                       # Extended language subtags and their primary language subtag
-                       # counterparts:
-                       [ 'zh-cmn-hans-cn', 'zh-cmn-Hans-CN' ],
-                       [ 'cmn-hans-cn', 'cmn-Hans-CN' ],
-                       [ 'zh-yue-hk', 'zh-yue-HK' ],
-                       [ 'yue-hk', 'yue-HK' ],
-
-                       # Language-Script-Region:
-                       [ 'zh-hans-cn', 'zh-Hans-CN' ],
-                       [ 'sr-latn-RS', 'sr-Latn-RS' ],
-
-                       # Language-Variant:
-                       [ 'sl-rozaj', 'sl-rozaj' ],
-                       [ 'sl-rozaj-biske', 'sl-rozaj-biske' ],
-                       [ 'sl-nedis', 'sl-nedis' ],
-
-                       # Language-Region-Variant:
-                       [ 'de-ch-1901', 'de-CH-1901' ],
-                       [ 'sl-it-nedis', 'sl-IT-nedis' ],
-
-                       # Language-Script-Region-Variant:
-                       [ 'hy-latn-it-arevela', 'hy-Latn-IT-arevela' ],
-
-                       # Language-Region:
-                       [ 'de-de', 'de-DE' ],
-                       [ 'en-us', 'en-US' ],
-                       [ 'es-419', 'es-419' ],
-
-                       # Private use subtags:
-                       [ 'de-ch-x-phonebk', 'de-CH-x-phonebk' ],
-                       [ 'az-arab-x-aze-derbend', 'az-Arab-x-aze-derbend' ],
-                       /**
-                        * Previous test does not reflect the BCP 47 which states:
-                        *  az-Arab-x-AZE-derbend
-                        * AZE being private, it should be lower case, hence the test above
-                        * should probably be:
-                        * [ 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ],
-                        */
-
-                       # Private use registry values:
-                       [ 'x-whatever', 'x-whatever' ],
-                       [ 'qaa-qaaa-qm-x-southern', 'qaa-Qaaa-QM-x-southern' ],
-                       [ 'de-qaaa', 'de-Qaaa' ],
-                       [ 'sr-latn-qm', 'sr-Latn-QM' ],
-                       [ 'sr-qaaa-rs', 'sr-Qaaa-RS' ],
-
-                       # Tags that use extensions
-                       [ 'en-us-u-islamcal', 'en-US-u-islamcal' ],
-                       [ 'zh-cn-a-myext-x-private', 'zh-CN-a-myext-x-private' ],
-                       [ 'en-a-myext-b-another', 'en-a-myext-b-another' ],
-
-                       # Invalid:
-                       // de-419-DE
-                       // a-DE
-                       // ar-a-aaa-b-bbb-a-ccc
-               ];
-       }
-}
index 7689ef1..0da03df 100644 (file)
@@ -43,4 +43,119 @@ class LanguageCodeTest extends PHPUnit_Framework_TestCase {
                $this->assertEquals( null, LanguageCode::replaceDeprecatedCodes( null ) );
        }
 
+       /**
+        * test @see LanguageCode::bcp47().
+        * Please note the BCP 47 explicitly state that language codes are case
+        * insensitive, there are some exceptions to the rule :)
+        * This test is used to verify our formatting against all lower and
+        * all upper cases language code.
+        *
+        * @see https://tools.ietf.org/html/bcp47
+        * @dataProvider provideLanguageCodes()
+        */
+       public function testBcp47( $code, $expected ) {
+               $code = strtolower( $code );
+               $this->assertEquals( $expected, LanguageCode::bcp47( $code ),
+                       "Applying BCP47 standard to lower case '$code'"
+               );
+
+               $code = strtoupper( $code );
+               $this->assertEquals( $expected, LanguageCode::bcp47( $code ),
+                       "Applying BCP47 standard to upper case '$code'"
+               );
+       }
+
+       /**
+        * Array format is ($code, $expected)
+        */
+       public static function provideLanguageCodes() {
+               return [
+                       // Extracted from BCP 47 (list not exhaustive)
+                       # 2.1.1
+                       [ 'en-ca-x-ca', 'en-CA-x-ca' ],
+                       [ 'sgn-be-fr', 'sgn-BE-FR' ],
+                       [ 'az-latn-x-latn', 'az-Latn-x-latn' ],
+                       # 2.2
+                       [ 'sr-Latn-RS', 'sr-Latn-RS' ],
+                       [ 'az-arab-ir', 'az-Arab-IR' ],
+
+                       # 2.2.5
+                       [ 'sl-nedis', 'sl-nedis' ],
+                       [ 'de-ch-1996', 'de-CH-1996' ],
+
+                       # 2.2.6
+                       [
+                               'en-latn-gb-boont-r-extended-sequence-x-private',
+                               'en-Latn-GB-boont-r-extended-sequence-x-private'
+                       ],
+
+                       // Examples from BCP 47 Appendix A
+                       # Simple language subtag:
+                       [ 'DE', 'de' ],
+                       [ 'fR', 'fr' ],
+                       [ 'ja', 'ja' ],
+
+                       # Language subtag plus script subtag:
+                       [ 'zh-hans', 'zh-Hans' ],
+                       [ 'sr-cyrl', 'sr-Cyrl' ],
+                       [ 'sr-latn', 'sr-Latn' ],
+
+                       # Extended language subtags and their primary language subtag
+                       # counterparts:
+                       [ 'zh-cmn-hans-cn', 'zh-cmn-Hans-CN' ],
+                       [ 'cmn-hans-cn', 'cmn-Hans-CN' ],
+                       [ 'zh-yue-hk', 'zh-yue-HK' ],
+                       [ 'yue-hk', 'yue-HK' ],
+
+                       # Language-Script-Region:
+                       [ 'zh-hans-cn', 'zh-Hans-CN' ],
+                       [ 'sr-latn-RS', 'sr-Latn-RS' ],
+
+                       # Language-Variant:
+                       [ 'sl-rozaj', 'sl-rozaj' ],
+                       [ 'sl-rozaj-biske', 'sl-rozaj-biske' ],
+                       [ 'sl-nedis', 'sl-nedis' ],
+
+                       # Language-Region-Variant:
+                       [ 'de-ch-1901', 'de-CH-1901' ],
+                       [ 'sl-it-nedis', 'sl-IT-nedis' ],
+
+                       # Language-Script-Region-Variant:
+                       [ 'hy-latn-it-arevela', 'hy-Latn-IT-arevela' ],
+
+                       # Language-Region:
+                       [ 'de-de', 'de-DE' ],
+                       [ 'en-us', 'en-US' ],
+                       [ 'es-419', 'es-419' ],
+
+                       # Private use subtags:
+                       [ 'de-ch-x-phonebk', 'de-CH-x-phonebk' ],
+                       [ 'az-arab-x-aze-derbend', 'az-Arab-x-aze-derbend' ],
+                       /**
+                        * Previous test does not reflect the BCP 47 which states:
+                        *  az-Arab-x-AZE-derbend
+                        * AZE being private, it should be lower case, hence the test above
+                        * should probably be:
+                        * [ 'az-arab-x-aze-derbend', 'az-Arab-x-AZE-derbend' ],
+                        */
+
+                       # Private use registry values:
+                       [ 'x-whatever', 'x-whatever' ],
+                       [ 'qaa-qaaa-qm-x-southern', 'qaa-Qaaa-QM-x-southern' ],
+                       [ 'de-qaaa', 'de-Qaaa' ],
+                       [ 'sr-latn-qm', 'sr-Latn-QM' ],
+                       [ 'sr-qaaa-rs', 'sr-Qaaa-RS' ],
+
+                       # Tags that use extensions
+                       [ 'en-us-u-islamcal', 'en-US-u-islamcal' ],
+                       [ 'zh-cn-a-myext-x-private', 'zh-CN-a-myext-x-private' ],
+                       [ 'en-a-myext-b-another', 'en-a-myext-b-another' ],
+
+                       # Invalid:
+                       // de-419-DE
+                       // a-DE
+                       // ar-a-aaa-b-bbb-a-ccc
+               ];
+       }
+
 }