Ticket #1089: 1089.diff
File 1089.diff, 51.9 KB (added by , 9 years ago) |
---|
-
translate.wordpress.org/includes/gp-plugins/gp-import-export/LICENSE
1 GNU 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 12 freedom to share and change it. By contrast, the GNU General Public 13 License is intended to guarantee your freedom to share and change free 14 software--to make sure the software is free for all its users. This 15 General Public License applies to most of the Free Software 16 Foundation's software and to any other program whose authors commit to 17 using it. (Some other Free Software Foundation software is covered by 18 the GNU Lesser General Public License instead.) You can apply it to 19 your programs, too. 20 21 When we speak of free software, we are referring to freedom, not 22 price. Our General Public Licenses are designed to make sure that you 23 have the freedom to distribute copies of free software (and charge for 24 this service if you wish), that you receive source code or can get it 25 if you want it, that you can change the software or use pieces of it 26 in 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 29 anyone to deny you these rights or to ask you to surrender the rights. 30 These restrictions translate to certain responsibilities for you if you 31 distribute copies of the software, or if you modify it. 32 33 For example, if you distribute copies of such a program, whether 34 gratis or for a fee, you must give the recipients all the rights that 35 you have. You must make sure that they, too, receive or can get the 36 source code. And you must show them these terms so they know their 37 rights. 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, 41 distribute and/or modify the software. 42 43 Also, for each author's protection and ours, we want to make certain 44 that everyone understands that there is no warranty for this free 45 software. If the software is modified by someone else and passed on, we 46 want its recipients to know that what they have is not the original, so 47 that any problems introduced by others will not reflect on the original 48 authors' reputations. 49 50 Finally, any free program is threatened constantly by software 51 patents. We wish to avoid the danger that redistributors of a free 52 program will individually obtain patent licenses, in effect making the 53 program proprietary. To prevent this, we have made it clear that any 54 patent must be licensed for everyone's free use or not licensed at all. 55 56 The precise terms and conditions for copying, distribution and 57 modification 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 63 a notice placed by the copyright holder saying it may be distributed 64 under the terms of this General Public License. The "Program", below, 65 refers to any such program or work, and a "work based on the Program" 66 means either the Program or any derivative work under copyright law: 67 that is to say, a work containing the Program or a portion of it, 68 either verbatim or with modifications and/or translated into another 69 language. (Hereinafter, translation is included without limitation in 70 the term "modification".) Each licensee is addressed as "you". 71 72 Activities other than copying, distribution and modification are not 73 covered by this License; they are outside its scope. The act of 74 running the Program is not restricted, and the output from the Program 75 is covered only if its contents constitute a work based on the 76 Program (independent of having been made by running the Program). 77 Whether that is true depends on what the Program does. 78 79 1. You may copy and distribute verbatim copies of the Program's 80 source code as you receive it, in any medium, provided that you 81 conspicuously and appropriately publish on each copy an appropriate 82 copyright notice and disclaimer of warranty; keep intact all the 83 notices that refer to this License and to the absence of any warranty; 84 and give any other recipients of the Program a copy of this License 85 along with the Program. 86 87 You may charge a fee for the physical act of transferring a copy, and 88 you 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 91 of it, thus forming a work based on the Program, and copy and 92 distribute such modifications or work under the terms of Section 1 93 above, 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 114 These requirements apply to the modified work as a whole. If 115 identifiable sections of that work are not derived from the Program, 116 and can be reasonably considered independent and separate works in 117 themselves, then this License, and its terms, do not apply to those 118 sections when you distribute them as separate works. But when you 119 distribute the same sections as part of a whole which is a work based 120 on the Program, the distribution of the whole must be on the terms of 121 this License, whose permissions for other licensees extend to the 122 entire whole, and thus to each and every part regardless of who wrote it. 123 124 Thus, it is not the intent of this section to claim rights or contest 125 your rights to work written entirely by you; rather, the intent is to 126 exercise the right to control the distribution of derivative or 127 collective works based on the Program. 128 129 In addition, mere aggregation of another work not based on the Program 130 with the Program (or with a work based on the Program) on a volume of 131 a storage or distribution medium does not bring the other work under 132 the scope of this License. 133 134 3. You may copy and distribute the Program (or a work based on it, 135 under Section 2) in object code or executable form under the terms of 136 Sections 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 155 The source code for a work means the preferred form of the work for 156 making modifications to it. For an executable work, complete source 157 code means all the source code for all modules it contains, plus any 158 associated interface definition files, plus the scripts used to 159 control compilation and installation of the executable. However, as a 160 special exception, the source code distributed need not include 161 anything that is normally distributed (in either source or binary 162 form) with the major components (compiler, kernel, and so on) of the 163 operating system on which the executable runs, unless that component 164 itself accompanies the executable. 165 166 If distribution of executable or object code is made by offering 167 access to copy from a designated place, then offering equivalent 168 access to copy the source code from the same place counts as 169 distribution of the source code, even though third parties are not 170 compelled to copy the source along with the object code. 171 172 4. You may not copy, modify, sublicense, or distribute the Program 173 except as expressly provided under this License. Any attempt 174 otherwise to copy, modify, sublicense or distribute the Program is 175 void, and will automatically terminate your rights under this License. 176 However, parties who have received copies, or rights, from you under 177 this License will not have their licenses terminated so long as such 178 parties remain in full compliance. 179 180 5. You are not required to accept this License, since you have not 181 signed it. However, nothing else grants you permission to modify or 182 distribute the Program or its derivative works. These actions are 183 prohibited by law if you do not accept this License. Therefore, by 184 modifying or distributing the Program (or any work based on the 185 Program), you indicate your acceptance of this License to do so, and 186 all its terms and conditions for copying, distributing or modifying 187 the Program or works based on it. 188 189 6. Each time you redistribute the Program (or any work based on the 190 Program), the recipient automatically receives a license from the 191 original licensor to copy, distribute or modify the Program subject to 192 these terms and conditions. You may not impose any further 193 restrictions on the recipients' exercise of the rights granted herein. 194 You are not responsible for enforcing compliance by third parties to 195 this License. 196 197 7. If, as a consequence of a court judgment or allegation of patent 198 infringement or for any other reason (not limited to patent issues), 199 conditions are imposed on you (whether by court order, agreement or 200 otherwise) that contradict the conditions of this License, they do not 201 excuse you from the conditions of this License. If you cannot 202 distribute so as to satisfy simultaneously your obligations under this 203 License and any other pertinent obligations, then as a consequence you 204 may not distribute the Program at all. For example, if a patent 205 license would not permit royalty-free redistribution of the Program by 206 all those who receive copies directly or indirectly through you, then 207 the only way you could satisfy both it and this License would be to 208 refrain entirely from distribution of the Program. 209 210 If any portion of this section is held invalid or unenforceable under 211 any particular circumstance, the balance of the section is intended to 212 apply and the section as a whole is intended to apply in other 213 circumstances. 214 215 It is not the purpose of this section to induce you to infringe any 216 patents or other property right claims or to contest validity of any 217 such claims; this section has the sole purpose of protecting the 218 integrity of the free software distribution system, which is 219 implemented by public license practices. Many people have made 220 generous contributions to the wide range of software distributed 221 through that system in reliance on consistent application of that 222 system; it is up to the author/donor to decide if he or she is willing 223 to distribute software through any other system and a licensee cannot 224 impose that choice. 225 226 This section is intended to make thoroughly clear what is believed to 227 be a consequence of the rest of this License. 228 229 8. If the distribution and/or use of the Program is restricted in 230 certain countries either by patents or by copyrighted interfaces, the 231 original copyright holder who places the Program under this License 232 may add an explicit geographical distribution limitation excluding 233 those countries, so that distribution is permitted only in or among 234 countries not thus excluded. In such case, this License incorporates 235 the limitation as if written in the body of this License. 236 237 9. The Free Software Foundation may publish revised and/or new versions 238 of the General Public License from time to time. Such new versions will 239 be similar in spirit to the present version, but may differ in detail to 240 address new problems or concerns. 241 242 Each version is given a distinguishing version number. If the Program 243 specifies a version number of this License which applies to it and "any 244 later version", you have the option of following the terms and conditions 245 either of that version or of any later version published by the Free 246 Software Foundation. If the Program does not specify a version number of 247 this License, you may choose any version ever published by the Free Software 248 Foundation. 249 250 10. If you wish to incorporate parts of the Program into other free 251 programs whose distribution conditions are different, write to the author 252 to ask for permission. For software which is copyrighted by the Free 253 Software Foundation, write to the Free Software Foundation; we sometimes 254 make exceptions for this. Our decision will be guided by the two goals 255 of preserving the free status of all derivatives of our free software and 256 of 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 261 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 REPAIR OR CORRECTION. 269 270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 POSSIBILITY 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 285 possible use to the public, the best way to achieve this is to make it 286 free 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 289 to attach them to the start of each source file to most effectively 290 convey the exclusion of warranty; and each file should have at least 291 the "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 310 Also add information on how to contact you by electronic and paper mail. 311 312 If the program is interactive, make it output a short notice like this 313 when 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 320 The hypothetical commands `show w' and `show c' should show the appropriate 321 parts of the General Public License. Of course, the commands you use may 322 be called something other than `show w' and `show c'; they could even be 323 mouse-clicks or menu items--whatever suits your program. 324 325 You should also get your employer (if you work as a programmer) or your 326 school, if any, to sign a "copyright disclaimer" for the program, if 327 necessary. 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 335 This General Public License does not permit incorporating your program into 336 proprietary programs. If your program is a subroutine library, you may 337 consider it more useful to permit linking proprietary applications with the 338 library. If this is what you want to do, use the GNU Lesser General 339 Public License instead of this License. 340 No newline at end of file -
translate.wordpress.org/includes/gp-plugins/gp-import-export/README.md
1 gp-import-export 2 =========== 3 4 ## Description 5 6 Bulk Import/Export plugin for GlotPress. 7 8 See 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 9 require_once( dirname(__FILE__) .'/includes/router.php' ); 10 11 class 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 67 GP::$plugins->import_export = new GP_Import_Export; -
translate.wordpress.org/includes/gp-plugins/gp-import-export/includes/router.php
1 <?php 2 3 class 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( '' => __( '— Select —' ) ); 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( '' => __('— All —') ) + $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' => __('— Translation Set —' ) ) + $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’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’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’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 336 if ( 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 2 gp_title( sprintf( __('Bulk Export Translations < %s < GlotPress'), esc_html( $project->name ) ) ); 3 gp_breadcrumb( array( 4 gp_project_links_from_root( $project ), 5 __('Bulk Export') 6 ) ); 7 8 gp_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"> 129 var name_question = '<?php _e( 'Enter a name for this configuration' ); ?>'; 130 var delete_question = '<?php _e( 'Do you want to delete "%s"?' ); ?>'; 131 var copy_data = '<?php _e( 'Copy the export data below:' ); ?>'; 132 var paste_data = '<?php _e( 'Paste your import data below:' ); ?>'; 133 var invalid_data = '<?php _e( 'Unfortunately, the data you have entered is not valid JSON.' ); ?>'; 134 135 jQuery( '#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 } ); 149 jQuery( '#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 164 jQuery( '#export-predefined' ).on( 'click', function() { 165 prompt( copy_data, localStorage.getItem( 'predefs' ) ); 166 return false; 167 }); 168 169 jQuery( '#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 176 jQuery( '#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 189 var 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 }; 195 var getPredefData = function() { 196 try { 197 return JSON.parse( localStorage.getItem( 'predefs' ) ) || {}; 198 } catch ( e ) { 199 return {}; 200 } 201 }; 202 var 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 217 jQuery( updatePredefs ); 218 219 function 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 } 229 jQuery.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 262 jQuery.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 }; 320 jQuery( '#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 331 jQuery( '#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 336 function 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 2 gp_title( sprintf( __('Bulk Import Translations < %s < GlotPress'), esc_html( $project->name ) ) ); 3 gp_breadcrumb( array( 4 gp_project_links_from_root( $project ), 5 __('Bulk Import') 6 ) ); 7 gp_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 ); ?> → <?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 2 gp_title( sprintf( __('Bulk Import Translations < %s < GlotPress'), esc_html( $project->name ) ) ); 3 gp_breadcrumb( array( 4 gp_project_links_from_root( $project ), 5 __('Bulk Import') 6 ) ); 7 gp_tmpl_header(); 8 9 function 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 ) ?> →</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 2 gp_title( sprintf( __('Bulk Import Translations < %s < GlotPress'), esc_html( $project->name ) ) ); 3 gp_breadcrumb( array( 4 gp_project_links_from_root( $project ), 5 __('Bulk Import') 6 ) ); 7 gp_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
43 43 * @return bool True if user has permissions, false if not. 44 44 */ 45 45 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; 46 52 if ( ! class_exists( 'BP_Roles' ) ) { 47 53 require_once( BACKPRESS_PATH . 'class.bp-roles.php' ); 48 54 }