MediaWiki  1.34.0
LanguageLibrary.php
Go to the documentation of this file.
1 <?php
2 
4 
6  public $langCache = [];
7  public $timeCache = [];
9 
10  public function register() {
11  // Pre-populate the language cache
12  global $wgContLang;
13  $this->langCache[$wgContLang->getCode()] = $wgContLang;
14  $this->maxLangCacheSize = $this->getEngine()->getOption( 'maxLangCacheSize' );
15 
16  $statics = [
17  'getContLangCode',
18  'isSupportedLanguage',
19  'isKnownLanguageTag',
20  'isValidCode',
21  'isValidBuiltInCode',
22  'fetchLanguageName',
23  'fetchLanguageNames',
24  'getFallbacksFor',
25  ];
26  $methods = [
27  'lcfirst',
28  'ucfirst',
29  'lc',
30  'uc',
31  'caseFold',
32  'formatNum',
33  'formatDate',
34  'formatDuration',
35  'getDurationIntervals',
36  'parseFormattedNumber',
37  'convertPlural',
38  'convertGrammar',
39  'gender',
40  'isRTL',
41  ];
42  $lib = [];
43  foreach ( $statics as $name ) {
44  $lib[$name] = [ $this, $name ];
45  }
46  $ths = $this;
47  foreach ( $methods as $name ) {
48  $lib[$name] = function () use ( $ths, $name ) {
49  $args = func_get_args();
50  return $ths->languageMethod( $name, $args );
51  };
52  }
53  return $this->getEngine()->registerInterface( 'mw.language.lua', $lib );
54  }
55 
61  public function getContLangCode() {
62  global $wgContLang;
63  return [ $wgContLang->getCode() ];
64  }
65 
72  public function isSupportedLanguage( $code ) {
73  $this->checkType( 'isSupportedLanguage', 1, $code, 'string' );
74  try {
75  // There's no good reason this should throw, but it does. Sigh.
76  return [ Language::isSupportedLanguage( $code ) ];
77  } catch ( MWException $ex ) {
78  return [ false ];
79  }
80  }
81 
88  public function isKnownLanguageTag( $code ) {
89  $this->checkType( 'isKnownLanguageTag', 1, $code, 'string' );
90  return [ Language::isKnownLanguageTag( $code ) ];
91  }
92 
99  public function isValidCode( $code ) {
100  $this->checkType( 'isValidCode', 1, $code, 'string' );
101  return [ Language::isValidCode( $code ) ];
102  }
103 
110  public function isValidBuiltInCode( $code ) {
111  $this->checkType( 'isValidBuiltInCode', 1, $code, 'string' );
112  return [ (bool)Language::isValidBuiltInCode( $code ) ];
113  }
114 
122  public function fetchLanguageName( $code, $inLanguage ) {
123  $this->checkType( 'fetchLanguageName', 1, $code, 'string' );
124  $this->checkTypeOptional( 'fetchLanguageName', 2, $inLanguage, 'string', null );
125  return [ Language::fetchLanguageName( $code, $inLanguage ) ];
126  }
127 
135  public function fetchLanguageNames( $inLanguage, $include ) {
136  $this->checkTypeOptional( 'fetchLanguageNames', 1, $inLanguage, 'string', null );
137  $this->checkTypeOptional( 'fetchLanguageNames', 2, $include, 'string', 'mw' );
138  return [ Language::fetchLanguageNames( $inLanguage, $include ) ];
139  }
140 
147  public function getFallbacksFor( $code ) {
148  $this->checkType( 'getFallbacksFor', 1, $code, 'string' );
149  $ret = Language::getFallbacksFor( $code );
150  // Make 1-based
151  if ( count( $ret ) ) {
152  $ret = array_combine( range( 1, count( $ret ) ), $ret );
153  }
154  return [ $ret ];
155  }
156 
165  public function languageMethod( $name, $args ) {
166  $name = strval( $name );
167  $code = array_shift( $args );
168  if ( !isset( $this->langCache[$code] ) ) {
169  if ( count( $this->langCache ) > $this->maxLangCacheSize ) {
170  throw new Scribunto_LuaError( 'too many language codes requested' );
171  }
172  try {
173  $this->langCache[$code] = Language::factory( $code );
174  } catch ( MWException $ex ) {
175  throw new Scribunto_LuaError( "language code '$code' is invalid" );
176  }
177  }
178  $lang = $this->langCache[$code];
179  switch ( $name ) {
180  // Zero arguments
181  case 'isRTL':
182  return [ $lang->$name() ];
183 
184  // One string argument passed straight through
185  case 'lcfirst':
186  case 'ucfirst':
187  case 'lc':
188  case 'uc':
189  case 'caseFold':
190  $this->checkType( $name, 1, $args[0], 'string' );
191  return [ $lang->$name( $args[0] ) ];
192 
193  case 'parseFormattedNumber':
194  if ( is_numeric( $args[0] ) ) {
195  $args[0] = strval( $args[0] );
196  }
197  if ( $this->getLuaType( $args[0] ) !== 'string' ) {
198  // Be like tonumber(), return nil instead of erroring out
199  return [ null ];
200  }
201  return [ $lang->$name( $args[0] ) ];
202 
203  // Custom handling
204  default:
205  return $this->$name( $lang, $args );
206  }
207  }
208 
216  public function convertPlural( $lang, $args ) {
217  $number = array_shift( $args );
218  $this->checkType( 'convertPlural', 1, $number, 'number' );
219  if ( is_array( $args[0] ) ) {
220  $args = $args[0];
221  }
222  $forms = array_values( array_map( 'strval', $args ) );
223  return [ $lang->convertPlural( $number, $forms ) ];
224  }
225 
233  public function convertGrammar( $lang, $args ) {
234  $this->checkType( 'convertGrammar', 1, $args[0], 'string' );
235  $this->checkType( 'convertGrammar', 2, $args[1], 'string' );
236  return [ $lang->convertGrammar( $args[0], $args[1] ) ];
237  }
238 
246  public function gender( $lang, $args ) {
247  $this->checkType( 'gender', 1, $args[0], 'string' );
248  $username = trim( array_shift( $args ) );
249 
250  if ( is_array( $args[0] ) ) {
251  $args = $args[0];
252  }
253  $forms = array_values( array_map( 'strval', $args ) );
254 
255  // Shortcuts
256  if ( count( $forms ) === 0 ) {
257  return [ '' ];
258  } elseif ( count( $forms ) === 1 ) {
259  return [ $forms[0] ];
260  }
261 
262  if ( $username === 'male' || $username === 'female' ) {
263  $gender = $username;
264  } else {
265  // default
266  $gender = User::getDefaultOption( 'gender' );
267 
268  // Check for "User:" prefix
269  $title = Title::newFromText( $username );
270  if ( $title && $title->getNamespace() == NS_USER ) {
271  $username = $title->getText();
272  }
273 
274  // check parameter, or use the ParserOptions if in interface message
275  $user = User::newFromName( $username );
276  if ( $user ) {
277  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
278  $gender = $genderCache->getGenderOf( $user, __METHOD__ );
279  } elseif ( $username === '' ) {
280  $parserOptions = $this->getParserOptions();
281  if ( $parserOptions->getInterfaceMessage() ) {
282  $genderCache = MediaWikiServices::getInstance()->getGenderCache();
283  $gender = $genderCache->getGenderOf( $parserOptions->getUser(), __METHOD__ );
284  }
285  }
286  }
287  return [ $lang->gender( $gender, $forms ) ];
288  }
289 
297  public function formatNum( $lang, $args ) {
298  $num = $args[0];
299  $this->checkType( 'formatNum', 1, $num, 'number' );
300 
301  $noCommafy = false;
302  if ( isset( $args[1] ) ) {
303  $this->checkType( 'formatNum', 2, $args[1], 'table' );
304  $options = $args[1];
305  $noCommafy = !empty( $options['noCommafy'] );
306  }
307  return [ $lang->formatNum( $num, $noCommafy ) ];
308  }
309 
318  public function formatDate( $lang, $args ) {
319  $this->checkType( 'formatDate', 1, $args[0], 'string' );
320  $this->checkTypeOptional( 'formatDate', 2, $args[1], 'string', '' );
321  $this->checkTypeOptional( 'formatDate', 3, $args[2], 'boolean', false );
322 
323  list( $format, $date, $local ) = $args;
324  $langcode = $lang->getCode();
325 
326  if ( $date === '' ) {
327  $cacheKey = $this->getParserOptions()->getTimestamp();
328  $timestamp = new MWTimestamp( $cacheKey );
329  $date = $timestamp->getTimestamp( TS_ISO_8601 );
330  $useTTL = true;
331  } else {
332  # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
333  if ( preg_match( '/^[0-9]{4}$/', $date ) ) {
334  $date = '00:00 ' . $date;
335  }
336 
337  $cacheKey = $date;
338  $useTTL = false;
339  }
340 
341  if ( isset( $this->timeCache[$format][$cacheKey][$langcode][$local] ) ) {
342  $ttl = $this->timeCache[$format][$cacheKey][$langcode][$local][1];
343  if ( $useTTL && $ttl !== null ) {
344  $this->getEngine()->setTTL( $ttl );
345  }
346  return [ $this->timeCache[$format][$cacheKey][$langcode][$local][0] ];
347  }
348 
349  # Default input timezone is UTC.
350  try {
351  $utc = new DateTimeZone( 'UTC' );
352  $dateObject = new DateTime( $date, $utc );
353  } catch ( Exception $ex ) {
354  throw new Scribunto_LuaError( "bad argument #2 to 'formatDate' (not a valid timestamp)" );
355  }
356 
357  # Set output timezone.
358  if ( $local ) {
359  global $wgLocaltimezone;
360  if ( isset( $wgLocaltimezone ) ) {
361  $tz = new DateTimeZone( $wgLocaltimezone );
362  } else {
363  $tz = new DateTimeZone( date_default_timezone_get() );
364  }
365  } else {
366  $tz = $utc;
367  }
368  $dateObject->setTimezone( $tz );
369  # Generate timestamp
370  $ts = $dateObject->format( 'YmdHis' );
371 
372  if ( $ts < 0 ) {
373  throw new Scribunto_LuaError( "mw.language:formatDate() only supports years from 0" );
374  } elseif ( $ts >= 100000000000000 ) {
375  throw new Scribunto_LuaError( "mw.language:formatDate() only supports years up to 9999" );
376  }
377 
378  $ttl = null;
379  $ret = $lang->sprintfDate( $format, $ts, $tz, $ttl );
380  $this->timeCache[$format][$cacheKey][$langcode][$local] = [ $ret, $ttl ];
381  if ( $useTTL && $ttl !== null ) {
382  $this->getEngine()->setTTL( $ttl );
383  }
384  return [ $ret ];
385  }
386 
394  public function formatDuration( $lang, $args ) {
395  $this->checkType( 'formatDuration', 1, $args[0], 'number' );
396  $this->checkTypeOptional( 'formatDuration', 2, $args[1], 'table', [] );
397 
398  list( $seconds, $chosenIntervals ) = $args;
399  $langcode = $lang->getCode();
400  $chosenIntervals = array_values( $chosenIntervals );
401 
402  $ret = $lang->formatDuration( $seconds, $chosenIntervals );
403  return [ $ret ];
404  }
405 
413  public function getDurationIntervals( $lang, $args ) {
414  $this->checkType( 'getDurationIntervals', 1, $args[0], 'number' );
415  $this->checkTypeOptional( 'getDurationIntervals', 2, $args[1], 'table', [] );
416 
417  list( $seconds, $chosenIntervals ) = $args;
418  $langcode = $lang->getCode();
419  $chosenIntervals = array_values( $chosenIntervals );
420 
421  $ret = $lang->getDurationIntervals( $seconds, $chosenIntervals );
422  return [ $ret ];
423  }
424 }
User\getDefaultOption
static getDefaultOption( $opt)
Get a given default option value.
Definition: User.php:1693
Language\fetchLanguageName
static fetchLanguageName( $code, $inLanguage=self::AS_AUTONYMS, $include=self::ALL)
Definition: Language.php:832
MWTimestamp
Library for creating and parsing MW-style timestamps.
Definition: MWTimestamp.php:32
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:316
Scribunto_LuaLanguageLibrary\isSupportedLanguage
isSupportedLanguage( $code)
Handler for isSupportedLanguage.
Definition: LanguageLibrary.php:72
Scribunto_LuaLanguageLibrary\$langCache
$langCache
Definition: LanguageLibrary.php:6
Scribunto_LuaError
Definition: LuaCommon.php:992
Scribunto_LuaLanguageLibrary\languageMethod
languageMethod( $name, $args)
Language object method handler.
Definition: LanguageLibrary.php:165
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:117
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
Scribunto_LuaLanguageLibrary\$timeCache
$timeCache
Definition: LanguageLibrary.php:7
Scribunto_LuaLanguageLibrary\gender
gender( $lang, $args)
gender handler
Definition: LanguageLibrary.php:246
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:515
Scribunto_LuaLanguageLibrary\convertPlural
convertPlural( $lang, $args)
convertPlural handler
Definition: LanguageLibrary.php:216
Scribunto_LuaLibraryBase\getEngine
getEngine()
Get the engine.
Definition: LibraryBase.php:56
Language\isKnownLanguageTag
static isKnownLanguageTag( $tag)
Returns true if a language code is an IETF tag known to MediaWiki.
Definition: Language.php:415
Scribunto_LuaLibraryBase\checkType
checkType( $name, $argIdx, $arg, $expectType)
Check the type of a variable.
Definition: LibraryBase.php:141
MWException
MediaWiki exception.
Definition: MWException.php:26
Scribunto_LuaLanguageLibrary\$maxLangCacheSize
$maxLangCacheSize
Definition: LanguageLibrary.php:8
Scribunto_LuaLanguageLibrary\getDurationIntervals
getDurationIntervals( $lang, $args)
getDurationIntervals handler
Definition: LanguageLibrary.php:413
$title
$title
Definition: testCompression.php:34
Scribunto_LuaLibraryBase\checkTypeOptional
checkTypeOptional( $name, $argIdx, &$arg, $expectType, $default)
Check the type of a variable, with default if null.
Definition: LibraryBase.php:164
Scribunto_LuaLibraryBase
This class provides some basic services that Lua libraries will probably need.
Definition: LibraryBase.php:27
Language\isValidBuiltInCode
static isValidBuiltInCode( $code)
Returns true if a language code is of a valid form for the purposes of internal customisation of Medi...
Definition: Language.php:400
Scribunto_LuaLibraryBase\getParserOptions
getParserOptions()
Get the parser options.
Definition: LibraryBase.php:92
Scribunto_LuaLanguageLibrary\formatDuration
formatDuration( $lang, $args)
formatDuration handler
Definition: LanguageLibrary.php:394
Scribunto_LuaLanguageLibrary\isValidBuiltInCode
isValidBuiltInCode( $code)
Handler for isValidBuiltInCode.
Definition: LanguageLibrary.php:110
Scribunto_LuaLanguageLibrary\getFallbacksFor
getFallbacksFor( $code)
Handler for fetchLanguageNames.
Definition: LanguageLibrary.php:147
Language\isValidCode
static isValidCode( $code)
Returns true if a language code string is of a valid form, whether or not it exists.
Definition: Language.php:385
Scribunto_LuaLanguageLibrary\formatDate
formatDate( $lang, $args)
formatDate handler
Definition: LanguageLibrary.php:318
$args
if( $line===false) $args
Definition: cdb.php:64
Scribunto_LuaLanguageLibrary\convertGrammar
convertGrammar( $lang, $args)
convertGrammar handler
Definition: LanguageLibrary.php:233
Scribunto_LuaLanguageLibrary\formatNum
formatNum( $lang, $args)
formatNum handler
Definition: LanguageLibrary.php:297
$wgLocaltimezone
$wgLocaltimezone
Fake out the timezone that the server thinks it's in.
Definition: DefaultSettings.php:3215
NS_USER
const NS_USER
Definition: Defines.php:62
Scribunto_LuaLanguageLibrary\getContLangCode
getContLangCode()
Handler for getContLangCode.
Definition: LanguageLibrary.php:61
Scribunto_LuaLanguageLibrary
Definition: LanguageLibrary.php:5
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:217
Scribunto_LuaLanguageLibrary\isKnownLanguageTag
isKnownLanguageTag( $code)
Handler for isKnownLanguageTag.
Definition: LanguageLibrary.php:88
Scribunto_LuaLanguageLibrary\fetchLanguageName
fetchLanguageName( $code, $inLanguage)
Handler for fetchLanguageName.
Definition: LanguageLibrary.php:122
Language\isSupportedLanguage
static isSupportedLanguage( $code)
Checks whether any localisation is available for that language tag in MediaWiki (MessagesXx....
Definition: Language.php:309
Language\fetchLanguageNames
static fetchLanguageNames( $inLanguage=self::AS_AUTONYMS, $include='mw')
Get an array of language names, indexed by code.
Definition: Language.php:818
Scribunto_LuaLanguageLibrary\isValidCode
isValidCode( $code)
Handler for isValidCode.
Definition: LanguageLibrary.php:99
$wgContLang
$wgContLang
Definition: Setup.php:801
Scribunto_LuaLanguageLibrary\fetchLanguageNames
fetchLanguageNames( $inLanguage, $include)
Handler for fetchLanguageNames.
Definition: LanguageLibrary.php:135
Scribunto_LuaLibraryBase\getLuaType
getLuaType( $var)
Get the Lua type corresponding to the type of the variable.
Definition: LibraryBase.php:106
Language\getFallbacksFor
static getFallbacksFor( $code, $mode=self::MESSAGES_FALLBACKS)
Get the ordered list of fallback languages.
Definition: Language.php:4404