Making WordPress.org

Ticket #760: 760-wporg.2.diff

File 760-wporg.2.diff, 22.3 KB (added by stephdau, 10 years ago)
  • extend/plugins-plugins/svn-track/class.dotorg-plugins-i18n.php

     
     1<?php
     2class Dotorg_Plugin_I18n {
     3        var $db;
     4        var $tracker;
     5
     6        // TODO: remove when we launch for all plugins.
     7        var $translated_plugins = array(
     8                'blogware-importer',
     9                'livejournal-importer',
     10        );
     11
     12        var $i18n_cache_group = 'plugin-i18n';
     13
     14        function __construct( $db, $tracker = null ) {
     15                if ( !empty( $db ) && is_object( $db ) )
     16                        $this->db = $db;
     17                if ( !empty( $tracker ) && is_object( $tracker ) )
     18                        $this->tracker = $tracker;
     19                wp_cache_add_global_groups( $this->i18n_cache_group );
     20        }
     21
     22        /*
     23         * ***********************
     24         * Processing
     25         * ***********************
     26         */
     27
     28        function process( $slug, $branch = 'dev', $type = 'all' ) {
     29                if ( empty( $slug ) || empty( $this->tracker ) )
     30                        return false;
     31
     32                // DEBUG: in_array check is because we'll start the program with a finite list of plugins
     33                // TODO: remove when we launch for all plugins.
     34                if ( ! in_array( $slug, $this->translated_plugins ) )
     35                        return false;
     36
     37                if ( 'stable' !== $branch )
     38                        $branch = 'dev';
     39
     40                if ( 'code' !== $type && 'readme' !== $type )
     41                        $type = 'all';
     42
     43                $path_rel = "{$slug}/trunk/";
     44
     45                if ( 'stable' === $branch ) {
     46                        if ( false == ( $stable_tag = $this->tracker->get_stable_tag_dir_using( $path_rel ) ) ) {
     47                                // Can't get a stable tag, bail out
     48                                return false;
     49                        } else if ( 'trunk' == trim( $stable_tag['tag_dir'], '/' ) ) {
     50                                // If stable is trunk, then it's really same as dev, switch to that
     51                                $branch = 'dev';
     52                        } else {
     53                                // We're dealing with an actual stable tag, go for it
     54                                $path_rel = "{$slug}/{$stable_tag['tag_dir']}"; //
     55                        }
     56                }
     57
     58                if ( 'code' === $type || 'all' === $type )
     59                        $this->process_code( $path_rel, $branch );
     60
     61                if ( 'readme' === $type || 'all' === $type )
     62                        $this->process_readme( $path_rel, $branch );
     63
     64                echo "Processed {$type} for {$path_rel}\n";
     65                return true;
     66        }
     67
     68        function process_code( $path_rel, $branch = 'dev' ) {
     69                if ( empty( $this->tracker ) )
     70                        return false;
     71
     72                $slug = preg_replace( '|^/?([^/]+)/?.+?$|', '\1', $path_rel );
     73
     74                if ( empty( $slug ) || !preg_match( '/^[a-z0-9-]+$/i', $slug ) )
     75                        return false;
     76
     77                // DEBUG: in_array check is because we'll start the program with a finite list of plugins
     78                // TODO: remove when we launch for all plugins.
     79                if ( !in_array( $slug, $this->translated_plugins ) )
     80                        return false;
     81
     82                $export_path = $this->tracker->create_export( $path_rel );
     83
     84                if ( empty( $export_path ) || !is_dir( $export_path ) )
     85                        return false;
     86
     87                $old_cwd = getcwd();
     88                chdir( $export_path );
     89
     90                // Check for a plugin text domain declaration and loading, grep recursively, not necessarily in [slug].php
     91                if ( ! shell_exec( 'grep -r --include "*.php" "Text Domain: ' . escapeshellarg( $slug ) . '" .' ) && ! shell_exec( 'grep -r --include "*.php" "\bload_plugin_textdomain\b" .' ) )
     92                        return false;
     93
     94                if ( !class_exists( 'PotExtMeta' ) )
     95                        require_once( __DIR__ . '/i18n-tools/pot-ext-meta.php' );
     96
     97                // Create pot file from code
     98                $pot_file = "./tmp-{$slug}.pot"; // Using tmp- prefix in case a plugin has $slug.pot committed
     99                $makepot  = new MakePOT;
     100
     101                if ( ! $makepot->wp_plugin( '.', $pot_file, $slug ) || ! file_exists( $pot_file ) )
     102                        return false;
     103
     104                // DEBUG
     105                // system( "cat {$pot_file}" );
     106
     107                $this->import_to_glotpress_project( $slug, $branch, $pot_file );
     108
     109                chdir( $old_cwd );
     110                return true;
     111        }
     112
     113        function process_readme( $path_rel, $branch = 'dev' ) {
     114                if ( empty( $this->tracker ) )
     115                        return false;
     116
     117                $slug = preg_replace( '|^/?([^/]+)/?.+?$|', '\1', $path_rel );
     118
     119                if ( empty( $slug ) || !preg_match( '/^[a-z0-9-]+$/i', $slug ) )
     120                        return false;
     121
     122                // DEBUG: in_array as separate check because we'll start the program with a finite list of plugins
     123                // TODO: remove when we launch for all plugins.
     124                if ( !in_array( $slug, $this->translated_plugins ) )
     125                        return false;
     126
     127                $export_path = $this->tracker->create_export( $path_rel );
     128
     129                if ( empty( $export_path ) || !is_dir( $export_path ) )
     130                        return false;
     131
     132                $old_cwd = getcwd();
     133                chdir( $export_path );
     134
     135                $readme = $this->tracker->parse_readme_in( $path_rel );
     136
     137                $str_priorities = array();
     138
     139                if ( !class_exists( 'PO' ) )
     140                        require_once( __DIR__ . '/i18n-tools/pomo/po.php' );
     141
     142                $pot = new PO;
     143
     144                // No need for license, being in the directory implies GPLv2 or later. Add here otherwise.
     145                foreach ( array( 'name', 'short_description' ) as $key ) {
     146                        $readme[ $key ] = trim( $readme[ $key ] ) ;
     147                }
     148
     149                // If empty or "sketchy", get the plugin name form the PHP file's headers
     150                if ( empty( $readme['name'] ) || 'Plugin Name' == trim( $readme['name'] ) ) {
     151                        // -o in grep will make sure we don't get comments opening delimiters (//, /*) or spaces as part of string
     152                        $name_from_php  = trim( shell_exec( 'grep -o "\bPlugin Name:.*" ' . escapeshellarg( $slug ) . '.php' ) );
     153                        // Remove the header label
     154                        $name_from_php  = str_replace( 'Plugin Name:', '', $name_from_php );
     155                        // Do clean out potential comment closing delimiter (*/) out of string
     156                        $name_from_php  = preg_replace( '|^(.+)[\s]+?\*/$|', '\1', $name_from_php );
     157                        // Use trimmed results as plugin name
     158                        $readme['name'] = trim( $name_from_php );
     159                }
     160
     161                if ( !empty( $readme['name'] ) ) {
     162                        $pot->add_entry( new Translation_Entry ( array(
     163                                'singular'           => $readme['name'],
     164                                'extracted_comments' => 'Name.',
     165                        ) ) );
     166
     167                        $str_priorities[ $readme['name'] ] = 1;
     168                }
     169
     170                if ( !empty( $readme['short_description'] ) ) {
     171                        $pot->add_entry( new Translation_Entry ( array(
     172                                'singular'           => $readme['short_description'],
     173                                'extracted_comments' => 'Short description.',
     174                        ) ) );
     175
     176                        $str_priorities[ $readme['short_description'] ] = 1;
     177                }
     178
     179                if ( !empty( $readme['screenshots'] ) ) {
     180                        foreach ( $readme['screenshots'] as $sshot_key => $sshot_desc ) {
     181                                $sshot_desc = trim( $sshot_desc );
     182                                $pot->add_entry( new Translation_Entry ( array(
     183                                        'singular'           => $sshot_desc,
     184                                        'extracted_comments' => 'Screenshot description.',
     185                                ) ) );
     186                        }
     187
     188                }
     189
     190                if ( empty( $readme['sections'] ) )
     191                        $readme['sections'] = array();
     192
     193                // Adding remaining content as a section so it's processed by the same loop below
     194                if ( !empty( $readme['remaining_content'] ) )
     195                        $readme['sections']['remaining_content'] = $readme['remaining_content'];
     196
     197                $strings = array();
     198
     199                foreach ( $readme['sections'] as $section_key => $section_text ) {
     200                        if ( 'screenshots' == $section_key )
     201                                continue;
     202
     203                        /*
     204                         * Scanned tags based on block elements found in Automattic_Readme::filter_text() $allowed.
     205                         * Scanning H3/4, li, p and blockquote. Other tags are ignored  in strings (a, strong, cite, etc).
     206                         * Processing notes:
     207                         * * Don't normalize/modify original text, will be used as a search pattern in original doc in some use-cases.
     208                         * * Using regexes over XML parsing for performance reasons, could move to the latter for more accuracy.
     209                         */
     210
     211                        if ( 'changelog' !== $section_key ) { // No need to scan non-translatable version headers in changelog
     212                                if ( preg_match_all( '|<h[3-4]+[^>]*>(.+)</h[3-4]+>|', $section_text, $matches ) ) {
     213                                        if ( !empty( $matches[1] ) ) {
     214                                                foreach ( $matches[1] as $text ) {
     215                                                        $strings = $this->handle_translator_comment( $strings, $text, "{$section_key} header" );
     216                                                }
     217                                        }
     218                                }
     219                        }
     220
     221                        if ( preg_match_all( '|<li>(.+)</li>|', $section_text, $matches ) ) {
     222                                if ( !empty( $matches[1] ) ) {
     223                                        foreach ( $matches[1] as $text ) {
     224                                                $strings = $this->handle_translator_comment( $strings, $text, "{$section_key} list item" );
     225                                                if ( 'changelog' === $section_key )
     226                                                        $str_priorities[ $text ] = -1;
     227                                        }
     228                                }
     229                        }
     230
     231                        if ( preg_match_all( '|<p>(.+)</p>|', $section_text, $matches ) ) {
     232                                if ( !empty( $matches[1] ) ) {
     233                                        foreach ( $matches[1] as $text ) {
     234                                                $strings = $this->handle_translator_comment( $strings, $text, "{$section_key} paragraph" );
     235                                                if ( 'changelog' === $section_key )
     236                                                        $str_priorities[ $text ] = -1;
     237                                        }
     238                                }
     239                        }
     240
     241                        if ( preg_match_all( '|<blockquote>(.+)</blockquote>|', $section_text, $matches ) ) {
     242                                if ( !empty( $matches[1] ) ) {
     243                                        foreach ( $matches[1] as $text ) {
     244                                                $strings = $this->handle_translator_comment( $strings, $text, "{$section_key} block quote" );
     245                                                if ( 'changelog' === $section_key )
     246                                                        $str_priorities[ $text ] = -1;
     247                                        }
     248                                }
     249                        }
     250                }
     251
     252                foreach ( $strings as $text => $comments ) {
     253                        $pot->add_entry( new Translation_Entry ( array(
     254                                'singular'           => $text,
     255                                'extracted_comments' => 'Found in ' . implode( $comments, ", " ) . '.',
     256                        ) ) );
     257                }
     258
     259                $pot_file = "./tmp-{$slug}-readme.pot";
     260                $pot->export_to_file( $pot_file );
     261
     262                // DEBUG
     263                // system( "cat {$pot_file}" );
     264
     265                // import to GlotPress, dev or stable
     266                $this->import_to_glotpress_project( $slug, "{$branch}-readme", $pot_file, $str_priorities );
     267
     268                chdir( $old_cwd );
     269                return true;
     270        }
     271
     272        function handle_translator_comment( $array, $key, $val ) {
     273                $val = trim( preg_replace( '/[^a-z0-9]/i', ' ', $val ) ); // cleanup key names for display
     274                if ( empty( $array[ $key ] ) ) {
     275                        $array[ $key ] = array( $val );
     276                } else if ( !in_array( $val, $array[ $key ] ) ) {
     277                        $array[ $key ][] = $val;
     278                }
     279                return $array;
     280        }
     281
     282        function import_to_glotpress_project( $project, $branch, $file, $str_priorities = array() ) {
     283                // Note: this will only work if the GlotPress project/sub-projects exist. To be improved, or must insure they do.
     284                $cmd = 'php ' . __DIR__ . '/../../../translate/glotpress/scripts/import-originals.php -o po -p ' . escapeshellarg( "wp-plugins/{$project }/{$branch}" ) . ' -f ' . escapeshellarg( $file );
     285                // DEBUG
     286                // var_dump( $cmd );
     287                system( $cmd );
     288                if ( empty( $str_priorities ) )
     289                        return;
     290                $branch_id = $this->get_gp_branch_id( $project, $branch );
     291                // Set the string priorities in GP once the originals have been imported
     292                if ( empty( $branch_id ) )
     293                        return;
     294                foreach ( (array) $str_priorities as $str => $prio ) {
     295                        if ( 1 !== $prio && -1 !== $prio )
     296                                $prio = 0;
     297                        $res = $this->db->query( $this->db->prepare(
     298                                'UPDATE translate_originals SET priority = %d WHERE project_id = %d AND status = %s AND singular = %s',
     299                                $prio, $branch_id, '+active', $str
     300                        ) );
     301                }
     302        }
     303
     304        /*
     305         * ***********************
     306         * Rendering
     307         * ***********************
     308         */
     309
     310        function translate( $key, $content, $args = array() ) {
     311                if ( empty( $key ) || empty( $content ) )
     312                        return $content;
     313
     314                if ( !empty( $args['topic_id'] ) && is_numeric( $args['topic_id'] ) )
     315                        $topic = get_topic( $args['topic_id'] );
     316                else
     317                        global $topic;
     318
     319                if ( empty( $topic ) )
     320                        return $content;
     321
     322                /*
     323                 * DEBUG: Getting $language from request or host name, should use something like $GLOBALS['locale']
     324                 * and/or $GLOBALS['i18n'] once/if set properly when on localized site and get it from that.
     325                 *
     326                 * TODO: find the proper way
     327                 *
     328                 * $GLOBALS['locale'] is currently en_US on localized sites (eg: fr.wordpress.org)
     329                 * $GLOBALS['i18n'] is currently false on localized sites (eg: fr.wordpress.org)
     330                 */
     331                $language     = '';
     332                $server_name  = strtolower( $_SERVER['SERVER_NAME'] );
     333                if ( 'api.wordpress.org' == $server_name && 2 == strlen( $_REQUEST['language'] ) ) {
     334                        $language = $_REQUEST['language'];
     335                } else if ( preg_match( '/^[a-z]{2}\.wordpress\.org$/', $server_name ) ) {
     336                        $language = substr( $server_name, 0, 2 );
     337                }
     338
     339                if ( empty( $language ) || 2 !== strlen( $language ) ) {
     340                        return $content;
     341                }
     342
     343                $slug = $topic->plugin_san;
     344
     345                // DEBUG: in_array check is because we'll start the program with a finite list of plugins
     346                // TODO: remove when we launch for all plugins.
     347                if ( empty( $slug ) || ! in_array( $slug, $this->translated_plugins ) ) {
     348                        return $content;
     349                }
     350
     351                $branch = ( empty( $topic->stable_tag ) || 'trunk' === $topic->stable_tag ) ? 'dev' : 'stable';
     352
     353                if ( empty( $args['code_i18n'] ) || true !== $args['code_i18n'] ) {
     354                        $branch .= '-readme';
     355                }
     356
     357                // Instantiate this before modifying $content
     358                $cache_suffix = "{$language}:{$key}";
     359
     360                // Try the cache
     361                if ( false !== ( $cache = $this->cache_get( $slug, $branch, $cache_suffix ) ) ) {
     362                        // DEBUG
     363                        // var_dump( array( $slug, $branch, $cache_suffix, $cache ) );
     364                        return $cache;
     365                }
     366
     367                $originals = $this->get_gp_originals( $slug, $branch, $key, $content );
     368
     369                if ( empty( $originals ) )
     370                        return $content;
     371
     372                $translation_set_id = $this->get_gp_translation_set_id( $slug, $branch, $language );
     373
     374                if ( empty( $translation_set_id ) )
     375                        return $content;
     376
     377                foreach ( $originals as $original ) {
     378                        if ( empty( $original->id ) )
     379                                continue;
     380
     381                        $translation = $this->db->get_var( $this->db->prepare(
     382                                'SELECT translation_0 FROM translate_translations WHERE original_id = %d AND translation_set_id = %d AND status = %s',
     383                                $original->id, $translation_set_id, 'current'
     384                        ) );
     385
     386                        if ( empty( $translation ) )
     387                                continue;
     388
     389                        $content = $this->translate_gp_original( $original->singular, $translation, $content );
     390                }
     391
     392                $this->cache_set( $slug, $branch, $content, $cache_suffix );
     393
     394                return $content;
     395        }
     396
     397        function cache_key( $slug, $branch, $suffix = null ) {
     398                // Main keys
     399                // plugin:press-this:stable-readme:originals
     400                // plugin:press-this:stable-readme:original:md5($str)
     401                // plugin:press-this:stable-readme:fr:md5($str)
     402                $key = "plugin:{$slug}:{$branch}";
     403                if ( !empty( $suffix ) )
     404                        $key .= ":{$suffix}";
     405                return $key;
     406        }
     407
     408        function cache_get( $slug, $branch, $suffix = null ) {
     409                $key = $this->cache_key( $slug, $branch, $suffix );
     410                // DEBUG
     411                // wp_cache_delete( $key, $this->i18n_cache_group );
     412                return wp_cache_get( $key, $this->i18n_cache_group );
     413        }
     414
     415        function cache_set( $slug, $branch, $content, $suffix = null ) {
     416                $key = $this->cache_key( $slug, $branch, $suffix );
     417                return wp_cache_set( $key, $content, $this->i18n_cache_group );
     418        }
     419
     420        function get_gp_branch_id( $slug, $branch ) {
     421                $branch_id = $this->db->get_var( $this->db->prepare(
     422                        'SELECT id FROM translate_projects WHERE path = %s',
     423                        "wp-plugins/{$slug}/{$branch}"
     424                ) );
     425
     426                return ( empty( $branch_id ) ) ? 0 : $branch_id;
     427        }
     428
     429        function get_gp_originals( $slug, $branch, $key, $str ) {
     430                // Try to get a single original with the whole content first (title, etc), if passed, or get them all otherwise.
     431                if ( !empty( $key ) && !empty( $str ) ) {
     432                        $originals = $this->search_gp_original( $slug, $branch, $key, $str );
     433                        if ( !empty( $originals ) )
     434                                return array( $originals );
     435                        // Do not cache this as originals, search_gp_original() does its own caching
     436                }
     437
     438                $cache_suffix = 'originals';
     439
     440                if ( false !== ( $originals = $this->cache_get( $slug, $branch, $cache_suffix ) ) )
     441                        return $originals;
     442
     443                $branch_id = $this->get_gp_branch_id( $slug, $branch );
     444
     445                if ( empty( $branch_id ) )
     446                        return array();
     447
     448                $originals = $this->db->get_results( $this->db->prepare(
     449                        'SELECT id, singular, comment FROM translate_originals WHERE project_id = %d AND status = %s',
     450                        $branch_id, '+active'
     451                ) );
     452
     453                if ( empty( $originals ) )
     454                        $originals = array(); // still cache if empty, but as array, never false
     455
     456                $this->cache_set( $slug, $branch, $originals, $cache_suffix );
     457
     458                return $originals;
     459        }
     460
     461        function get_gp_translation_set_id( $slug, $branch, $locale ) {
     462                $branch_id = $this->get_gp_branch_id( $slug, $branch );
     463
     464                if ( empty( $branch_id ) )
     465                        return 0;
     466
     467                $translation_set_id = $this->db->get_var( $this->db->prepare(
     468                        'SELECT id FROM translate_translation_sets WHERE project_id = %d AND locale = %s',
     469                        $branch_id, $locale ) );
     470
     471                return ( empty( $translation_set_id ) ) ? 0 : $translation_set_id;
     472        }
     473
     474        function search_gp_original( $slug, $branch, $key, $str ) {
     475                $cache_suffix = "original:{$key}";
     476
     477                if ( false !== ( $original = $this->cache_get( $slug, $branch, $cache_suffix ) ) )
     478                        return $original;
     479
     480                $branch_id = $this->get_gp_branch_id( $slug, $branch );
     481
     482                if ( empty( $branch_id ) )
     483                        return false;
     484
     485                $original = $this->db->get_row( $this->db->prepare(
     486                        'SELECT id, singular, comment FROM translate_originals WHERE project_id = %d AND status = %s AND singular = %s',
     487                        $branch_id, '+active', $str
     488                ) );
     489
     490                if ( empty( $original ) )
     491                        $original = null;
     492
     493                $this->cache_set( $slug, $branch, $original, $cache_suffix );
     494
     495                return $original;
     496        }
     497
     498        function translate_gp_original( $original, $translation, $content) {
     499                $content = str_replace( $original, $translation, $content );
     500                return $content;
     501        }
     502}
     503 No newline at end of file
  • extend/plugins-plugins/svn-track/class.dotorg-plugins-tracker.php

    Property changes on: extend/plugins-plugins/svn-track/class.dotorg-plugins-i18n.php
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    9393                                bb_set_current_user( $user->ID );
    9494                        }
    9595
    96                         if ( 1 < $argc && 'update' == $argv[1] ) {
     96                        if ( 1 < $argc && ( 'update' == $argv[1] || 'i18n' == $argv[1] ) ) {
    9797                                if ( !isset( $_SERVER['REMOTE_ADDR'] ) )
    9898                                        $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
    9999
    100100                                if ( 2 == $argc ) // php bb-load.php update
    101101                                        return $this->process_changes();
    102102
     103                                if ( 'i18n' == $argv[1] ) {
     104                                        // php bb-load.php i18n slug [dev|stable, default: dev] [code|readme|all, default: all]
     105                                        return $this->process_i18n( $argv[2], ( 'stable' === $argv[3] ) ? $argv[3] : 'dev', $argv[4] );
     106                                }
     107
    103108                                switch ( $argv[2] ) {
    104109                                case 'all' :
    105110                                        return $this->process_all();
     
    277282                        $content = preg_replace_callback( "#<img class='screenshot' src='(screenshot-[^']+)' alt='[^']+' />#", array( &$this, '_screenshot_img_tag' ), $content );
    278283                }
    279284
    280                 return $content;
     285                return $this->translate( $show, $content );
    281286        }
    282287
     288        function i18n_obj( $db, $tracker = null ) {
     289                if ( !class_exists( 'Dotorg_Plugin_I18n' ) )
     290                        require_once( __DIR__ . '/class.dotorg-plugins-i18n.php' );
     291                return new Dotorg_Plugin_I18n( $db, $tracker );
     292        }
     293
     294        function translate( $key, $content, $args = array() ) {
     295                return $this->i18n_obj( $this->db )->translate( $key, $content, $args );
     296        }
     297
    283298        function _screenshot_shortcode( $matches ) {
    284299                return $this->_screenshot_image( $matches[1], $matches[2] );
    285300        }
     
    15621577                        else
    15631578                                bb_delete_topicmeta( $topic_id, $key );
    15641579                }
     1580
     1581                // Reprocess the readme for translation.
     1582                // DEBUG: placeholder, untested and not ready as of yet.
     1583                // $this->process_i18n( $slug, 'stable', 'readme' ); // Figures on its own if stable means dev (trunk).
    15651584        }
    15661585
    15671586        function load_topic_page( $topic_id ) {
     
    17311750                        return 'http://wordpress.org/support/view/plugin-reviews/' . $topic->topic_slug;
    17321751                if ( bb_get_option( 'mod_rewrite' ) ) {
    17331752                        if ( 'description' == $section )
    1734                                 return rtrim( get_topic_link( $topic_id ), '/' ) . '/';
    1735                         return rtrim( get_topic_link( $topic_id ), '/' ) . "/$section/";
     1753                                return $this->localize_section_url( rtrim( get_topic_link( $topic_id ), '/' ) . '/' );
     1754                        return  $this->localize_section_url( rtrim( get_topic_link( $topic_id ), '/' ) . "/$section/" );
    17361755                } else {
    17371756                        if ( 'description' == $section )
    1738                                 return remove_query_arg( 'show', get_topic_link( $topic_id ) );
    1739                         return add_query_arg( 'show', $section, get_topic_link( $topic_id ) );
     1757                                return  $this->localize_section_url( remove_query_arg( 'show', get_topic_link( $topic_id ) ) );
     1758                        return  $this->localize_section_url( add_query_arg( 'show', $section, get_topic_link( $topic_id ) ) );
    17401759                }
    17411760        }
    17421761
     1762        function localize_section_url( $url ) {
     1763                $server_name = strtolower( $_SERVER[ 'SERVER_NAME' ] );
     1764                if ( 'wordpress.org' != $server_name && preg_match( '/\.wordpress\.org$/', $server_name ) )
     1765                        return str_replace( '://wordpress.org/', "://{$server_name}/", $url );
     1766                return $url;
     1767        }
     1768
    17431769        function section_title( $section ) {
    17441770                switch ( $section ) {
    17451771                        case 'description':
     
    19962022                return false;
    19972023        }
    19982024
     2025        function process_i18n( $slug, $branch = 'dev', $type = 'all' ) {
     2026                return $this->i18n_obj( $this->db, $this )->process( $slug, $branch, $type );
     2027        }
     2028
    19992029        function get_all_roots( $via = 'local' ) {
    20002030                global $bbdb;
    20012031                $root_rels = false;
  • bb-theme/plugins/search.php

     
    3232
    3333        echo wporg_get_plugin_icon( $topic );
    3434?>
    35         <h3><a href="<?php topic_link(); ?>"><?php topic_title(); ?></a></h3>
     35        <h3><a href="<?php topic_link(); ?>"><?php echo $svn_tracker->translate( 'title', get_topic_title() ); ?></a></h3>
    3636        <?php echo $svn_tracker->_post_section( 'short_description', $bb_post->post_text, 0); ?>
    3737        <ul class="plugin-meta">
    3838                <li><?php $svn_tracker->template( 'version', 'before=<span class="info-marker">'. __( 'Version:', 'wporg' ) .'</span> '); ?></li>
  • bb-theme/plugins/topic-404.php

     
    7070
    7171<div class="plugin-block">
    7272        <?php $topic = get_topic( $bb_post->topic_id ); ?>
    73         <h3><a href="<?php topic_link(); ?>"><?php topic_title(); ?></a></h3>
     73        <h3><a href="<?php topic_link(); ?>"><?php echo $svn_tracker->translate( 'title', get_topic_title() ); ?></a></h3>
    7474        <?php post_text(); ?>
    7575        <ul class="plugin-meta">
    7676                <li><?php $svn_tracker->template( 'version', 'before=<span class="info-marker">Version</span> '); ?></li>
  • bb-theme/plugins/topic.php

     
    4444</style>
    4545<?php endif; ?>
    4646
    47         <h2 itemprop="name"><?php echo apply_filters( 'topic_title', $topic->topic_title ); ?></h2>
     47        <h2 itemprop="name"><?php echo apply_filters( 'topic_title', $svn_tracker->translate( 'title', $topic->topic_title ) ); ?></h2>
    4848</div>
    4949
    5050<div id="plugin-description">