class FakeConverter {
var $mLang;
function FakeConverter($langobj) {$this->mLang = $langobj;}
+ function autoConvertToAllVariants($text) {return $text;}
function convert($t, $i) {return $t;}
function parserConvert($t, $p) {return $t;}
function getVariants() { return array( $this->mLang->getCode() ); }
function getPreferredVariant() {return $this->mLang->getCode(); }
- function findVariantLink(&$l, &$n, $forTemplate = false) {}
+ function findVariantLink(&$l, &$n, $ignoreOtherCond = false) {}
function getExtraHashOptions() {return '';}
function getParsedTitle() {return '';}
function markNoConversion($text, $noParse=false) {return $text;}
static public $mLocalisationKeys = array(
'fallback', 'namespaceNames', 'mathNames', 'bookstoreList',
- 'magicWords', 'messages', 'rtl', 'digitTransformTable',
+ 'magicWords', 'messages', 'rtl', 'capitalizeAllNouns', 'digitTransformTable',
'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension',
'defaultUserOptionOverrides', 'linkTrail', 'namespaceAliases',
'dateFormats', 'datePreferences', 'datePreferenceMigrationMap',
*
* xkY Y (full year) in Thai solar calendar. Months and days are
* identical to the Gregorian calendar
+ * xoY Y (full year) in Minguo calendar or Juche year.
+ * Months and days are identical to the
+ * Gregorian calendar
+ * xtY Y (full year) in Japanese nengo. Months and days are
+ * identical to the Gregorian calendar
*
* Characters enclosed in double quotes will be considered literal (with
* the quotes themselves removed). Unmatched quotes will be considered
$hebrew = false;
$hijri = false;
$thai = false;
+ $minguo = false;
+ $tenno = false;
for ( $p = 0; $p < strlen( $format ); $p++ ) {
$num = false;
$code = $format[$p];
$code .= $format[++$p];
}
- if ( ( $code === 'xi' || $code == 'xj' || $code == 'xk' || $code == 'xm' ) && $p < strlen( $format ) - 1 ) {
+ if ( ( $code === 'xi' || $code == 'xj' || $code == 'xk' || $code == 'xm' || $code == 'xo' || $code == 'xt' ) && $p < strlen( $format ) - 1 ) {
$code .= $format[++$p];
}
$num = $hebrew[0];
break;
case 'xkY':
- if ( !$thai ) $thai = self::tsToThai( $ts );
+ if ( !$thai ) $thai = self::tsToYear( $ts, 'thai' );
$num = $thai[0];
break;
+ case 'xoY':
+ if ( !$minguo ) $minguo = self::tsToYear( $ts, 'minguo' );
+ $num = $minguo[0];
+ break;
+ case 'xtY':
+ if ( !$tenno ) $tenno = self::tsToYear( $ts, 'tenno' );
+ $num = $tenno[0];
+ break;
case 'y':
$num = substr( $ts, 2, 2 );
break;
}
/**
- * Algorithm to convert Gregorian dates to Thai solar dates.
+ * Algorithm to convert Gregorian dates to Thai solar dates,
+ * Minguo dates or Minguo dates.
*
* Link: http://en.wikipedia.org/wiki/Thai_solar_calendar
+ * http://en.wikipedia.org/wiki/Minguo_calendar
+ * http://en.wikipedia.org/wiki/Japanese_era_name
*
- * @param $ts String: 14-character timestamp
+ * @param $ts String: 14-character timestamp, calender name
* @return array converted year, month, day
*/
- private static function tsToThai( $ts ) {
+ private static function tsToYear( $ts, $cName ) {
$gy = substr( $ts, 0, 4 );
$gm = substr( $ts, 4, 2 );
$gd = substr( $ts, 6, 2 );
- # Add 543 years to the Gregorian calendar
- # Months and days are identical
- $gy_thai = $gy + 543;
+ if (!strcmp($cName,'thai')) {
+ # Thai solar dates
+ # Add 543 years to the Gregorian calendar
+ # Months and days are identical
+ $gy_offset = $gy + 543;
+ } else if ((!strcmp($cName,'minguo')) || !strcmp($cName,'juche')) {
+ # Minguo dates
+ # Deduct 1911 years from the Gregorian calendar
+ # Months and days are identical
+ $gy_offset = $gy - 1911;
+ } else if (!strcmp($cName,'tenno')) {
+ # Nengō dates up to Meiji period
+ # Deduct years from the Gregorian calendar
+ # depending on the nengo periods
+ # Months and days are identical
+ if (($gy < 1912) || (($gy == 1912) && ($gm < 7)) || (($gy == 1912) && ($gm == 7) && ($gd < 31))) {
+ # Meiji period
+ $gy_gannen = $gy - 1868 + 1;
+ $gy_offset = $gy_gannen;
+ if ($gy_gannen == 1)
+ $gy_offset = '元';
+ $gy_offset = '明治'.$gy_offset;
+ } else if ((($gy == 1912) && ($gm == 7) && ($gd == 31)) || (($gy == 1912) && ($gm >= 8)) || (($gy > 1912) && ($gy < 1926)) || (($gy == 1926) && ($gm < 12)) || (($gy == 1926) && ($gm == 12) && ($gd < 26))) {
+ # Taishō period
+ $gy_gannen = $gy - 1912 + 1;
+ $gy_offset = $gy_gannen;
+ if ($gy_gannen == 1)
+ $gy_offset = '元';
+ $gy_offset = '大正'.$gy_offset;
+ } else if ((($gy == 1926) && ($gm == 12) && ($gd >= 26)) || (($gy > 1926) && ($gy < 1989)) || (($gy == 1989) && ($gm == 1) && ($gd < 8))) {
+ # Shōwa period
+ $gy_gannen = $gy - 1926 + 1;
+ $gy_offset = $gy_gannen;
+ if ($gy_gannen == 1)
+ $gy_offset = '元';
+ $gy_offset = '昭和'.$gy_offset;
+ } else {
+ # Heisei period
+ $gy_gannen = $gy - 1989 + 1;
+ $gy_offset = $gy_gannen;
+ if ($gy_gannen == 1)
+ $gy_offset = '元';
+ $gy_offset = '平成'.$gy_offset;
+ }
+ } else {
+ $gy_offset = $gy;
+ }
- return array( $gy_thai, $gm, $gd );
+ return array( $gy_offset, $gm, $gd );
}
-
/**
* Roman number formatting up to 3000
*/
$n = $minLength-1;
$out = preg_replace(
"/\b(\w{1,$n})\b/",
- "$1U800",
+ "$1u800",
$out );
}
// "example.wikipedia.com" and "192.168.83.1" as well.
$out = preg_replace(
"/(\w)\.(\w|\*)/u",
- "$1U82e$2",
+ "$1u82e$2",
$out );
wfProfileOut( __METHOD__ );
* settings or anything else of the sort.
*/
protected function stripForSearchCallback( $matches ) {
- return 'U8' . bin2hex( $matches[1] );
+ return 'u8' . bin2hex( $matches[1] );
}
/**
return $this->isRTL() ? "\xE2\x80\x8F" : "\xE2\x80\x8E";
}
+ function capitalizeAllNouns() {
+ $this->load();
+ return $this->capitalizeAllNouns;
+ }
+
/**
* An arrow, depending on the language direction
*
function commaList( $list ) {
return implode(
$list,
- wfMsgExt( 'comma-separator', array( 'escapenoentities', 'language' => $this ) ) );
+ wfMsgExt( 'comma-separator', array( 'parsemag', 'escapenoentities', 'language' => $this ) ) );
}
-
+
+ /**
+ * Take a list of strings and build a locale-friendly semicolon-separated
+ * list, using the local semicolon-separator message.
+ * @param $list array of strings to put in a semicolon list
+ * @return string
+ */
+ function semicolonList( $list ) {
+ return implode(
+ $list,
+ wfMsgExt( 'semicolon-separator', array( 'parsemag', 'escapenoentities', 'language' => $this ) ) );
+ }
+
/**
* Same as commaList, but separate it with the pipe instead.
* @param $list array of strings to put in a pipe list
* @param $ellipsis String to append to the truncated text
* @return string
*/
- function truncate( $string, $length, $ellipsis = "" ) {
+ function truncate( $string, $length, $ellipsis = '...' ) {
+ # Use the localized ellipsis character
+ if( $ellipsis == '...' ) {
+ $ellipsis = wfMsgExt( 'ellipsis', array( 'escapenoentities', 'language' => $this ) );
+ }
+
if( $length == 0 ) {
return $ellipsis;
}
} elseif( $char >= 0x80 &&
preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
'[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m ) ) {
- # We chopped in the middle of a character; remove it
+ # We chopped in the middle of a character; remove it
$string = $m[1];
}
return $string . $ellipsis;
* These details may be overriden per language.
*/
function gender( $gender, $forms ) {
+ if ( !count($forms) ) { return ''; }
$forms = $this->preConvertPlural( $forms, 2 );
if ( $gender === 'male' ) return $forms[0];
if ( $gender === 'female' ) return $forms[1];
return $text;
}
+ # convert text to all supported variants
+ function autoConvertToAllVariants($text) {
+ return $this->mConverter->autoConvertToAllVariants($text);
+ }
+
# convert text to different variants of a language.
function convert( $text, $isTitle = false) {
return $this->mConverter->convert($text, $isTitle);
*
* @param $link String: the name of the link
* @param $nt Mixed: the title object of the link
+ * @param boolean $ignoreOtherCond: to disable other conditions when
+ * we need to transclude a template or update a category's link
* @return null the input parameters may be modified upon return
*/
- function findVariantLink( &$link, &$nt, $forTemplate = false ) {
- $this->mConverter->findVariantLink($link, $nt, $forTemplate );
+ function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
+ $this->mConverter->findVariantLink( $link, $nt, $ignoreOtherCond );
}
/**
* into an array of all possible variants of the text:
* 'variant' => text in that variant
*/
-
function convertLinkToAllVariants($text){
return $this->mConverter->convertLinkToAllVariants($text);
}
return self::$mLocalisationCache[$code]['deps'];
}
}
+ } else {
+ $cache = false;
}
# Try the global cache
wfDebug( "Language::loadLocalisation(): got localisation for $code from source\n" );
}
+ # Load magic word source file
+ global $IP;
+ $filename = "$IP/includes/MagicWord.php";
+ $newDeps = array( $filename => filemtime( $filename ) );
+ $deps = array_merge( $deps, $newDeps );
+
if ( !empty( $fallback ) ) {
# Load the fallback localisation, with a circular reference guard
if ( isset( $recursionGuard[$code] ) ) {
self::loadLocalisation( $cache );
$cache = self::$mLocalisationCache[$cache];
}
+ // At least one language file and the MagicWord file needed
+ if( count($cache['deps']) < 2 ) {
+ return true;
+ }
$expired = false;
foreach ( $cache['deps'] as $file => $mtime ) {
if ( !file_exists( $file ) || filemtime( $file ) > $mtime ) {
$this->namespaceNames[NS_PROJECT_TALK] = $wgMetaNamespaceTalk;
} else {
$talk = $this->namespaceNames[NS_PROJECT_TALK];
- $talk = str_replace( '$1', $wgMetaNamespace, $talk );
-
- # Allow grammar transformations
- # Allowing full message-style parsing would make simple requests
- # such as action=raw much more expensive than they need to be.
- # This will hopefully cover most cases.
- $talk = preg_replace_callback( '/{{grammar:(.*?)\|(.*?)}}/i',
- array( &$this, 'replaceGrammarInNamespace' ), $talk );
- $talk = str_replace( ' ', '_', $talk );
- $this->namespaceNames[NS_PROJECT_TALK] = $talk;
+ $this->namespaceNames[NS_PROJECT_TALK] =
+ $this->fixVariableInNamespace( $talk );
}
# The above mixing may leave namespaces out of canonical order.
}
if ( $this->namespaceAliases ) {
foreach ( $this->namespaceAliases as $name => $index ) {
+ if ( $index === NS_PROJECT_TALK ) {
+ unset( $this->namespaceAliases[$name] );
+ $name = $this->fixVariableInNamespace( $name );
+ $this->namespaceAliases[$name] = $index;
+ }
$this->mNamespaceIds[$this->lc($name)] = $index;
}
}
wfProfileOut( __METHOD__ );
}
+ function fixVariableInNamespace( $talk ) {
+ if ( strpos( $talk, '$1' ) === false ) return $talk;
+
+ global $wgMetaNamespace;
+ $talk = str_replace( '$1', $wgMetaNamespace, $talk );
+
+ # Allow grammar transformations
+ # Allowing full message-style parsing would make simple requests
+ # such as action=raw much more expensive than they need to be.
+ # This will hopefully cover most cases.
+ $talk = preg_replace_callback( '/{{grammar:(.*?)\|(.*?)}}/i',
+ array( &$this, 'replaceGrammarInNamespace' ), $talk );
+ return str_replace( ' ', '_', $talk );
+ }
+
function replaceGrammarInNamespace( $m ) {
return $this->convertGrammar( trim( $m[2] ), trim( $m[1] ) );
}