From 8e0c0a9fc92263db8b88a4a379cb842105b923f6 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Tue, 1 Apr 2014 12:32:00 +0200 Subject: [PATCH] Preparations for migrating core to use JSON based i18n MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit LocalisationCache and Language have to take the JSON files into account in deciding if a language is present or not. Standardizing language validity checking with isSupportedLanguage and isValidBuiltInCode. Co-Authored-By: Niklas Laxström Co-Authored-By: Siebrand Mazeland Change-Id: I35bbb3a7a145fc48d14fff620407dff5ecfdd4fc --- includes/cache/LocalisationCache.php | 19 +++++------ languages/Language.php | 33 +++++++++++++++---- .../languages/LanguageClassesTestCase.php | 2 +- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/includes/cache/LocalisationCache.php b/includes/cache/LocalisationCache.php index d0274a1c93..8827219e01 100644 --- a/includes/cache/LocalisationCache.php +++ b/includes/cache/LocalisationCache.php @@ -448,7 +448,7 @@ class LocalisationCache { # Recache the data if necessary if ( !$this->manualRecache && $this->isExpired( $code ) ) { - if ( file_exists( Language::getMessagesFileName( $code ) ) ) { + if ( Language::isSupportedLanguage( $code ) ) { $this->recache( $code ); } elseif ( $code === 'en' ) { throw new MWException( 'MessagesEn.php is missing.' ); @@ -680,16 +680,16 @@ class LocalisationCache { global $IP; wfProfileIn( __METHOD__ ); + + // This reads in the PHP i18n file with non-messages l10n data $fileName = Language::getMessagesFileName( $code ); if ( !file_exists( $fileName ) ) { - wfProfileOut( __METHOD__ ); - - return false; + $data = array(); + } else { + $deps[] = new FileDependency( $fileName ); + $data = $this->readPHPFile( $fileName, 'core' ); } - $deps[] = new FileDependency( $fileName ); - $data = $this->readPHPFile( $fileName, 'core' ); - # Load CLDR plural rules for JavaScript $data['pluralRules'] = $this->getPluralRules( $code ); # And for PHP @@ -856,10 +856,7 @@ class LocalisationCache { $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] ); - # Load the extension localisations - # This is done after the core because we know the fallback sequence now. - # But it has a higher precedence for merging so that we can support things - # like site-specific message overrides. + # Load core messages and the extension localisations. wfProfileIn( __METHOD__ . '-extensions' ); $allData = $initialData; foreach ( $wgMessagesDirs as $dirs ) { diff --git a/languages/Language.php b/languages/Language.php index fcb0f097d7..8c68b60c2a 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -261,7 +261,10 @@ class Language { * @since 1.21 */ public static function isSupportedLanguage( $code ) { - return $code === strtolower( $code ) && is_readable( self::getMessagesFileName( $code ) ); + return self::isValidBuiltInCode( $code ) + && ( is_readable( self::getMessagesFileName( $code ) ) + || is_readable( self::getJsonMessagesFileName( $code ) ) + ); } /** @@ -351,7 +354,7 @@ class Language { /** * Returns true if a language code is of a valid form for the purposes of - * internal customisation of MediaWiki, via Messages*.php. + * internal customisation of MediaWiki, via Messages*.php or *.json. * * @param $code string * @@ -910,12 +913,16 @@ class Language { # We do this using a foreach over the codes instead of a directory # loop so that messages files in extensions will work correctly. foreach ( $returnMw as $code => $value ) { - if ( is_readable( self::getMessagesFileName( $code ) ) ) { + if ( is_readable( self::getMessagesFileName( $code ) ) + || is_readable( self::getJsonMessagesFileName( $code ) ) + ) { $namesMwFile[$code] = $names[$code]; } } + return $namesMwFile; } + # 'mw' option; default if it's not one of the other two options (all/mwfile) return $returnMw; } @@ -4048,10 +4055,7 @@ class Language { * @return string $prefix . $mangledCode . $suffix */ public static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) { - // Protect against path traversal - if ( !Language::isValidCode( $code ) - || strcspn( $code, ":/\\\000" ) !== strlen( $code ) - ) { + if ( !self::isValidBuiltInCode( $code ) ) { throw new MWException( "Invalid language code \"$code\"" ); } @@ -4086,6 +4090,21 @@ class Language { return $file; } + /** + * @param $code string + * @return string + * @since 1.23 + */ + public static function getJsonMessagesFileName( $code ) { + global $IP; + + if ( !self::isValidBuiltInCode( $code ) ) { + throw new MWException( "Invalid language code \"$code\"" ); + } + + return "$IP/languages/i18n/$code.json" ; + } + /** * @param $code string * @return string diff --git a/tests/phpunit/languages/LanguageClassesTestCase.php b/tests/phpunit/languages/LanguageClassesTestCase.php index 632e037ff3..f93ff7d388 100644 --- a/tests/phpunit/languages/LanguageClassesTestCase.php +++ b/tests/phpunit/languages/LanguageClassesTestCase.php @@ -50,7 +50,7 @@ abstract class LanguageClassesTestCase extends MediaWikiTestCase { $found = preg_match( '/Language(.+)Test/', get_called_class(), $m ); if ( $found ) { # Normalize language code since classes uses underscores - $m[1] = str_replace( '_', '-', $m[1] ); + $m[1] = strtolower( str_replace( '_', '-', $m[1] ) ); } else { # Fallback to english language $m[1] = 'en'; -- 2.20.1