r69063 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r69062‎ | r69063 | r69064 >
Date:18:46, 5 July 2010
Author:roberthl
Status:deferred
Tags:
Comment:
Translate:
- Abstract JavaScript message formats.
- Add full support for Shapado JavaScript message format.
Modified paths:
  • /trunk/extensions/Translate/FFS.php (modified) (history)
  • /trunk/extensions/Translate/_autoload.php (modified) (history)
  • /trunk/extensions/Translate/groups/OpenLayers/OpenLayers.yml (modified) (history)
  • /trunk/extensions/Translate/groups/Shapado/Shapado.yml (modified) (history)

Diff [purge]

Index: trunk/extensions/Translate/FFS.php
@@ -363,83 +363,163 @@
364364 }
365365 }
366366
367 -class JavaScriptFFS extends SimpleFFS {
368 - private function leftTrim( $string ) {
369 - $string = ltrim( $string );
370 - $string = ltrim( $string, '"' );
 367+abstract class JavaScriptFFS extends SimpleFFS {
371368
372 - return $string;
373 - }
 369+ /**
 370+ * Message keys format.
 371+ */
 372+ abstract protected function transformKey( $key );
374373
 374+ /**
 375+ * Header of message file.
 376+ */
 377+ abstract protected function header( $code, $authors );
 378+
 379+ /**
 380+ * Footer of message file.
 381+ */
 382+ abstract protected function footer();
 383+
375384 public function readFromVariable( $data ) {
376 - // Add trailing comma to last key pair.
377 - $data = str_replace( "\"\n};", "\",\n};", $data );
378385
379 - // Just get relevant data.
 386+ /* Pre-processing */
 387+
 388+ // Find the start and end of the data section (enclosed in curly braces).
380389 $dataStart = strpos( $data, '{' );
381390 $dataEnd = strrpos( $data, '}' );
 391+ // Strip everything outside of the data section.
382392 $data = substr( $data, $dataStart + 1, $dataEnd - $dataStart - 1 );
 393+
383394 // Strip comments.
384395 $data = preg_replace( '#^(\s*?)//(.*?)$#m', '', $data );
385 - // Break in to message segements for further parsing.
386 - $data = explode( '",', $data );
387396
 397+ // Replace message endings with double quotes.
 398+ $data = preg_replace( "#\'\,\n#", "\",\n", $data );
 399+
 400+ // Strip excess whitespace.
 401+ $data = trim( $data );
 402+
 403+ /* Per-key message */
 404+
 405+ // Break in to segments.
 406+ $data = explode( "\",\n", $data );
 407+
388408 $messages = array();
389 - // Process each segment.
390 - foreach ( $data as $segment ) {
391 - // Remove excess quote mark at beginning.
392 - $segment = substr( $segment, 1 );
393 - // Add back trailing quote.
 409+ foreach( $data as $segment ) {
 410+ // Add back trailing quote, removed by explosion.
394411 $segment .= '"';
395 - // Concatenate seperate strings.
 412+
 413+ // Concatenate separate strings.
396414 $segment = explode( '" +', $segment );
397 - $segment = array_map( array( $this, 'leftTrim' ), $segment );
 415+ for( $i = 0; $i < count( $segment ); $i++ ) {
 416+ $segment[$i] = ltrim( $segment[$i] );
 417+ $segment[$i] = ltrim( $segment[$i], '"' );
 418+ }
398419 $segment = implode( $segment );
399 - # $segment = preg_replace( '#\" \+(.*?)\"#m', '', $segment );
 420+
 421+ // Remove line breaks between message keys and messages.
 422+ $segment = preg_replace( "#\:(\s+)[\\\"\']#", ': "', $segment );
 423+
400424 // Break in to key and message.
401 - $segments = explode( '\':', $segment );
 425+ $segments = explode( ': "', $segment );
402426 $key = $segments[ 0 ];
403 - unset( $segments[ 0 ] );
404 - $value = implode( $segments );
405 - // Strip excess whitespace from both.
 427+ $value = $segments[1];
 428+
 429+ // Strip excess whitespace from key and value.
406430 $key = trim( $key );
407431 $value = trim( $value );
408 - // Remove quotation marks and syntax.
409 - $key = substr( $key, 1 );
410 - $value = substr( $value, 1, - 1 );
 432+
 433+ // Strip quotation marks.
 434+ $key = trim( $key, '\'"' );
 435+ $value = trim( $value, '\'"' );
 436+
 437+ // Unescape any JavaScript and append to message array.
411438 $messages[ $key ] = self::unescapeJsString( $value );
412439 }
413440
414 - // Remove extraneous key that is sometimes present.
415 - unset( $messages[ 0 ] );
416 -
417441 return array( 'MESSAGES' => $messages );
418442 }
419443
420 - // Quick shortcut for getting the plain exported data
421444 public function writeIntoVariable( MessageCollection $collection ) {
422 - $code = $collection->code;
 445+ $r = $this->header( $collection->code, $collection->getAuthors() );
 446+
 447+ // Get and write messages.
 448+ foreach ( $collection as $message ) {
 449+ $key = $this->transformKey( Xml::escapeJsString( $message->key() ) );
 450+ $value = Xml::escapeJsString( $message->translation() );
 451+
 452+ $r .= " {$key}: \"{$value}\",\n\n";
 453+ }
 454+
 455+ // Strip last comma, re-add trailing newlines.
 456+ $r = substr( $r, 0, - 3 );
 457+ $r .= "\n\n";
 458+
 459+ return $r . $this->footer();
 460+ }
 461+
 462+ protected function authorsList( $authors ) {
 463+ if( count( $authors ) > 0 ) {
 464+ foreach ( $authors as $author ) {
 465+ $authorsList .= " * - $author\n";
 466+ }
 467+ return <<<EOT
 468+/* Translators:
 469+$authorsList */
 470+
 471+
 472+EOT;
 473+ } else {
 474+ return '';
 475+ }
 476+ }
 477+
 478+ private static function unescapeJsString( $string ) {
 479+ // See ECMA 262 section 7.8.4 for string literal format
 480+ $pairs = array(
 481+ "\\" => "\\\\",
 482+ "\"" => "\\\"",
 483+ '\'' => '\\\'',
 484+ "\n" => "\\n",
 485+ "\r" => "\\r",
 486+
 487+ # To avoid closing the element or CDATA section
 488+ "<" => "\\x3c",
 489+ ">" => "\\x3e",
 490+
 491+ # To avoid any complaints about bad entity refs
 492+ "&" => "\\x26",
 493+
 494+ # Work around https://bugzilla.mozilla.org/show_bug.cgi?id=274152
 495+ # Encode certain Unicode formatting chars so affected
 496+ # versions of Gecko don't misinterpret our strings;
 497+ # this is a common problem with Farsi text.
 498+ "\xe2\x80\x8c" => "\\u200c", // ZERO WIDTH NON-JOINER
 499+ "\xe2\x80\x8d" => "\\u200d", // ZERO WIDTH JOINER
 500+ );
 501+ $pairs = array_flip( $pairs );
 502+
 503+ return strtr( $string, $pairs );
 504+ }
 505+}
 506+
 507+class OpenLayersFFS extends JavaScriptFFS {
 508+ protected function transformKey( $key ) {
 509+ return "'$key'";
 510+ }
 511+
 512+ protected function header( $code, $authors ) {
423513 $names = Language::getLanguageNames();
424514 $name = $names[ $code ];
425515
426 - // Generate list of authors for comment.
427 - $authors = $collection->getAuthors();
428 - $authorList = '';
 516+ $authorsList = $this->authorsList( $authors );
429517
430 - foreach ( $authors as $author ) {
431 - $authorList .= " * - $author\n";
432 - }
433 -
434 - // Generate header and write.
435 - $r = <<<EOT
 518+ return <<<EOT
436519 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
437520 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
438521 * full text of the license. */
439522
440 -/* Translators (2009 onwards):
441 -$authorList */
442 -
443 -/**
 523+$authorsList/**
444524 * @requires OpenLayers/Lang.js
445525 */
446526
@@ -451,25 +531,33 @@
452532 */
453533 OpenLayers.Lang["$code"] = OpenLayers.Util.applyDefaults({
454534
455 -
456535 EOT;
 536+ }
457537
458 - // Get and write messages.
459 - foreach ( $collection as $message ) {
460 - $key = Xml::escapeJsString( $message->key() );
461 - $value = Xml::escapeJsString( $message->translation() );
 538+ protected function footer() {
 539+ return '});';
 540+ }
 541+}
462542
463 - $line = " '{$message->key()}': \"{$value}\",\n\n";
464 - $r .= $line;
465 - }
 543+class ShapadoJsFFS extends JavaScriptFFS {
 544+ protected function transformKey( $key ) {
 545+ return $key;
 546+ }
466547
467 - // Strip last comma.
468 - $r = substr( $r, 0, - 3 );
469 - $r .= "\n\n";
 548+ protected function header( $code, $authors ) {
470549
471 - // File terminator.
472 - return $r . '});';
 550+ $authorsList = $this->authorsList( $authors );
 551+
 552+ return <<<EOT
 553+{$authorsList}var I18n = {
 554+
 555+
 556+EOT;
473557 }
 558+
 559+ protected function footer() {
 560+ return '};';
 561+ }
474562 }
475563
476564 class YamlFFS extends SimpleFFS {
Index: trunk/extensions/Translate/groups/Shapado/Shapado.yml
@@ -466,3 +466,17 @@
467467
468468 MANGLER:
469469 prefix: wiki-
 470+
 471+---
 472+BASIC:
 473+ id: out-shapado-js
 474+ label: Shapado (JavaScript)
 475+ description: "{{int:bw-desc-shapado-js}}"
 476+ namespace: NS_SHAPADO
 477+ display: out/shapado/js
 478+ class: FileBasedMessageGroup
 479+
 480+FILES:
 481+ class: ShapadoJsFFS
 482+ sourcePattern: %GROUPROOT%/shapado/public/javascripts/i18n/%CODE%.js
 483+ targetPattern: shapado/public/javascripts/i18n/%CODE%.js
Index: trunk/extensions/Translate/groups/OpenLayers/OpenLayers.yml
@@ -8,8 +8,8 @@
99 class: FileBasedMessageGroup
1010
1111 FILES:
12 - class: JavaScriptFFS
13 - sourcePattern: %GROUPROOT%/Lang/%CODE%.js
 12+ class: OpenLayersFFS
 13+ sourcePattern: %GROUPROOT%/openlayers/%CODE%.js
1414 targetPattern: openlayers/%CODE%.js
1515 codeMap:
1616 cs: cs-CZ
Index: trunk/extensions/Translate/_autoload.php
@@ -128,6 +128,8 @@
129129 $wgAutoloadClasses['YamlFFS'] = $dir . 'FFS.php';
130130 $wgAutoloadClasses['RubyYamlFFS'] = $dir . 'FFS.php';
131131 $wgAutoloadClasses['JavaScriptFFS'] = $dir . 'FFS.php';
 132+$wgAutoloadClasses['OpenLayersFFS'] = $dir . 'FFS.php';
 133+$wgAutoloadClasses['ShapadoJsFFS'] = $dir . 'FFS.php';
132134 $wgAutoloadClasses['GettextFFS'] = $dir . '/ffs/Gettext.php';
133135
134136 $wgAutoloadClasses['HtmlTag'] = $dir . 'utils/Html.php';

Status & tagging log