├── .gitignore ├── Changes ├── LICENSE ├── README.md ├── bin └── po2json ├── dist.ini ├── lib └── DDG │ └── Translate.pm ├── share └── js │ ├── ddg_translate.js │ ├── gettext │ ├── COPYING.LESSER │ └── Gettext.js │ └── sprintf.js └── t ├── 10-gettext.t ├── 20-ddg-translate.t ├── 21-dryrun.t ├── 30-ddg-othertest.t └── data ├── ddg_translate_dryrun_test.html ├── ddg_translate_test.html ├── gettext_test.html ├── locale └── de_DE │ └── LC_MESSAGES │ ├── othertest.json │ ├── othertest.mo │ ├── othertest.po │ ├── test.json │ ├── test.mo │ └── test.po └── update_locale.sh /.gitignore: -------------------------------------------------------------------------------- 1 | DDG-Translate-* 2 | .build 3 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for {{$dist->name}} 2 | 3 | {{$NEXT}} 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This license does not apply to any DuckDuckGo logos or marks that may be contained 2 | in this repo. DuckDuckGo logos and marks are licensed separately under the CCBY-NC-ND 4.0 3 | license (https://creativecommons.org/licenses/by-nc-nd/4.0/), and official up-to-date 4 | versions can be downloaded from https://duckduckgo.com/press. 5 | 6 | This software is copyright (c) 2019 by DuckDuckGo, Inc. https://duckduckgo.com, 7 | DuckDuckGo Community 8 | 9 | This is free software; you can redistribute it and/or modify it under 10 | the same terms as the Perl 5 programming language system itself. 11 | 12 | Terms of the Perl programming language system itself 13 | 14 | a) the GNU General Public License as published by the Free 15 | Software Foundation; either version 1, or (at your option) any 16 | later version, or 17 | b) the "Artistic License" 18 | 19 | --- The GNU General Public License, Version 1, February 1989 --- 20 | 21 | This software is Copyright (c) 2011 by Gabriel Weinberg, DuckDuckGo Community 22 | 23 | This is free software, licensed under: 24 | 25 | The GNU General Public License, Version 1, February 1989 26 | 27 | GNU GENERAL PUBLIC LICENSE 28 | Version 1, February 1989 29 | 30 | Copyright (C) 1989 Free Software Foundation, Inc. 31 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 | 33 | Everyone is permitted to copy and distribute verbatim copies 34 | of this license document, but changing it is not allowed. 35 | 36 | Preamble 37 | 38 | The license agreements of most software companies try to keep users 39 | at the mercy of those companies. By contrast, our General Public 40 | License is intended to guarantee your freedom to share and change free 41 | software--to make sure the software is free for all its users. The 42 | General Public License applies to the Free Software Foundation's 43 | software and to any other program whose authors commit to using it. 44 | You can use it for your programs, too. 45 | 46 | When we speak of free software, we are referring to freedom, not 47 | price. Specifically, the General Public License is designed to make 48 | sure that you have the freedom to give away or sell copies of free 49 | software, that you receive source code or can get it if you want it, 50 | that you can change the software or use pieces of it in new free 51 | programs; and that you know you can do these things. 52 | 53 | To protect your rights, we need to make restrictions that forbid 54 | anyone to deny you these rights or to ask you to surrender the rights. 55 | These restrictions translate to certain responsibilities for you if you 56 | distribute copies of the software, or if you modify it. 57 | 58 | For example, if you distribute copies of a such a program, whether 59 | gratis or for a fee, you must give the recipients all the rights that 60 | you have. You must make sure that they, too, receive or can get the 61 | source code. And you must tell them their rights. 62 | 63 | We protect your rights with two steps: (1) copyright the software, and 64 | (2) offer you this license which gives you legal permission to copy, 65 | distribute and/or modify the software. 66 | 67 | Also, for each author's protection and ours, we want to make certain 68 | that everyone understands that there is no warranty for this free 69 | software. If the software is modified by someone else and passed on, we 70 | want its recipients to know that what they have is not the original, so 71 | that any problems introduced by others will not reflect on the original 72 | authors' reputations. 73 | 74 | The precise terms and conditions for copying, distribution and 75 | modification follow. 76 | 77 | GNU GENERAL PUBLIC LICENSE 78 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 79 | 80 | 0. This License Agreement applies to any program or other work which 81 | contains a notice placed by the copyright holder saying it may be 82 | distributed under the terms of this General Public License. The 83 | "Program", below, refers to any such program or work, and a "work based 84 | on the Program" means either the Program or any work containing the 85 | Program or a portion of it, either verbatim or with modifications. Each 86 | licensee is addressed as "you". 87 | 88 | 1. You may copy and distribute verbatim copies of the Program's source 89 | code as you receive it, in any medium, provided that you conspicuously and 90 | appropriately publish on each copy an appropriate copyright notice and 91 | disclaimer of warranty; keep intact all the notices that refer to this 92 | General Public License and to the absence of any warranty; and give any 93 | other recipients of the Program a copy of this General Public License 94 | along with the Program. You may charge a fee for the physical act of 95 | transferring a copy. 96 | 97 | 2. You may modify your copy or copies of the Program or any portion of 98 | it, and copy and distribute such modifications under the terms of Paragraph 99 | 1 above, provided that you also do the following: 100 | 101 | a) cause the modified files to carry prominent notices stating that 102 | you changed the files and the date of any change; and 103 | 104 | b) cause the whole of any work that you distribute or publish, that 105 | in whole or in part contains the Program or any part thereof, either 106 | with or without modifications, to be licensed at no charge to all 107 | third parties under the terms of this General Public License (except 108 | that you may choose to grant warranty protection to some or all 109 | third parties, at your option). 110 | 111 | c) If the modified program normally reads commands interactively when 112 | run, you must cause it, when started running for such interactive use 113 | in the simplest and most usual way, to print or display an 114 | announcement including an appropriate copyright notice and a notice 115 | that there is no warranty (or else, saying that you provide a 116 | warranty) and that users may redistribute the program under these 117 | conditions, and telling the user how to view a copy of this General 118 | Public License. 119 | 120 | d) You may charge a fee for the physical act of transferring a 121 | copy, and you may at your option offer warranty protection in 122 | exchange for a fee. 123 | 124 | Mere aggregation of another independent work with the Program (or its 125 | derivative) on a volume of a storage or distribution medium does not bring 126 | the other work under the scope of these terms. 127 | 128 | 3. You may copy and distribute the Program (or a portion or derivative of 129 | it, under Paragraph 2) in object code or executable form under the terms of 130 | Paragraphs 1 and 2 above provided that you also do one of the following: 131 | 132 | a) accompany it with the complete corresponding machine-readable 133 | source code, which must be distributed under the terms of 134 | Paragraphs 1 and 2 above; or, 135 | 136 | b) accompany it with a written offer, valid for at least three 137 | years, to give any third party free (except for a nominal charge 138 | for the cost of distribution) a complete machine-readable copy of the 139 | corresponding source code, to be distributed under the terms of 140 | Paragraphs 1 and 2 above; or, 141 | 142 | c) accompany it with the information you received as to where the 143 | corresponding source code may be obtained. (This alternative is 144 | allowed only for noncommercial distribution and only if you 145 | received the program in object code or executable form alone.) 146 | 147 | Source code for a work means the preferred form of the work for making 148 | modifications to it. For an executable file, complete source code means 149 | all the source code for all modules it contains; but, as a special 150 | exception, it need not include source code for modules which are standard 151 | libraries that accompany the operating system on which the executable 152 | file runs, or for standard header files or definitions files that 153 | accompany that operating system. 154 | 155 | 4. You may not copy, modify, sublicense, distribute or transfer the 156 | Program except as expressly provided under this General Public License. 157 | Any attempt otherwise to copy, modify, sublicense, distribute or transfer 158 | the Program is void, and will automatically terminate your rights to use 159 | the Program under this License. However, parties who have received 160 | copies, or rights to use copies, from you under this General Public 161 | License will not have their licenses terminated so long as such parties 162 | remain in full compliance. 163 | 164 | 5. By copying, distributing or modifying the Program (or any work based 165 | on the Program) you indicate your acceptance of this license to do so, 166 | and all its terms and conditions. 167 | 168 | 6. Each time you redistribute the Program (or any work based on the 169 | Program), the recipient automatically receives a license from the original 170 | licensor to copy, distribute or modify the Program subject to these 171 | terms and conditions. You may not impose any further restrictions on the 172 | recipients' exercise of the rights granted herein. 173 | 174 | 7. The Free Software Foundation may publish revised and/or new versions 175 | of the General Public License from time to time. Such new versions will 176 | be similar in spirit to the present version, but may differ in detail to 177 | address new problems or concerns. 178 | 179 | Each version is given a distinguishing version number. If the Program 180 | specifies a version number of the license which applies to it and "any 181 | later version", you have the option of following the terms and conditions 182 | either of that version or of any later version published by the Free 183 | Software Foundation. If the Program does not specify a version number of 184 | the license, you may choose any version ever published by the Free Software 185 | Foundation. 186 | 187 | 8. If you wish to incorporate parts of the Program into other free 188 | programs whose distribution conditions are different, write to the author 189 | to ask for permission. For software which is copyrighted by the Free 190 | Software Foundation, write to the Free Software Foundation; we sometimes 191 | make exceptions for this. Our decision will be guided by the two goals 192 | of preserving the free status of all derivatives of our free software and 193 | of promoting the sharing and reuse of software generally. 194 | 195 | NO WARRANTY 196 | 197 | 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 198 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 199 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 200 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 201 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 202 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 203 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 204 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 205 | REPAIR OR CORRECTION. 206 | 207 | 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 208 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 209 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 210 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 211 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 212 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 213 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 214 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 215 | POSSIBILITY OF SUCH DAMAGES. 216 | 217 | END OF TERMS AND CONDITIONS 218 | 219 | Appendix: How to Apply These Terms to Your New Programs 220 | 221 | If you develop a new program, and you want it to be of the greatest 222 | possible use to humanity, the best way to achieve this is to make it 223 | free software which everyone can redistribute and change under these 224 | terms. 225 | 226 | To do so, attach the following notices to the program. It is safest to 227 | attach them to the start of each source file to most effectively convey 228 | the exclusion of warranty; and each file should have at least the 229 | "copyright" line and a pointer to where the full notice is found. 230 | 231 | 232 | Copyright (C) 19yy 233 | 234 | This program is free software; you can redistribute it and/or modify 235 | it under the terms of the GNU General Public License as published by 236 | the Free Software Foundation; either version 1, or (at your option) 237 | any later version. 238 | 239 | This program is distributed in the hope that it will be useful, 240 | but WITHOUT ANY WARRANTY; without even the implied warranty of 241 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 242 | GNU General Public License for more details. 243 | 244 | You should have received a copy of the GNU General Public License 245 | along with this program; if not, write to the Free Software 246 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 247 | 248 | 249 | Also add information on how to contact you by electronic and paper mail. 250 | 251 | If the program is interactive, make it output a short notice like this 252 | when it starts in an interactive mode: 253 | 254 | Gnomovision version 69, Copyright (C) 19xx name of author 255 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 256 | This is free software, and you are welcome to redistribute it 257 | under certain conditions; type `show c' for details. 258 | 259 | The hypothetical commands `show w' and `show c' should show the 260 | appropriate parts of the General Public License. Of course, the 261 | commands you use may be called something other than `show w' and `show 262 | c'; they could even be mouse-clicks or menu items--whatever suits your 263 | program. 264 | 265 | You should also get your employer (if you work as a programmer) or your 266 | school, if any, to sign a "copyright disclaimer" for the program, if 267 | necessary. Here a sample; alter the names: 268 | 269 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 270 | program `Gnomovision' (a program to direct compilers to make passes 271 | at assemblers) written by James Hacker. 272 | 273 | , 1 April 1989 274 | Ty Coon, President of Vice 275 | 276 | That's all there is to it! 277 | 278 | 279 | --- The Artistic License 1.0 --- 280 | 281 | This software is Copyright (c) 2011 by Gabriel Weinberg, DuckDuckGo Community 282 | 283 | This is free software, licensed under: 284 | 285 | The Artistic License 1.0 286 | 287 | The Artistic License 288 | 289 | Preamble 290 | 291 | The intent of this document is to state the conditions under which a Package 292 | may be copied, such that the Copyright Holder maintains some semblance of 293 | artistic control over the development of the package, while giving the users of 294 | the package the right to use and distribute the Package in a more-or-less 295 | customary fashion, plus the right to make reasonable modifications. 296 | 297 | Definitions: 298 | 299 | - "Package" refers to the collection of files distributed by the Copyright 300 | Holder, and derivatives of that collection of files created through 301 | textual modification. 302 | - "Standard Version" refers to such a Package if it has not been modified, 303 | or has been modified in accordance with the wishes of the Copyright 304 | Holder. 305 | - "Copyright Holder" is whoever is named in the copyright or copyrights for 306 | the package. 307 | - "You" is you, if you're thinking about copying or distributing this Package. 308 | - "Reasonable copying fee" is whatever you can justify on the basis of media 309 | cost, duplication charges, time of people involved, and so on. (You will 310 | not be required to justify it to the Copyright Holder, but only to the 311 | computing community at large as a market that must bear the fee.) 312 | - "Freely Available" means that no fee is charged for the item itself, though 313 | there may be fees involved in handling the item. It also means that 314 | recipients of the item may redistribute it under the same conditions they 315 | received it. 316 | 317 | 1. You may make and give away verbatim copies of the source form of the 318 | Standard Version of this Package without restriction, provided that you 319 | duplicate all of the original copyright notices and associated disclaimers. 320 | 321 | 2. You may apply bug fixes, portability fixes and other modifications derived 322 | from the Public Domain or from the Copyright Holder. A Package modified in such 323 | a way shall still be considered the Standard Version. 324 | 325 | 3. You may otherwise modify your copy of this Package in any way, provided that 326 | you insert a prominent notice in each changed file stating how and when you 327 | changed that file, and provided that you do at least ONE of the following: 328 | 329 | a) place your modifications in the Public Domain or otherwise make them 330 | Freely Available, such as by posting said modifications to Usenet or an 331 | equivalent medium, or placing the modifications on a major archive site 332 | such as ftp.uu.net, or by allowing the Copyright Holder to include your 333 | modifications in the Standard Version of the Package. 334 | 335 | b) use the modified Package only within your corporation or organization. 336 | 337 | c) rename any non-standard executables so the names do not conflict with 338 | standard executables, which must also be provided, and provide a separate 339 | manual page for each non-standard executable that clearly documents how it 340 | differs from the Standard Version. 341 | 342 | d) make other distribution arrangements with the Copyright Holder. 343 | 344 | 4. You may distribute the programs of this Package in object code or executable 345 | form, provided that you do at least ONE of the following: 346 | 347 | a) distribute a Standard Version of the executables and library files, 348 | together with instructions (in the manual page or equivalent) on where to 349 | get the Standard Version. 350 | 351 | b) accompany the distribution with the machine-readable source of the Package 352 | with your modifications. 353 | 354 | c) accompany any non-standard executables with their corresponding Standard 355 | Version executables, giving the non-standard executables non-standard 356 | names, and clearly documenting the differences in manual pages (or 357 | equivalent), together with instructions on where to get the Standard 358 | Version. 359 | 360 | d) make other distribution arrangements with the Copyright Holder. 361 | 362 | 5. You may charge a reasonable copying fee for any distribution of this 363 | Package. You may charge any fee you choose for support of this Package. You 364 | may not charge a fee for this Package itself. However, you may distribute this 365 | Package in aggregate with other (possibly commercial) programs as part of a 366 | larger (possibly commercial) software distribution provided that you do not 367 | advertise this Package as a product of your own. 368 | 369 | 6. The scripts and library files supplied as input to or produced as output 370 | from the programs of this Package do not automatically fall under the copyright 371 | of this Package, but belong to whomever generated them, and may be sold 372 | commercially, and may be aggregated with this Package. 373 | 374 | 7. C or perl subroutines supplied by you and linked into this Package shall not 375 | be considered part of this Package. 376 | 377 | 8. The name of the Copyright Holder may not be used to endorse or promote 378 | products derived from this software without specific prior written permission. 379 | 380 | 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 381 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 382 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 383 | 384 | The End 385 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # duckduckgo-translate 2 | This is the DuckDuckGo Translation library that handles translation tokens sent from the Duck.co website. This library also helps DDG and the community translate DuckDuckGo micro-sites and other services. 3 | 4 | This has been purpose-built for DuckDuckGo, it is not intended for general use. 5 | -------------------------------------------------------------------------------- /bin/po2json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | # Copyright (C) 2008, Joshua I. Miller Eunrtst@cpan.orgE, all 4 | # rights reserved. 5 | # 6 | # This program is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Library General Public License as published 8 | # by the Free Software Foundation; either version 2, or (at your option) 9 | # any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # Library General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Library General Public 17 | # License along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 | # USA. 20 | 21 | 22 | use strict; 23 | use JSON; 24 | use Locale::PO; 25 | use File::Basename qw(basename); 26 | 27 | my $gettext_context_glue = "\004"; 28 | 29 | sub usage { 30 | return "$0 {-p} {file.po} > {outputfile.json} 31 | -p : do pretty-printing of json data\n"; 32 | } 33 | 34 | &main; 35 | 36 | sub main 37 | { 38 | my ($src_fh, $src); 39 | 40 | my $pretty = 0; 41 | if ($ARGV[0] =~ /^--?p$/) { 42 | shift @ARGV; 43 | $pretty = 1; 44 | } 45 | 46 | if (length($ARGV[0])) 47 | { 48 | if ($ARGV[0] =~ /^-h/) { 49 | print &usage; 50 | exit 1; 51 | } 52 | 53 | unless (-r $ARGV[0]) { 54 | print "ERROR: Unable to read file [$ARGV[0]]\n"; 55 | die &usage; 56 | } 57 | 58 | $src = $ARGV[0]; 59 | } else { 60 | die &usage; 61 | } 62 | 63 | # we'll be building this data struct 64 | my $json = {}; 65 | 66 | my $plural_form_count; 67 | # get po object stack 68 | my $pos = Locale::PO->load_file_asarray($src) or die "Can't parse po file [$src]."; 69 | 70 | 71 | foreach my $po (@$pos) 72 | { 73 | my $qmsgid1 = $po->msgid; 74 | my $msgid1 = $po->dequote( $qmsgid1 ); 75 | 76 | # on the header 77 | if (length($msgid1) == 0) 78 | { 79 | my $qmsgstr = $po->msgstr; 80 | my $cur = $po->dequote( $qmsgstr ); 81 | my %cur; 82 | foreach my $h (split(/\\n/, $cur)) 83 | { 84 | next unless length($h); 85 | my @h = split(':', $h, 2); 86 | 87 | if (length($cur{$h[0]})) { 88 | warn "SKIPPING DUPLICATE HEADER LINE: $h\n"; 89 | } elsif ($h[0] =~ /#-#-#-#-#/) { 90 | warn "SKIPPING ERROR MARKER IN HEADER: $h\n"; 91 | } elsif (@h == 2) { 92 | $cur{$h[0]} = $h[1]; 93 | } else { 94 | warn "PROBLEM LINE IN HEADER: $h\n"; 95 | $cur{$h} = ''; 96 | } 97 | } 98 | 99 | # init header ref 100 | $$json{''} ||= {}; 101 | 102 | # populate header ref 103 | foreach my $key (keys %cur) { 104 | $$json{''}{$key} = length($cur{$key}) ? $cur{$key} : ''; 105 | } 106 | 107 | # save plural form count 108 | if ($$json{''}{'Plural-Forms'}) { 109 | my $t = $$json{''}{'Plural-Forms'}; 110 | $t =~ s/^\s*//; 111 | if ($t =~ /nplurals=(\d+)/) { 112 | $plural_form_count = $1; 113 | } else { 114 | die "ERROR parsing plural forms header [$t]\n"; 115 | } 116 | } else { 117 | warn "NO PLURAL FORM HEADER FOUND - DEFAULTING TO 2\n"; 118 | # just default to 2 119 | $plural_form_count = 2; 120 | } 121 | 122 | # on a normal msgid 123 | } else { 124 | my $qmsgctxt = $po->msgctxt; 125 | my $msgctxt = $po->dequote($qmsgctxt) if $qmsgctxt; 126 | 127 | # build the new msgid key 128 | my $msg_ctxt_id = defined($msgctxt) ? join($gettext_context_glue, ($msgctxt, $msgid1)) : $msgid1; 129 | 130 | # build translation side 131 | my @trans; 132 | 133 | # msgid plural side 134 | my $qmsgid_plural = $po->msgid_plural; 135 | my $msgid2 = $po->dequote( $qmsgid_plural ) if $qmsgid_plural; 136 | push(@trans, $msgid2); 137 | 138 | # translated string 139 | # this shows up different if we're plural 140 | if (defined($msgid2) && length($msgid2)) 141 | { 142 | my $plurals = $po->msgstr_n; 143 | for (my $i=0; $i<$plural_form_count; $i++) 144 | { 145 | my $qstr = ref($plurals) ? $$plurals{$i} : undef; 146 | my $str = $po->dequote( $qstr ) if $qstr; 147 | push(@trans, $str); 148 | } 149 | 150 | # singular 151 | } else { 152 | my $qmsgstr = $po->msgstr; 153 | my $msgstr = $po->dequote( $qmsgstr ) if $qmsgstr; 154 | push(@trans, $msgstr); 155 | } 156 | 157 | $$json{$msg_ctxt_id} = \@trans; 158 | } 159 | } 160 | 161 | 162 | my $jsonobj = new JSON; 163 | my $basename = basename($src); 164 | $basename =~ s/\.pot?$//; 165 | if ($pretty) 166 | { 167 | print $jsonobj->pretty->encode( { $basename => $json }); 168 | } else { 169 | print $jsonobj->encode($json); 170 | } 171 | } 172 | 173 | =head1 NAME 174 | 175 | po2json - Convert a Uniforum format portable object file to javascript object notation. 176 | 177 | =head1 SYNOPSIS 178 | 179 | po2json /path/to/domain.po > domain.json 180 | 181 | =head1 DESCRIPTION 182 | 183 | This takes a PO file, as is created from GNU Gettext's xgettext, and converts it into a JSON file. 184 | 185 | The output is an annonymous associative array. So, if you plan to load this via a 29 | 54 | 55 | var gt = new Gettext({ "domain" : "myDomain" }); 56 | // rest is the same 57 | 58 | 59 | // ////////////////////////////////////////////////////////// 60 | // The reson the shortcuts aren't exported by default is because they'd be 61 | // glued to the single domain you created. So, if you're adding i18n support 62 | // to some js library, you should use it as so: 63 | 64 | if (typeof(MyNamespace) == 'undefined') MyNamespace = {}; 65 | MyNamespace.MyClass = function () { 66 | var gtParms = { "domain" : 'MyNamespace_MyClass' }; 67 | this.gt = new Gettext(gtParams); 68 | return this; 69 | }; 70 | MyNamespace.MyClass.prototype._ = function (msgid) { 71 | return this.gt.gettext(msgid); 72 | }; 73 | MyNamespace.MyClass.prototype.something = function () { 74 | var myString = this._("this will get translated"); 75 | }; 76 | 77 | // ////////////////////////////////////////////////////////// 78 | // Adding the shortcuts to a global scope is easier. If that's 79 | // ok in your app, this is certainly easier. 80 | var myGettext = new Gettext({ 'domain' : 'myDomain' }); 81 | function _ (msgid) { 82 | return myGettext.gettext(msgid); 83 | } 84 | alert( _("text") ); 85 | 86 | // ////////////////////////////////////////////////////////// 87 | // Data structure of the json data 88 | // NOTE: if you're loading via the 123 | 124 | // in domain.json 125 | json_locale_data = { 126 | "mydomain" : { 127 | // po header fields 128 | "" : { 129 | "plural-forms" : "...", 130 | "lang" : "en", 131 | }, 132 | // all the msgid strings and translations 133 | "msgid" : [ "msgid_plural", "translation", "plural_translation" ], 134 | }, 135 | }; 136 | // please see the included bin/po2json script for the details on this format 137 | 138 | This method also allows you to use unsupported file formats, so long as you can parse them into the above format. 139 | 140 | =item 2. Use AJAX to load language file. 141 | 142 | Use XMLHttpRequest (actually, SJAX - syncronous) to load an external resource. 143 | 144 | Supported external formats are: 145 | 146 | =over 147 | 148 | =item * Javascript Object Notation (.json) 149 | 150 | (see bin/po2json) 151 | 152 | type=application/json 153 | 154 | =item * Uniforum Portable Object (.po) 155 | 156 | (see GNU Gettext's xgettext) 157 | 158 | type=application/x-po 159 | 160 | =item * Machine Object (compiled .po) (.mo) 161 | 162 | NOTE: .mo format isn't actually supported just yet, but support is planned. 163 | 164 | (see GNU Gettext's msgfmt) 165 | 166 | type=application/x-mo 167 | 168 | =back 169 | 170 | =back 171 | 172 | =head1 METHODS 173 | 174 | The following methods are implemented: 175 | 176 | new Gettext(args) 177 | textdomain (domain) 178 | gettext (msgid) 179 | dgettext (domainname, msgid) 180 | dcgettext (domainname, msgid, LC_MESSAGES) 181 | ngettext (msgid, msgid_plural, count) 182 | dngettext (domainname, msgid, msgid_plural, count) 183 | dcngettext (domainname, msgid, msgid_plural, count, LC_MESSAGES) 184 | pgettext (msgctxt, msgid) 185 | dpgettext (domainname, msgctxt, msgid) 186 | dcpgettext (domainname, msgctxt, msgid, LC_MESSAGES) 187 | npgettext (msgctxt, msgid, msgid_plural, count) 188 | dnpgettext (domainname, msgctxt, msgid, msgid_plural, count) 189 | dcnpgettext (domainname, msgctxt, msgid, msgid_plural, count, LC_MESSAGES) 190 | strargs (string, args_array) 191 | 192 | 193 | =head2 new Gettext (args) 194 | 195 | Several methods of loading locale data are included. You may specify a plugin or alternative method of loading data by passing the data in as the "locale_data" option. For example: 196 | 197 | var get_locale_data = function () { 198 | // plugin does whatever to populate locale_data 199 | return locale_data; 200 | }; 201 | var gt = new Gettext( 'domain' : 'messages', 202 | 'locale_data' : get_locale_data() ); 203 | 204 | The above can also be used if locale data is specified in a statically included 4 | 5 | 6 | 29 | 30 | 31 |

ddg_translate.js Translation Dryrun Test

32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /t/data/ddg_translate_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 31 | 32 | 33 |

ddg_translate.js Translation Test

34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /t/data/gettext_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 30 | 31 | 32 |

Gettext.js Translation Test

33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/othertest.json: -------------------------------------------------------------------------------- 1 | {"":{"Plural-Forms":" nplurals=2; plural=n != 1;","MIME-Version":" 1.0","POT-Creation-Date":" 2009-06-14 09:29-0400","Language":" de_DE","Last-Translator":" Community","Content-Type":" text/plain; charset=UTF-8","Language-Team":" DuckDuckGo Community ","PO-Revision-Date":" 2009-06-14 09:29-0400","Content-Transfer-Encoding":" 8bit","Project-Id-Version":" DuckDuckGo-Translation-0.000"},"Other":[null,"Anderes"],"Umlaut-Test":[null,"Dies ist ein Ümläut"],"Hello":[null,"Anderes Hallo"],"Change order test %s %s":[null,"Ganz andere Reihenfolge hier %2$s %1$s"],"You have %d message":["You have %d messages","Du hast %d AndereNachricht","Du hast %d AndereNachrichten"]} -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/othertest.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckduckgo/duckduckgo-translate/6e03421d21a4bd4e829822fc65faf6ecd51bff2f/t/data/locale/de_DE/LC_MESSAGES/othertest.mo -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/othertest.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: DuckDuckGo-Translation-0.000\n" 4 | "Last-Translator: Community\n" 5 | "Language-Team: DuckDuckGo Community \n" 6 | "POT-Creation-Date: 2009-06-14 09:29-0400\n" 7 | "PO-Revision-Date: 2009-06-14 09:29-0400\n" 8 | "Language: de_DE\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "Plural-Forms: nplurals=2; plural=n != 1;" 13 | 14 | msgid "You have %d message" 15 | msgid_plural "You have %d messages" 16 | msgstr[0] "Du hast %d AndereNachricht" 17 | msgstr[1] "Du hast %d AndereNachrichten" 18 | 19 | msgid "Hello" 20 | msgstr "Anderes Hallo" 21 | 22 | msgid "Umlaut-Test" 23 | msgstr "Dies ist ein Ümläut" 24 | 25 | msgid "Change order test %s %s" 26 | msgstr "Ganz andere Reihenfolge hier %2$s %1$s" 27 | 28 | msgid "Other" 29 | msgstr "Anderes" 30 | -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/test.json: -------------------------------------------------------------------------------- 1 | locale_data['test'] = {"":{"Plural-Forms":" nplurals=2; plural=n != 1;","MIME-Version":" 1.0","POT-Creation-Date":" 2009-06-14 09:29-0400","Language":" de_DE","Last-Translator":" Community","Content-Type":" text/plain; charset=UTF-8","Language-Team":" DuckDuckGo Community ","PO-Revision-Date":" 2009-06-14 09:29-0400","Content-Transfer-Encoding":" 8bit","Project-Id-Version":" DuckDuckGo-Translation-0.000"},"Hello":[null,"Hallo"],"Change order test %s %s":[null,"Andere Reihenfolge hier %2$s %1$s"],"You have %d message of %s":["You have %d messages of %s","Du hast %d Nachricht von %s","Du hast %d Nachrichten von %s"],"You have %d message":["You have %d messages","Du hast %d Nachricht","Du hast %d Nachrichten"]}; 2 | -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/test.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duckduckgo/duckduckgo-translate/6e03421d21a4bd4e829822fc65faf6ecd51bff2f/t/data/locale/de_DE/LC_MESSAGES/test.mo -------------------------------------------------------------------------------- /t/data/locale/de_DE/LC_MESSAGES/test.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: DuckDuckGo-Translation-0.000\n" 4 | "Last-Translator: Community\n" 5 | "Language-Team: DuckDuckGo Community \n" 6 | "POT-Creation-Date: 2009-06-14 09:29-0400\n" 7 | "PO-Revision-Date: 2009-06-14 09:29-0400\n" 8 | "Language: de_DE\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "Plural-Forms: nplurals=2; plural=n != 1;" 13 | 14 | msgid "You have %d message" 15 | msgid_plural "You have %d messages" 16 | msgstr[0] "Du hast %d Nachricht" 17 | msgstr[1] "Du hast %d Nachrichten" 18 | 19 | msgid "You have %d message of %s" 20 | msgid_plural "You have %d messages of %s" 21 | msgstr[0] "Du hast %d Nachricht von %s" 22 | msgstr[1] "Du hast %d Nachrichten von %s" 23 | 24 | msgid "Hello" 25 | msgstr "Hallo" 26 | 27 | msgid "Change order test %s %s" 28 | msgstr "Andere Reihenfolge hier %2$s %1$s" 29 | -------------------------------------------------------------------------------- /t/data/update_locale.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BASE=$(dirname $0) 4 | 5 | for domain in test othertest 6 | do 7 | msgfmt -o $BASE/locale/de_DE/LC_MESSAGES/$domain.mo $BASE/locale/de_DE/LC_MESSAGES/$domain.po 8 | echo -n "locale_data['$domain'] = " >$BASE/locale/de_DE/LC_MESSAGES/$domain.json 9 | $BASE/../../share/js/gettext/po2json $BASE/locale/de_DE/LC_MESSAGES/$domain.po >>$BASE/locale/de_DE/LC_MESSAGES/$domain.json 10 | echo ";" >>$BASE/locale/de_DE/LC_MESSAGES/$domain.json 11 | done 12 | --------------------------------------------------------------------------------