Making WordPress.org

Ticket #1089: 1089.diff

File 1089.diff, 51.9 KB (added by akirk, 9 years ago)
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/LICENSE

     
     1GNU GENERAL PUBLIC LICENSE
     2                       Version 2, June 1991
     3
     4 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
     5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     6 Everyone is permitted to copy and distribute verbatim copies
     7 of this license document, but changing it is not allowed.
     8
     9                            Preamble
     10
     11  The licenses for most software are designed to take away your
     12freedom to share and change it.  By contrast, the GNU General Public
     13License is intended to guarantee your freedom to share and change free
     14software--to make sure the software is free for all its users.  This
     15General Public License applies to most of the Free Software
     16Foundation's software and to any other program whose authors commit to
     17using it.  (Some other Free Software Foundation software is covered by
     18the GNU Lesser General Public License instead.)  You can apply it to
     19your programs, too.
     20
     21  When we speak of free software, we are referring to freedom, not
     22price.  Our General Public Licenses are designed to make sure that you
     23have the freedom to distribute copies of free software (and charge for
     24this service if you wish), that you receive source code or can get it
     25if you want it, that you can change the software or use pieces of it
     26in new free programs; and that you know you can do these things.
     27
     28  To protect your rights, we need to make restrictions that forbid
     29anyone to deny you these rights or to ask you to surrender the rights.
     30These restrictions translate to certain responsibilities for you if you
     31distribute copies of the software, or if you modify it.
     32
     33  For example, if you distribute copies of such a program, whether
     34gratis or for a fee, you must give the recipients all the rights that
     35you have.  You must make sure that they, too, receive or can get the
     36source code.  And you must show them these terms so they know their
     37rights.
     38
     39  We protect your rights with two steps: (1) copyright the software, and
     40(2) offer you this license which gives you legal permission to copy,
     41distribute and/or modify the software.
     42
     43  Also, for each author's protection and ours, we want to make certain
     44that everyone understands that there is no warranty for this free
     45software.  If the software is modified by someone else and passed on, we
     46want its recipients to know that what they have is not the original, so
     47that any problems introduced by others will not reflect on the original
     48authors' reputations.
     49
     50  Finally, any free program is threatened constantly by software
     51patents.  We wish to avoid the danger that redistributors of a free
     52program will individually obtain patent licenses, in effect making the
     53program proprietary.  To prevent this, we have made it clear that any
     54patent must be licensed for everyone's free use or not licensed at all.
     55
     56  The precise terms and conditions for copying, distribution and
     57modification follow.
     58
     59                    GNU GENERAL PUBLIC LICENSE
     60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
     61
     62  0. This License applies to any program or other work which contains
     63a notice placed by the copyright holder saying it may be distributed
     64under the terms of this General Public License.  The "Program", below,
     65refers to any such program or work, and a "work based on the Program"
     66means either the Program or any derivative work under copyright law:
     67that is to say, a work containing the Program or a portion of it,
     68either verbatim or with modifications and/or translated into another
     69language.  (Hereinafter, translation is included without limitation in
     70the term "modification".)  Each licensee is addressed as "you".
     71
     72Activities other than copying, distribution and modification are not
     73covered by this License; they are outside its scope.  The act of
     74running the Program is not restricted, and the output from the Program
     75is covered only if its contents constitute a work based on the
     76Program (independent of having been made by running the Program).
     77Whether that is true depends on what the Program does.
     78
     79  1. You may copy and distribute verbatim copies of the Program's
     80source code as you receive it, in any medium, provided that you
     81conspicuously and appropriately publish on each copy an appropriate
     82copyright notice and disclaimer of warranty; keep intact all the
     83notices that refer to this License and to the absence of any warranty;
     84and give any other recipients of the Program a copy of this License
     85along with the Program.
     86
     87You may charge a fee for the physical act of transferring a copy, and
     88you may at your option offer warranty protection in exchange for a fee.
     89
     90  2. You may modify your copy or copies of the Program or any portion
     91of it, thus forming a work based on the Program, and copy and
     92distribute such modifications or work under the terms of Section 1
     93above, provided that you also meet all of these conditions:
     94
     95    a) You must cause the modified files to carry prominent notices
     96    stating that you changed the files and the date of any change.
     97
     98    b) You must cause any work that you distribute or publish, that in
     99    whole or in part contains or is derived from the Program or any
     100    part thereof, to be licensed as a whole at no charge to all third
     101    parties under the terms of this License.
     102
     103    c) If the modified program normally reads commands interactively
     104    when run, you must cause it, when started running for such
     105    interactive use in the most ordinary way, to print or display an
     106    announcement including an appropriate copyright notice and a
     107    notice that there is no warranty (or else, saying that you provide
     108    a warranty) and that users may redistribute the program under
     109    these conditions, and telling the user how to view a copy of this
     110    License.  (Exception: if the Program itself is interactive but
     111    does not normally print such an announcement, your work based on
     112    the Program is not required to print an announcement.)
     113
     114These requirements apply to the modified work as a whole.  If
     115identifiable sections of that work are not derived from the Program,
     116and can be reasonably considered independent and separate works in
     117themselves, then this License, and its terms, do not apply to those
     118sections when you distribute them as separate works.  But when you
     119distribute the same sections as part of a whole which is a work based
     120on the Program, the distribution of the whole must be on the terms of
     121this License, whose permissions for other licensees extend to the
     122entire whole, and thus to each and every part regardless of who wrote it.
     123
     124Thus, it is not the intent of this section to claim rights or contest
     125your rights to work written entirely by you; rather, the intent is to
     126exercise the right to control the distribution of derivative or
     127collective works based on the Program.
     128
     129In addition, mere aggregation of another work not based on the Program
     130with the Program (or with a work based on the Program) on a volume of
     131a storage or distribution medium does not bring the other work under
     132the scope of this License.
     133
     134  3. You may copy and distribute the Program (or a work based on it,
     135under Section 2) in object code or executable form under the terms of
     136Sections 1 and 2 above provided that you also do one of the following:
     137
     138    a) Accompany it with the complete corresponding machine-readable
     139    source code, which must be distributed under the terms of Sections
     140    1 and 2 above on a medium customarily used for software interchange; or,
     141
     142    b) Accompany it with a written offer, valid for at least three
     143    years, to give any third party, for a charge no more than your
     144    cost of physically performing source distribution, a complete
     145    machine-readable copy of the corresponding source code, to be
     146    distributed under the terms of Sections 1 and 2 above on a medium
     147    customarily used for software interchange; or,
     148
     149    c) Accompany it with the information you received as to the offer
     150    to distribute corresponding source code.  (This alternative is
     151    allowed only for noncommercial distribution and only if you
     152    received the program in object code or executable form with such
     153    an offer, in accord with Subsection b above.)
     154
     155The source code for a work means the preferred form of the work for
     156making modifications to it.  For an executable work, complete source
     157code means all the source code for all modules it contains, plus any
     158associated interface definition files, plus the scripts used to
     159control compilation and installation of the executable.  However, as a
     160special exception, the source code distributed need not include
     161anything that is normally distributed (in either source or binary
     162form) with the major components (compiler, kernel, and so on) of the
     163operating system on which the executable runs, unless that component
     164itself accompanies the executable.
     165
     166If distribution of executable or object code is made by offering
     167access to copy from a designated place, then offering equivalent
     168access to copy the source code from the same place counts as
     169distribution of the source code, even though third parties are not
     170compelled to copy the source along with the object code.
     171
     172  4. You may not copy, modify, sublicense, or distribute the Program
     173except as expressly provided under this License.  Any attempt
     174otherwise to copy, modify, sublicense or distribute the Program is
     175void, and will automatically terminate your rights under this License.
     176However, parties who have received copies, or rights, from you under
     177this License will not have their licenses terminated so long as such
     178parties remain in full compliance.
     179
     180  5. You are not required to accept this License, since you have not
     181signed it.  However, nothing else grants you permission to modify or
     182distribute the Program or its derivative works.  These actions are
     183prohibited by law if you do not accept this License.  Therefore, by
     184modifying or distributing the Program (or any work based on the
     185Program), you indicate your acceptance of this License to do so, and
     186all its terms and conditions for copying, distributing or modifying
     187the Program or works based on it.
     188
     189  6. Each time you redistribute the Program (or any work based on the
     190Program), the recipient automatically receives a license from the
     191original licensor to copy, distribute or modify the Program subject to
     192these terms and conditions.  You may not impose any further
     193restrictions on the recipients' exercise of the rights granted herein.
     194You are not responsible for enforcing compliance by third parties to
     195this License.
     196
     197  7. If, as a consequence of a court judgment or allegation of patent
     198infringement or for any other reason (not limited to patent issues),
     199conditions are imposed on you (whether by court order, agreement or
     200otherwise) that contradict the conditions of this License, they do not
     201excuse you from the conditions of this License.  If you cannot
     202distribute so as to satisfy simultaneously your obligations under this
     203License and any other pertinent obligations, then as a consequence you
     204may not distribute the Program at all.  For example, if a patent
     205license would not permit royalty-free redistribution of the Program by
     206all those who receive copies directly or indirectly through you, then
     207the only way you could satisfy both it and this License would be to
     208refrain entirely from distribution of the Program.
     209
     210If any portion of this section is held invalid or unenforceable under
     211any particular circumstance, the balance of the section is intended to
     212apply and the section as a whole is intended to apply in other
     213circumstances.
     214
     215It is not the purpose of this section to induce you to infringe any
     216patents or other property right claims or to contest validity of any
     217such claims; this section has the sole purpose of protecting the
     218integrity of the free software distribution system, which is
     219implemented by public license practices.  Many people have made
     220generous contributions to the wide range of software distributed
     221through that system in reliance on consistent application of that
     222system; it is up to the author/donor to decide if he or she is willing
     223to distribute software through any other system and a licensee cannot
     224impose that choice.
     225
     226This section is intended to make thoroughly clear what is believed to
     227be a consequence of the rest of this License.
     228
     229  8. If the distribution and/or use of the Program is restricted in
     230certain countries either by patents or by copyrighted interfaces, the
     231original copyright holder who places the Program under this License
     232may add an explicit geographical distribution limitation excluding
     233those countries, so that distribution is permitted only in or among
     234countries not thus excluded.  In such case, this License incorporates
     235the limitation as if written in the body of this License.
     236
     237  9. The Free Software Foundation may publish revised and/or new versions
     238of the General Public License from time to time.  Such new versions will
     239be similar in spirit to the present version, but may differ in detail to
     240address new problems or concerns.
     241
     242Each version is given a distinguishing version number.  If the Program
     243specifies a version number of this License which applies to it and "any
     244later version", you have the option of following the terms and conditions
     245either of that version or of any later version published by the Free
     246Software Foundation.  If the Program does not specify a version number of
     247this License, you may choose any version ever published by the Free Software
     248Foundation.
     249
     250  10. If you wish to incorporate parts of the Program into other free
     251programs whose distribution conditions are different, write to the author
     252to ask for permission.  For software which is copyrighted by the Free
     253Software Foundation, write to the Free Software Foundation; we sometimes
     254make exceptions for this.  Our decision will be guided by the two goals
     255of preserving the free status of all derivatives of our free software and
     256of promoting the sharing and reuse of software generally.
     257
     258                            NO WARRANTY
     259
     260  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
     261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
     262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
     263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
     264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
     266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
     267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
     268REPAIR OR CORRECTION.
     269
     270  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
     271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
     272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
     273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
     274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
     275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
     276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
     277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
     278POSSIBILITY OF SUCH DAMAGES.
     279
     280                     END OF TERMS AND CONDITIONS
     281
     282            How to Apply These Terms to Your New Programs
     283
     284  If you develop a new program, and you want it to be of the greatest
     285possible use to the public, the best way to achieve this is to make it
     286free software which everyone can redistribute and change under these terms.
     287
     288  To do so, attach the following notices to the program.  It is safest
     289to attach them to the start of each source file to most effectively
     290convey the exclusion of warranty; and each file should have at least
     291the "copyright" line and a pointer to where the full notice is found.
     292
     293    {description}
     294    Copyright (C) {year}  {fullname}
     295
     296    This program is free software; you can redistribute it and/or modify
     297    it under the terms of the GNU General Public License as published by
     298    the Free Software Foundation; either version 2 of the License, or
     299    (at your option) any later version.
     300
     301    This program is distributed in the hope that it will be useful,
     302    but WITHOUT ANY WARRANTY; without even the implied warranty of
     303    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     304    GNU General Public License for more details.
     305
     306    You should have received a copy of the GNU General Public License along
     307    with this program; if not, write to the Free Software Foundation, Inc.,
     308    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     309
     310Also add information on how to contact you by electronic and paper mail.
     311
     312If the program is interactive, make it output a short notice like this
     313when it starts in an interactive mode:
     314
     315    Gnomovision version 69, Copyright (C) year name of author
     316    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     317    This is free software, and you are welcome to redistribute it
     318    under certain conditions; type `show c' for details.
     319
     320The hypothetical commands `show w' and `show c' should show the appropriate
     321parts of the General Public License.  Of course, the commands you use may
     322be called something other than `show w' and `show c'; they could even be
     323mouse-clicks or menu items--whatever suits your program.
     324
     325You should also get your employer (if you work as a programmer) or your
     326school, if any, to sign a "copyright disclaimer" for the program, if
     327necessary.  Here is a sample; alter the names:
     328
     329  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
     330  `Gnomovision' (which makes passes at compilers) written by James Hacker.
     331
     332  {signature of Ty Coon}, 1 April 1989
     333  Ty Coon, President of Vice
     334
     335This General Public License does not permit incorporating your program into
     336proprietary programs.  If your program is a subroutine library, you may
     337consider it more useful to permit linking proprietary applications with the
     338library.  If this is what you want to do, use the GNU Lesser General
     339Public License instead of this License.
     340 No newline at end of file
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/README.md

     
     1gp-import-export
     2===========
     3
     4## Description
     5
     6Bulk Import/Export plugin for GlotPress.
     7
     8See https://github.com/Automattic/gp-import-export
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/gp-import-export.php

     
     1<?php
     2
     3/* GP_Import_Export
     4 * This plugin adds "Bulk Import" and "Bulk Export" project actions
     5 *  - Import a zip archive with multiple PO files to different sets
     6 *  - Export a zip archive of translations based on filters.
     7 */
     8
     9require_once( dirname(__FILE__) .'/includes/router.php' );
     10
     11class GP_Import_Export extends GP_Plugin {
     12
     13        public $id = 'gp-import-export';
     14
     15        public function __construct() {
     16                parent::__construct();
     17                $this->add_routes();
     18                $this->add_filter( 'gp_project_actions', array( 'args' => 2 ) );
     19        }
     20
     21        function add_routes() {
     22                $path = '(.+?)';
     23
     24                GP::$router->add( "/importer/$path", array( 'GP_Route_Import_Export', 'importer_get' ), 'get' );
     25                GP::$router->add( "/importer/$path", array( 'GP_Route_Import_Export', 'importer_post' ), 'post' );
     26
     27                GP::$router->add( "/exporter/$path/-do", array( 'GP_Route_Import_Export', 'exporter_do_get' ), 'get' );
     28                GP::$router->add( "/exporter/$path", array( 'GP_Route_Import_Export', 'exporter_get' ), 'get' );
     29        }
     30
     31        function gp_project_actions( $actions, $project ) {
     32
     33                if ( GP::$user->current()->can( 'bulk-import', 'project', $project->id ) ) {
     34                        $actions[] = gp_link_get( gp_url( '/importer/' . $project->path ), __( 'Bulk Import' ) );
     35                }
     36
     37                if ( GP::$user->current()->can( 'bulk-export', 'project', $project->id ) ) {
     38                        $actions[] = gp_link_get( gp_url( '/exporter/' . $project->path ), __( 'Bulk Export' ) );
     39                }
     40
     41                return $actions;
     42        }
     43
     44        public static function rrmdir( $dir ) {
     45                if ( trim( str_replace( array( '/', '.' ), '', $dir) ) == '' ) {
     46                        // prevent empty argument, thus deleting more than wanted
     47                        return false;
     48                }
     49
     50                foreach ( glob( str_replace( '*', '', $dir ) . '/{,.}*', GLOB_BRACE ) as $file ) { // Also look for hidden files
     51
     52                        if (  $file == $dir . '/.' || $file == $dir . '/..' ) { // but ignore dot directories
     53                                continue;
     54                        }
     55
     56                        if ( is_dir( $file ) ) {
     57                                self::rrmdir( $file );
     58                        } else {
     59                                unlink( $file );
     60                        }
     61                }
     62
     63                rmdir( $dir );
     64        }
     65}
     66
     67GP::$plugins->import_export = new GP_Import_Export;
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/includes/router.php

     
     1<?php
     2
     3class GP_Route_Import_export extends GP_Route_Main {
     4
     5        function __construct() {
     6                $this->template_path = dirname( dirname( __FILE__ ) ) . '/templates/';
     7        }
     8
     9        function exporter_get( $project_path ) {
     10                $project = GP::$project->by_path( $project_path );
     11
     12                if ( ! $project ) {
     13                        $this->die_with_404();
     14                }
     15
     16                if ( $this->cannot_and_redirect( 'bulk-export', 'project', $project->id ) ) {
     17                        return;
     18                }
     19
     20                $can_write = $this->can( 'write', 'project', $project->id );
     21
     22                if ( isset( GP::$plugins->views ) ) {
     23                        GP::$plugins->views->set_project_id( $project->id );
     24                        if ( $views = GP::$plugins->views->views ) {
     25                                $views_for_select = array( '' => __( '&mdash; Select &mdash;' ) );
     26                                foreach ( $views as $id => $view ) {
     27                                        $views_for_select[ $id ] = $view->name;
     28                                }
     29                                unset( $views );
     30                        }
     31                }
     32
     33                $translation_sets = GP::$translation_set->by_project_id( $project->id );
     34
     35                $values = array_map( function( $set ) { return $set->id; }, $translation_sets );
     36                $labels = array_map( function( $set ) { return $set->name_with_locale(); }, $translation_sets );
     37                $sets_for_select = apply_filters( 'exporter_translations_sets_for_select', array_combine( $values, $labels ), $project->id );
     38                $sets_for_select =  array( '' => __('&mdash; All &mdash;') ) +  $sets_for_select;
     39
     40                $this->tmpl( 'exporter', get_defined_vars() );
     41        }
     42
     43        function exporter_do_get( $project_path ) {
     44                @ini_set( 'memory_limit', '256M' );
     45
     46                $project = GP::$project->by_path( $project_path );
     47
     48                if ( ! $project ) {
     49                        $this->die_with_404();
     50                }
     51
     52                if ( $this->cannot_and_redirect( 'bulk-export', 'project', $project->id ) ) {
     53                        return;
     54                }
     55
     56                $format = gp_array_get( GP::$formats, gp_get( 'format', 'po' ), null );
     57
     58                if ( ! $format ) {
     59                        $this->die_with_404();
     60                }
     61
     62
     63                if ( isset( GP::$plugins->views ) ) {
     64                        GP::$plugins->views->set_project_id( $project->id );
     65                        $current_view = GP::$plugins->views->current_view;
     66                }
     67
     68                $project_for_slug = isset( $current_view ) ? $project_path . '/' . $current_view : $project_path;
     69                $filters = gp_get('filters');
     70                if ( isset( $filters['status'] ) && $filters['status'] != 'current_or_waiting_or_fuzzy_or_untranslated' ) {
     71                        $project_for_slug .= '/' . $filters['status'];
     72                }
     73                $slug = str_replace( '/', '-', $project_for_slug ) . '-' . date( 'Y-d-m-Hi' );
     74
     75                $working_path = '/tmp/' . $slug ;
     76
     77                // Make sure we have a fresh working directory.
     78                if ( file_exists( $working_path ) ) {
     79                        GP_Import_Export::rrmdir( $working_path );
     80                }
     81
     82                mkdir( $working_path );
     83
     84                $translations_sets = apply_filters( 'exporter_translations_sets_for_processing', gp_get( 'translation_sets' ), $project->id );
     85                if ( ! array_filter( $translations_sets ) || in_array( '0', $translations_sets ) ){
     86                        $_translation_sets = GP::$translation_set->by_project_id( $project->id );
     87                        $translations_sets = array_map( function( $set ) { return $set->id; }, $_translation_sets );
     88                };
     89
     90                $export_created = false;
     91                $empty = 0;
     92                foreach ( $translations_sets as $set_id ) {
     93                        $translation_set = GP::$translation_set->get( $set_id );
     94                        if ( ! $translation_set ) {
     95                                $this->errors[] = 'Translation set not found'; //TODO: do something with this
     96                                continue;
     97                        }
     98                        $locale = GP_Locales::by_slug( $translation_set->locale );
     99                        $filename = $working_path . '/' . sprintf(  '%s-%s.' . $format->extension, str_replace( '/', '-', $project_for_slug ), $locale->slug );
     100                        $entries = GP::$translation->for_export( $project, $translation_set, gp_get( 'filters' ) );
     101                        if ( empty( $entries ) ) {
     102                                $empty++;
     103                                continue;
     104                        }
     105                        file_put_contents(  $filename, $format->print_exported_file( $project, $locale, $translation_set, $entries ) );
     106                        $export_created = true;
     107                }
     108
     109                if ( ! $export_created ) {
     110                        if ( count( $translations_sets ) == count( $empty ) ) {
     111                                $this->notices[] = 'No matches for your selection';
     112                                $this->redirect();
     113                        } else {
     114                                $this->die_with_error( 'Error creating export files' );
     115                        }
     116                }
     117
     118                $tempdir = sys_get_temp_dir();
     119                $archive_file =  $tempdir . '/' . $slug . '.zip';
     120
     121                $zip = new ZipArchiveExtended;
     122                if ( $zip->open( $archive_file, ZipArchiveExtended::CREATE | ZipArchiveExtended::OVERWRITE ) ) {
     123                        $zip->addDir( $slug, $tempdir );
     124                        $zip->close();
     125                }
     126
     127                $this->headers_for_download( $archive_file );
     128                readfile( $archive_file );
     129
     130                GP_Import_Export::rrmdir( $working_path );
     131                unlink( $archive_file );
     132        }
     133
     134        function importer_get( $project_path ) {
     135                $project = GP::$project->by_path( $project_path );
     136
     137                if ( ! $project ) {
     138                        $this->die_with_404();
     139                }
     140
     141                if ( $this->cannot_and_redirect( 'bulk-import', 'project', $project->id ) ) {
     142                        return;
     143                }
     144
     145                $this->tmpl( 'importer', get_defined_vars() );
     146        }
     147
     148        function importer_post( $project_path ) {
     149                $project = GP::$project->by_path( $project_path );
     150
     151                if ( ! $project ) {
     152                        $this->die_with_404();
     153                }
     154
     155                if ( $this->cannot_and_redirect( 'bulk-import', 'project', $project->id ) ) {
     156                        return;
     157                }
     158
     159                $step = gp_post( 'importer-step', '1' );
     160
     161                // process the archive file upon each step because it is uploaded on every step because of the server-farm infrastructure
     162                $pofiles = $this->process_archive_file( $project );
     163
     164                switch( $step ) {
     165                        case 1:
     166                        default:
     167                                $this->show_selections( $project, $pofiles );
     168                                break;
     169                        case 2:
     170                                $this->confirm_selections( $project, $pofiles );
     171                                break;
     172                        case 3:
     173                                $this->process_imports( $project, $pofiles );
     174                                break;
     175                }
     176
     177        }
     178
     179        /**
     180         * extract the uploaded ZIP file
     181         * @param  object $project the project derived from the URL
     182         * @return array           the filenames of the extracted .po files
     183         */
     184        function process_archive_file( $project ) {
     185
     186                if ( ! is_uploaded_file( $_FILES['import-file']['tmp_name'] ) ) {
     187                        $this->redirect_with_error( __( 'Error uploading the file.' ) );
     188                        return;
     189                } else {
     190                        if ( ! gp_endswith( $_FILES['import-file']['name'], '.zip' ) || ! in_array( $_FILES['import-file']['type'], array( 'application/octet-stream', 'application/zip' ) ) ) {
     191                                $upload_error = true;
     192                                $this->redirect_with_error( __( 'Please upload a zip file.' ) );
     193                        }
     194                }
     195
     196                $filename = preg_replace("([^\w\s\d\-_~,;:\[\]\(\].]|[\.]{2,})", '',  $_FILES['import-file']['name'] );
     197                $slug = preg_replace( '/\.zip$/', '', $filename );
     198
     199                $working_directory = '/bulk-importer-' . $slug;
     200                $this->working_path = sys_get_temp_dir() . $working_directory;
     201
     202                // Make sure we have a fresh working directory.
     203                if ( file_exists( $this->working_path ) ) {
     204                        GP_Import_Export::rrmdir( $this->working_path );
     205                }
     206
     207                mkdir( $this->working_path );
     208
     209                $zip = new ZipArchiveExtended;
     210                if ( $zip->open( $_FILES['import-file']['tmp_name'] ) ) {
     211                        $zip->extractToFlatten( $this->working_path );
     212                        $zip->close();
     213                }
     214
     215                $pofiles = glob( $this->working_path . '/*.po' );
     216                if ( empty( $pofiles ) ) {
     217                        GP_Import_Export::rrmdir( $this->working_path );
     218                        $this->redirect_with_error( __( 'No PO files found in zip archive' ) );
     219                }
     220
     221                return $pofiles;
     222        }
     223
     224        /**
     225         * Step 1: extract the uploaded ZIP file
     226         * @param  object $project the project derived from the URL
     227         * @param  array $pofiles the filenames of the extracted .po files
     228         */
     229        function show_selections( $project, $pofiles ) {
     230                $sets = GP::$translation_set->by_project_id( $project->id );
     231                $sets_for_select = array_combine(
     232                        array_map( function( $s ){ return $s->id; }, $sets ),
     233                        array_map( function( $s ){ return $s->locale . ' - ' . $s->name; }, $sets )
     234                );
     235
     236                $sets_for_select = array( '0' => __('&mdash; Translation Set &mdash;' ) ) + $sets_for_select;
     237                unset( $sets );
     238
     239                $this->tmpl( 'importer-files', get_defined_vars() );
     240        }
     241
     242
     243        /**
     244         * Step 2: Confirm the locale mappings by the user and select
     245         * @param  object $project the project derived from the URL
     246         * @param  array $pofiles the filenames of the extracted .po files
     247         */
     248        function confirm_selections( $project, $pofiles ) {
     249
     250                $to_import = array();
     251                foreach( $pofiles as $po_file ) {
     252                        $target_set = gp_post( basename( $po_file, '.po') );
     253                        if ( $target_set  ) {
     254
     255                                $translation_set = GP::$translation_set->get( $target_set );
     256
     257                                if ( ! $translation_set ) {
     258                                        $this->errors[] = sprintf( __( 'Couldn&#8217;t find translation set id %d!' ), $target_set );
     259                                }
     260
     261                                $to_import[ basename( $po_file ) ] = array( 'id' => $translation_set->id, 'name' => $translation_set->name_with_locale() );
     262                        }
     263                }
     264
     265                if ( empty( $to_import ) ) {
     266                        $this->redirect_with_error( __( 'Please select a matching translation set for each PO file.' ) );
     267                }
     268
     269                $this->tmpl( 'importer-confirmation', get_defined_vars() );
     270        }
     271
     272        /**
     273         * Step 3: Do the import
     274         * @param  object $project the project derived from the URL
     275         * @param  array $pofiles the filenames of the extracted .po files
     276         */
     277
     278        function process_imports( $project, $pofiles ) {
     279
     280                if ( 'no' == gp_post( 'overwrite', 'yes' ) ) {
     281                        add_filter( 'translation_set_import_over_existing', '__return_false' );
     282                }
     283
     284                if ( 'waiting' == gp_post( 'status', 'current' ) ) {
     285                        add_filter( 'translation_set_import_status', function( $status ) {
     286                                return 'waiting';
     287                        });
     288                }
     289
     290                foreach( $pofiles as $po_file ) {
     291                        $target_set = gp_post( basename( $po_file, '.po') );
     292                        if ( $target_set  ) {
     293
     294                                $translation_set = GP::$translation_set->get( $target_set );
     295
     296                                if ( ! $translation_set ) {
     297                                        $this->errors[] = sprintf( __( 'Couldn&#8217;t find translation set id %d!' ), $target_set );
     298                                }
     299
     300                                $format = gp_array_get( GP::$formats, 'po', null );
     301                                $translations = $format->read_translations_from_file( $po_file, $project );
     302                                if ( ! $translations ) {
     303                                        $this->errors[] = sprintf( __( 'Couldn&#8217;t load translations from file %s!' ), basename( $po_file ) );
     304                                        continue;
     305                                }
     306                                $translations_added = $translation_set->import( $translations );
     307                                $this->notices[] = sprintf( __( '%s translations were added from %s' ), $translations_added, basename( $po_file ) );
     308                        }
     309                }
     310                $this->notices = array( implode('<br>', $this->notices ) );
     311                $this->errors = array( implode('<br>', $this->errors ) );
     312
     313                // cleanup
     314                if ( $this->working_path ) {
     315                        GP_Import_Export::rrmdir( $this->working_path );
     316                }
     317
     318                $this->redirect();
     319        }
     320
     321
     322        function headers_for_download( $filename ) {
     323                $this->header( 'Pragma: public' );
     324                $this->header( 'Expires: 0' );
     325                $this->header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
     326                $this->header( 'Cache-Control: public' );
     327                $this->header( 'Content-Description: File Transfer' );
     328                $this->header( 'Content-type: application/octet-stream' );
     329                $this->header( 'Content-Disposition: attachment; filename="' . basename( $filename ) . '"' );
     330                $this->header( 'Content-Transfer-Encoding: binary' );
     331                $this->header( 'Content-Length: ' . filesize( $filename ) );
     332        }
     333
     334}
     335
     336if ( class_exists( 'ZipArchive' ) ) {
     337        class ZipArchiveExtended extends ZipArchive {
     338
     339                public function addDir( $path, $basedir ) {
     340                        $cwd = getcwd();
     341                        chdir( $basedir );
     342
     343                        $this->addEmptyDir( $path );
     344                        $nodes = glob( $path . '/*' );
     345                        foreach ( $nodes as $node ) {
     346                                if ( is_dir( $node ) ) {
     347                                        $this->addDir( $node );
     348                                } else if ( is_file( $node ) )  {
     349                                        $this->addFile( $node );
     350                                }
     351                        }
     352
     353                        chdir( $cwd );
     354                        return true;
     355                }
     356
     357                public function extractToFlatten( $path ) {
     358                        for ( $i = 0; $i < $this->numFiles; $i++ ) {
     359
     360                                $entry = $this->getNameIndex( $i );
     361                                if ( substr( $entry, -1 ) == '/' ) continue; // skip directories to flatten the file structure
     362
     363                                $fp = $this->getStream( $entry );
     364                                if ( $fp ) {
     365                                        $ofp = fopen( $path . '/' . basename( $entry ), 'w' );
     366                                        while ( ! feof( $fp ) ) {
     367                                                fwrite( $ofp, fread( $fp, 8192 ) );
     368                                        }
     369
     370                                        fclose( $fp );
     371                                        fclose( $ofp );
     372                                }
     373                        }
     374
     375                        return $path;
     376                }
     377        }
     378} else {
     379        class ZipArchiveExtended {
     380                const CREATE = 0;
     381                const OVERWRITE = 0;
     382
     383                private $archive_file;
     384                public function open( $archive_file, $flags = false ) {
     385                        $this->archive_file = $archive_file;
     386                        return true;
     387                }
     388
     389                public function addDir( $path, $basedir ) {
     390                        $cwd = getcwd();
     391                        chdir( $basedir );
     392
     393                        $zip_command = 'zip -r ' . escapeshellarg( $this->archive_file ) . ' ' . escapeshellarg( $path );
     394                        $zip_output = array();
     395                        $zip_status = null;
     396
     397                        exec( $zip_command, $zip_output, $zip_status );
     398
     399                        if ( 0 !== $zip_status ) {
     400                                return false;
     401                        }
     402
     403                        return true;
     404                }
     405
     406                public function extractToFlatten( $path ) {
     407                        system( 'unzip -j -qq ' . $this->archive_file . ' *.po -d ' . escapeshellarg( $path ) );
     408                        return $path;
     409                }
     410
     411                public function close() {
     412                }
     413
     414        }
     415}
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/exporter.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Export Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Export')
     6) );
     7
     8gp_tmpl_header();
     9?>
     10<style type="text/css">
     11#predefines {
     12        border: 1px #ccc solid;
     13        padding: .5em;
     14        float: right;
     15        width: 300px;
     16}
     17
     18#predefines ul {
     19        margin-left: 0;
     20        padding-left: 1em;
     21}
     22
     23#predefines ul li {
     24        display: block;
     25        margin-left: 0;
     26        padding-left: 0;
     27}
     28
     29#predefines ul li a.delete {
     30        background-color: transparent;
     31        color: #c99;
     32        margin-right: 1em;
     33        font-size: 8pt;
     34}
     35
     36#predefines h4 {
     37        margin-top: 0;
     38}
     39
     40#predefines .options {
     41        font-size: 80%;
     42        float: right;
     43}
     44#save-predefined {
     45        float: right;
     46}
     47#import-predefined, #export-predefined {
     48        color: #999;
     49}
     50#export-predefined {
     51        display: none;
     52}
     53</style>
     54<h2><?php _e('Bulk Export Translations'); ?></h2>
     55<form id="export-filters" class="export-filters" action="<?php echo esc_url( gp_url_current() ); ?>/-do" method="get" accept-charset="utf-8">
     56        <div id="predefines">
     57                <span class="options">
     58                        <a href="" id="import-predefined"><?php _e( 'Import' ); ?></a>
     59                        <a href="" id="export-predefined"><?php _e( 'Export' ); ?></a>
     60                </span>
     61                <h4><?php _e( 'Restore previous form data' ); ?></h4>
     62                <ul></ul>
     63                <a href="" id="save-predefined"><?php _e( 'Save current form data' ); ?></a>
     64        </div>
     65
     66        <dl>
     67                <dt><label>Translation Sets</label></dt>
     68                <dd>
     69                        <?php echo gp_select( 'translation_sets[]', $sets_for_select, null, array( 'multiple' => 'multiple', 'size' => '12', 'style' =>'height:auto;' ) ); ?>
     70                </dd>
     71                <dt><label><?php _e( 'Translations status:' ); ?></label></dt>
     72                <dd>
     73                        <?php
     74                        echo gp_radio_buttons( 'filters[status]',
     75                                array(
     76                                        'current_or_waiting_or_fuzzy_or_untranslated' => __('Current/waiting/fuzzy + untranslated (All)'),
     77                                        'current' => __('Current only'),
     78                                        'old' => __('Approved, but obsoleted by another string'),
     79                                        'waiting' => __('Waiting approval'),
     80                                        'fuzzy' => __('Fuzzy'),
     81                                        'rejected' => __('Rejected'),
     82                                        'untranslated' => __('Without current translation'),
     83                                        'either' => __('Any'),
     84                                ), 'current_or_waiting_or_fuzzy_or_untranslated' );
     85                        ?>
     86                </dd>
     87
     88                <dt><label><?php _e('Originals priority:'); ?></label></dt>
     89                <dd>
     90                        <?php
     91                        $valid_priorities = GP::$original->get_static( 'priorities' );
     92                        krsort( $valid_priorities);
     93                        if ( ! isset( $can_write) || ! $can_write ) {
     94                                //Non admins can't see hidden strings
     95                                unset( $valid_priorities['-2'] );
     96                        }
     97                        foreach ( $valid_priorities as $priority => $label ):
     98                                ?>
     99                                <input checked="checked" type="checkbox" name="filters[priority][]" value="<?php echo esc_attr( $priority );?>" id="priority[<?php echo esc_attr( $label );?>]"><label for='priority[<?php echo esc_attr( $label );?>]'><?php echo esc_html( $label );?></label><br />
     100                        <?php endforeach; ?>
     101                </dd>
     102                <?php if( isset( $views_for_select ) ): ?>
     103                <dt><?php _e( 'Predefined View' ); ?></dt>
     104                <dd>
     105                        <?php echo gp_select('filters[view]', $views_for_select, null ); ?>
     106                </dd>
     107                <?php endif; ?>
     108                <dt><label><?php _e( 'Format:' ); ?></label></dt>
     109                <dd>
     110                        <?php
     111                        $format_options = array();
     112                        foreach ( GP::$formats as $slug => $format ) {
     113                                $format_options[$slug] = $format->name;
     114                        }
     115                        echo gp_select( 'export-format', $format_options, 'po' );
     116                        ?>
     117                </dd>
     118                <dt><label><?php _e( 'Translations added between:' ); ?></label></dt>
     119                <dd>
     120                <?php /* translators: %1$s: from date, %2$s: to date */ printf( __( '%1$s - %2$s' ), '<input type="date" name="filters[before_date_added]" placeholder="YYYY-MM-DD"/>', '<input type="date" name="filters[after_date_added]" placeholder="YYYY-MM-DD" />' ); ?>
     121                        <a href="" id="last-month"><?php _e( 'last month' ); ?></a>
     122                        <a href="" id="clear-dates"><?php _e( 'clear' ); ?></a>
     123                </dd>
     124        </dl>
     125        <p><input type="submit" value="<?php echo esc_attr( __( 'Export' ) ); ?>" name="export" /></p>
     126</form>
     127
     128<script type="text/javascript">
     129var name_question = '<?php _e( 'Enter a name for this configuration' ); ?>';
     130var delete_question = '<?php _e( 'Do you want to delete "%s"?' ); ?>';
     131var copy_data = '<?php _e( 'Copy the export data below:' ); ?>';
     132var paste_data = '<?php _e( 'Paste your import data below:' ); ?>';
     133var invalid_data = '<?php _e( 'Unfortunately, the data you have entered is not valid JSON.' ); ?>';
     134
     135jQuery( '#save-predefined' ).on( 'click', function() {
     136        var predefs,
     137                data = jQuery( this ).closest( 'form' ).serialize(),
     138                name = prompt( name_question );
     139        if ( ! name ) {
     140                return false;
     141        }
     142
     143        predefs = getPredefData();
     144        predefs[ name ] = data;
     145        localStorage.setItem( 'predefs', JSON.stringify( predefs ) );
     146        updatePredefs();
     147        return false;
     148} );
     149jQuery( '#import-predefined' ).on( 'click', function() {
     150        var data = prompt( paste_data );
     151
     152        try {
     153                JSON.parse( localStorage.getItem( 'predefs' ) );
     154        } catch ( e ) {
     155                alert( invalid_data );
     156                return false;
     157        }
     158
     159        localStorage.setItem( 'predefs', data );
     160        updatePredefs();
     161        return false;
     162});
     163
     164jQuery( '#export-predefined' ).on( 'click', function() {
     165        prompt( copy_data, localStorage.getItem( 'predefs' ) );
     166        return false;
     167});
     168
     169jQuery( '#predefines' ).on( 'click', 'li span a', function() {
     170        var data = jQuery( this ).closest( 'li' ).data( 'form' ),
     171                form = jQuery( '#predefines' ).closest( 'form' );
     172        form.unserialize( data );
     173        return false;
     174} );
     175
     176jQuery( '#predefines' ).on( 'click', 'li a.delete', function() {
     177        var li = jQuery( this ).closest( 'li' ),
     178                predefs = getPredefData();
     179        if ( ! confirm( delete_question.replace( '%s', li.data( 'name' )) ) ) {
     180                return false;
     181        }
     182        delete predefs[ li.data( 'name' ) ];
     183        localStorage.setItem( 'predefs', JSON.stringify( predefs ) );
     184
     185        updatePredefs();
     186        return false;
     187} );
     188
     189var addPredefItem = function( name, data ) {
     190        var li = jQuery( '<li><a href="" class="delete">X</a><span><a href="#">' );
     191        li.data( 'form', data ).data( 'name', name ).find( 'span a' ).text( name );
     192        jQuery( '#predefines ul' ).append( li );
     193
     194};
     195var getPredefData = function() {
     196        try {
     197                return JSON.parse( localStorage.getItem( 'predefs' ) ) || {};
     198        } catch ( e ) {
     199                return {};
     200        }
     201};
     202var updatePredefs = function() {
     203        jQuery( '#predefines ul' ).html( '' );
     204        var name,
     205                predefs = getPredefData();
     206        for ( name in predefs ) {
     207                addPredefItem( name, predefs[ name ] );
     208        }
     209
     210        if ( jQuery( '#predefines ul li' ).length ) {
     211                jQuery( '#export-predefined' ).show();
     212        } else {
     213                jQuery( '#export-predefined' ).hide();
     214        }
     215};
     216// Run when document is ready
     217jQuery( updatePredefs );
     218
     219function decodeUriIfNecessary( str ) {
     220        if ( str.match( /%[0-9a-fA-F]{2}/ ) ) {
     221                try {
     222                        return decodeURIComponent( str );
     223                } catch (e) {
     224                        return str;
     225                }
     226        }
     227        return str;
     228}
     229jQuery.unserialize = function( str ) {
     230        var arr, i, parts,
     231                items = str.split( '&' ),
     232                ret = "{",
     233                arrays = [],
     234                index = "";
     235
     236        for ( i = 0; i < items.length; i++ ) {
     237                parts = items[ i ].split( /=/ );
     238                if ( parts[ 0 ].substr( -6 ) === '%5B%5D' ) {
     239                        // Process arrays without a key
     240                        index = decodeUriIfNecessary( parts[ 0 ].substr( 0, parts[ 0 ].length - 6 ) );
     241                        if ( arrays[ index ] === undefined ) {
     242                                arrays[ index ] = [];
     243                        }
     244                        arrays[ index ].push( decodeUriIfNecessary( parts[ 1 ].replace( /\+/g, " " ) ) );
     245                } else {
     246                        if ( parts.length > 1 ) {
     247                                ret += "\"" + decodeUriIfNecessary( parts[ 0 ] ) + "\": \"" + decodeUriIfNecessary( parts[ 1 ].replace( /\+/g, " " ) ).replace( /\n/g, "\\n" ).replace( /\r/g, "\\r" ) + "\", ";
     248                        }
     249                }
     250        }
     251
     252        ret = ( ret != "{" ) ? ret.substr( 0, ret.length - 2 ) + "}" : ret + "}";
     253        ret = JSON.parse( ret );
     254
     255        // Process the arrays without key
     256        for ( arr in arrays ) {
     257                ret[ arr ] = arrays[ arr ];
     258        }
     259        return ret;
     260};
     261
     262jQuery.fn.unserialize = function( param ) {
     263        var i, val, parts,
     264                items = jQuery.unserialize( param ),
     265                applyString = function( index, item ) {
     266                        var val, i;
     267                        item = jQuery( item );
     268                        if ( parts[ 1 ] instanceof Array ) {
     269                                for ( i in parts[ 1 ] ) {
     270                                        val = "" + parts[ 1 ][ i ];
     271                                        if ( item.val() == decodeUriIfNecessary( val.replace( /\+/g, " " ) ) ) {
     272                                                item.prop( "checked", true );
     273                                        } else {
     274                                                if ( jQuery.inArray( item.val(), parts[ 1 ] ) < 0 ) {
     275                                                        item.prop( "checked", false );
     276                                                }
     277                                        }
     278                                }
     279                        } else {
     280                                val = "" + parts[ 1 ];
     281                                if ( item.val() == decodeUriIfNecessary( val.replace( /\+/g, " " ) ) ) {
     282                                        item.prop( "checked", true );
     283                                } else {
     284                                        item.prop( "checked", false );
     285                                }
     286                        }
     287                };
     288
     289        for ( i in items ) {
     290                parts = ( items instanceof Array ) ? items[ i ].split( /=/ ) : [ i, ( items[ i ] instanceof Array ) ? items[ i ] : "" + items[ i ] ];
     291                parts[ 0 ] = decodeUriIfNecessary( parts[ 0 ] );
     292
     293                if ( parts[ 0 ].indexOf( "[]" ) == -1 && parts[ 1 ] instanceof Array ) {
     294                        parts[ 0 ] += "[]";
     295                }
     296
     297                obj = this.find( '[name=\'' + parts[ 0 ] + '\']' );
     298                if ( obj.length == 0 ) {
     299                        try {
     300                                obj = this.parent().find( '[name=\'' + parts[ 0 ] + '\']' );
     301                        } catch ( e ) {}
     302                }
     303
     304                if ( typeof obj.attr( "type" ) == "string" && ( obj.attr( "type" ).toLowerCase() == "radio" || obj.attr( "type" ).toLowerCase() == "checkbox" ) ) {
     305                        obj.each( applyString );
     306                } else if ( obj.length > 0 && obj[ 0 ].tagName == "SELECT" && parts[ 1 ] instanceof Array && obj.prop( "multiple" ) ) {
     307                        // Here, i have an array for a multi-select.
     308                        obj.val( parts[ 1 ] );
     309                } else {
     310                        // When the value is an array, we join without delimiter
     311                        val = ( parts[ 1 ] instanceof Array ) ? parts[ 1 ].join( "" ) : parts[ 1 ];
     312                        // when the value is an object, we set the value to ""
     313                        val = ( ( typeof val == "object" ) || ( typeof val == "undefined" ) ) ? "" : val;
     314
     315                        obj.val( decodeUriIfNecessary( val.replace( /\+/g, " " ) ) );
     316                }
     317        }
     318        return this;
     319};
     320jQuery( '#last-month' ).on( 'click', function() {
     321        var d = new Date;
     322        d.setDate( 1 );
     323        d.setMonth( d.getMonth() - 1 );
     324        jQuery( 'input[name=filters\\[before_date_added\\]]' ).val( getMySQLDate( d ) );
     325        d = new Date;
     326        d.setDate( 0 );
     327        jQuery( 'input[name=filters\\[after_date_added\\]]' ).val( getMySQLDate( d ) );
     328        return false;
     329});
     330
     331jQuery( '#clear-dates' ).on( 'click', function() {
     332        jQuery( 'input[name=filters\\[before_date_added\\]], input[name=filters\\[after_date_added\\]]' ).val( '' );
     333        return false;
     334});
     335
     336function getMySQLDate( date ) {
     337        var day = date.getDate(),
     338                month = date.getMonth() + 1,
     339                year = date.getYear();
     340
     341        if ( year < 2000 ) {
     342                year += 1900;
     343        }
     344        if ( month < 10 ) {
     345                month = '0' + String( month );
     346        }
     347        if ( day < 10 ) {
     348                day = '0' + String( day );
     349        }
     350        return year + '-' + month + '-' + day;
     351}
     352</script>
     353
     354<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer-confirmation.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8?>
     9
     10        <h2><?php _e('Bulk Import Translations'); ?></h2>
     11        <form action="" method="post" enctype="multipart/form-data" id="step3">
     12        <input type="hidden" name="importer-step" value="3">
     13                <dl>
     14                        <dt><?php _e( 'Select Sets' ); ?></dt>
     15                        <dd>
     16                        <?php foreach ( $to_import as $po => $destination ) : ?>
     17                                <p>
     18                                        <?php echo basename( $po ); ?> &rarr; <?php echo $destination['name']; ?>
     19                                        <input type="hidden" name="<?php echo esc_attr( basename( $po, '.po' ) ) ; ?>" value="<?php echo absint( $destination['id'] );?>">
     20                                </p>
     21                        <?php endforeach; ?>
     22                        </dd>
     23                        <dt><?php _e( 'Overwrite Translations' ); ?></dt>
     24                        <dd>
     25                                <?php echo gp_radio_buttons( 'overwrite', array(
     26                                        'yes' => 'Overwrite existing translations',
     27                                        'no' => 'Only import new translations',
     28                                ), 'yes' ); ?>
     29                        </dd>
     30                        <dt><?php _e( 'Translation Status' ); ?></dt>
     31                        <dd>
     32                                <?php echo gp_radio_buttons( 'status', array(
     33                                        'current' => 'Current',
     34                                        'waiting' => 'Waiting',
     35                                ), 'current' ); ?>
     36                        </dd>
     37                        <dt><input type="submit" value="<?php echo esc_attr( __( 'Import' ) ); ?>"></dt>
     38                </dl>
     39        </form>
     40
     41        <script type="text/javascript">
     42                parent.document.getElementById('step2').style.display = 'none';
     43                parent.document.getElementById('step3').innerHTML = document.getElementById('step3').innerHTML;
     44                parent.document.getElementById('step1form').target = "top";
     45        </script>
     46
     47
     48<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer-files.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8
     9function get_key_to_be_selected( $name_and_id, $options ) {
     10        $selected_locale = '';
     11
     12        foreach( $options as $value => $label ) {
     13                $locale = substr( $label, 0, strpos( $label, ' - ' ) );
     14
     15                // we don't stop after the first match but continue the search because of cases like:
     16                // pt-br: br == Breton, but we want Brasilian Portuguese
     17                // zh vs. zh-cn vs zh-tw
     18                // In general: Take the longest possible match
     19
     20                if ( strlen( $locale ) > strlen( $selected_locale ) ) {
     21                        if ( preg_match( "#\b$locale\b#", $name_and_id ) ) {
     22                                $selected_key = $value;
     23                                $selected_locale = $locale;
     24                        }
     25                }
     26        }
     27        return $selected_key;
     28}
     29
     30?>
     31
     32        <h2><?php _e('Bulk Import Translations'); ?></h2>
     33        <form action="" method="post" enctype="multipart/form-data" id="step2">
     34                <input type="hidden" name="importer-step" value="2">
     35                <dl>
     36                        <dt><?php _e( 'Select Sets' ); ?></dt>
     37                        <dd>
     38                        <?php foreach ( $pofiles as $po ) : ?>
     39                        <?php $po_name = basename( $po, '.po' ); ?>
     40                                <p>
     41                                        <label for="<?php echo $po_name; ?>"><?php echo basename( $po ) ?> &rarr;</label>
     42                                        <?php echo gp_select( $po_name, $sets_for_select, get_key_to_be_selected( $po_name, $sets_for_select ) ); ?>
     43                                </p>
     44                        <?php endforeach; ?>
     45                        </dd>
     46                        <dt><input type="submit" value="<?php echo esc_attr( __('Review') ); ?>"></dt>
     47                </dl>
     48        </form>
     49
     50        <script type="text/javascript">
     51                parent.document.getElementById('step1').style.display = 'none';
     52                parent.document.getElementById('step2').innerHTML = document.getElementById('step2').innerHTML;
     53        </script>
     54
     55<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/gp-import-export/templates/importer.php

     
     1<?php
     2gp_title( sprintf( __('Bulk Import Translations &lt; %s &lt; GlotPress'), esc_html( $project->name ) ) );
     3gp_breadcrumb( array(
     4        gp_project_links_from_root( $project ),
     5        __('Bulk Import')
     6) );
     7gp_tmpl_header();
     8?>
     9
     10        <h2><?php _e('Bulk Import Translations'); ?></h2>
     11        <form action="" method="post" enctype="multipart/form-data" id="step1form">
     12                <div id="inner-error" class="error" style="display: none"></div>
     13                <input type="hidden" name="importer-step" value="1">
     14                <dl id="step1">
     15                        <dt><label for="import-file"><?php _e( 'Import File:' ); ?></label></dt>
     16                        <dd><input type="file" name="import-file" id="import-file" /></dd>
     17                        <dt><input type="submit" value="<?php echo esc_attr( __( 'Import' ) ); ?>"></dt>
     18                </dl>
     19                <dl id="step2">
     20                </dl>
     21                <dl id="step3">
     22                </dl>
     23        </form>
     24
     25        <div id="tempframe-holder" style="display: none"></div>
     26
     27        <script type="text/javascript">
     28        var updateErrorsInterval;
     29        jQuery( function() {
     30                jQuery( '#tempframe-holder' ).html( '<iframe name="tempframe"></iframe>' );
     31                jQuery( '#step1form' ).attr( 'target', 'tempframe' );
     32                updateErrorsInterval = setInterval( updateErrors, 1000 );
     33        }) ;
     34        function updateErrors() {
     35                if ( typeof window.tempframe === 'undefined' || typeof window.tempframe.jQuery === 'undefined' ) {
     36                        return false;
     37                }
     38                var error = window.tempframe.jQuery('.error');
     39                if ( error.length > 0 ) {
     40                        jQuery('#inner-error').html( error.html() ).show();
     41                        jQuery('html, body').animate({
     42                            scrollTop: jQuery("#inner-error").offset().top
     43                        }, 200);
     44                } else {
     45                        jQuery('#inner-error').hide();
     46                }
     47        }
     48        </script>
     49
     50<?php gp_tmpl_footer();
  • translate.wordpress.org/includes/gp-plugins/wporg-rosetta-roles/wporg-rosetta-roles.php

     
    4343         * @return bool True if user has permissions, false if not.
    4444         */
    4545        public function pre_can_user( $verdict, $args ) {
     46                if ( in_array( $args['action'], array( 'bulk-import', 'bulk-export' ) ) ) {
     47                        // the bulk-import permission is checked by GlotPress, independently of the user's status within Rosetta
     48                        return;
     49                }
     50
     51                return true;
    4652                if ( ! class_exists( 'BP_Roles' ) ) {
    4753                        require_once( BACKPRESS_PATH . 'class.bp-roles.php' );
    4854                }